diff --git a/include/cdio/iso9660.h b/include/cdio/iso9660.h index b2167eaf..dca597d6 100644 --- a/include/cdio/iso9660.h +++ b/include/cdio/iso9660.h @@ -1,5 +1,5 @@ /* - $Id: iso9660.h,v 1.69 2005/02/20 10:21:01 rocky Exp $ + $Id: iso9660.h,v 1.70 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -526,7 +526,7 @@ PRAGMA_END_PACKED @see iso9660_dir */ struct iso9660_stat_s { /* big endian!! */ - bool_3way_t b_rock; /**< has Rock Ridge extension. + bool_3way_t b3_rock; /**< has Rock Ridge extension. If not true then the next 9 fields aren't used. */ @@ -535,8 +535,11 @@ struct iso9660_stat_s { /* big endian!! */ posix_uid_t st_uid; /**< user ID of owner */ posix_gid_t st_gid; /**< group ID of owner */ uint8_t s_rock_offset; - int i_size; /**< FIXME: Is this one of the - size fields below? */ + int i_symlink; /**< size of psz_symlink */ + int i_symlink_max; /**< max allocated to psz_symlink */ + char *psz_symlink; /**< if symbolic link, name + of pointed to file. + */ struct tm atime; /**< time of last access */ struct tm mtime; /**< time of last modification */ struct tm ctime; /**< create time */ diff --git a/include/cdio/rock.h b/include/cdio/rock.h index 8ad1b54b..0807d7f8 100644 --- a/include/cdio/rock.h +++ b/include/cdio/rock.h @@ -1,5 +1,5 @@ /* - $Id: rock.h,v 1.4 2005/02/20 16:21:06 rocky Exp $ + $Id: rock.h,v 1.5 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2005 Rocky Bernstein @@ -156,8 +156,8 @@ typedef enum { #define ISO_ROCK_SL_ROOT 8 typedef struct iso_rock_sl_part_s { - unsigned char flags; - unsigned char len; + uint8_t flags; + uint8_t len; char text[EMPTY_ARRAY_SIZE]; } GNUC_PACKED iso_rock_sl_part_t ; diff --git a/lib/iso9660/iso9660_fs.c b/lib/iso9660/iso9660_fs.c index 247e959b..86b99507 100644 --- a/lib/iso9660/iso9660_fs.c +++ b/lib/iso9660/iso9660_fs.c @@ -1,5 +1,5 @@ /* - $Id: iso9660_fs.c,v 1.22 2005/02/20 17:47:01 rocky Exp $ + $Id: iso9660_fs.c,v 1.23 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -52,7 +52,7 @@ #include -static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.22 2005/02/20 17:47:01 rocky Exp $"; +static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.23 2005/02/21 02:02:12 rocky Exp $"; /* Implementation of iso9660_t type */ struct _iso9660_s { @@ -811,7 +811,7 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, p_stat->lsn = from_733 (p_iso9660_dir->extent); p_stat->size = from_733 (p_iso9660_dir->size); p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE); - p_stat->b_rock = dunno; /*FIXME should do based on mask */ + p_stat->b3_rock = dunno; /*FIXME should do based on mask */ { char rr_fname[256] = ""; @@ -852,6 +852,7 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm)); if (dir_len < sizeof (iso9660_dir_t)) { + free(p_stat->psz_symlink); free(p_stat); return NULL; } @@ -1047,7 +1048,7 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, cmp = strcmp(splitpath[0], p_stat->filename); - if ( 0 != cmp && 0 == p_env->i_joliet_level && yep != p_stat->b_rock ) { + if ( 0 != cmp && 0 == p_env->i_joliet_level && yep != p_stat->b3_rock ) { char *trans_fname = NULL; unsigned int i_trans_fname=strlen(p_stat->filename); int trans_len; @@ -1069,11 +1070,13 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, if (!cmp) { iso9660_stat_t *ret_stat = _fs_stat_traverse (p_cdio, p_stat, &splitpath[1]); + free(p_stat->psz_symlink); free(p_stat); free (_dirbuf); return ret_stat; } + free(p_stat->psz_symlink); free(p_stat); offset += iso9660_get_dir_len(p_iso9660_dir); @@ -1137,7 +1140,7 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, cmp = strcmp(splitpath[0], p_stat->filename); - if ( 0 != cmp && 0 == p_iso->i_joliet_level && yep != p_stat->b_rock ) { + if ( 0 != cmp && 0 == p_iso->i_joliet_level && yep != p_stat->b3_rock ) { char *trans_fname = malloc(strlen(p_stat->filename)+1); int trans_len; @@ -1155,11 +1158,13 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, if (!cmp) { iso9660_stat_t *ret_stat = _fs_iso_stat_traverse (p_iso, p_stat, &splitpath[1]); + free(p_stat->psz_symlink); free(p_stat); free (_dirbuf); return ret_stat; } + free(p_stat->psz_symlink); free(p_stat); offset += iso9660_get_dir_len(p_iso9660_dir); @@ -1244,7 +1249,7 @@ iso9660_ifs_stat (iso9660_t *p_iso, const char psz_path[]) splitpath = _cdio_strsplit (psz_path, '/'); stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath); free(p_root); - /*** FIXME _cdio_strfreev (splitpath); ***/ + _cdio_strfreev (splitpath); return stat; } @@ -1293,6 +1298,7 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { + free(p_stat->psz_symlink); free(p_stat); return NULL; } @@ -1357,6 +1363,7 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { + free(p_stat->psz_symlink); free(p_stat); return NULL; } diff --git a/lib/iso9660/rock.c b/lib/iso9660/rock.c index b420140a..b3672a01 100644 --- a/lib/iso9660/rock.c +++ b/lib/iso9660/rock.c @@ -1,5 +1,5 @@ /* - $Id: rock.c,v 1.7 2005/02/20 17:47:01 rocky Exp $ + $Id: rock.c,v 1.8 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2005 Rocky Bernstein Adapted from GNU/Linux fs/isofs/rock.c (C) 1992, 1993 Eric Youngdale @@ -41,6 +41,33 @@ #include #include + +/* Our own realloc routine tailored for the iso9660_stat_t symlink + field. I can't figure out how to make realloc() work without + valgrind complaint. +*/ +static bool +realloc_symlink(/*in/out*/ iso9660_stat_t *p_stat, uint8_t i_grow) +{ + if (!p_stat->i_symlink) { + p_stat->psz_symlink = (char *) calloc(1, 2*i_grow+1); + return (NULL != p_stat->psz_symlink); + } else { + unsigned int i_needed = p_stat->i_symlink + i_grow ; + if ( i_needed <= p_stat->i_symlink_max) + return true; + else { + char * psz_newsymlink = (char *) calloc(1, 2*i_needed); + if (!psz_newsymlink) return false; + p_stat->i_symlink_max = 2*i_needed; + memcpy(psz_newsymlink, p_stat->psz_symlink, p_stat->i_symlink); + free(p_stat->psz_symlink); + p_stat->psz_symlink = psz_newsymlink; + return true; + } + } +} + /* These functions are designed to read the system areas of a directory record * and extract relevant information. There are different functions provided * depending upon what information we need at the time. One function fills @@ -90,22 +117,25 @@ */ int get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, - /*out*/ char * psz_name, iso9660_stat_t *p_stat) + /*out*/ char * psz_name, + /*in/out*/ iso9660_stat_t *p_stat) { int len; unsigned char *chr; + int symlink_len = 0; CONTINUE_DECLS; int i_namelen = 0; int truncate=0; - if (!p_stat || nope == p_stat->b_rock) return 0; + if (!p_stat || nope == p_stat->b3_rock) return 0; *psz_name = 0; SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); - /* repeat:*/ + /*repeat:*/ { iso_extension_record_t * rr; int sig; + int rootflag; while (len > 1){ /* There may be one byte for padding somewhere */ rr = (iso_extension_record_t *) chr; @@ -128,8 +158,17 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, } CHECK_CE; break; + case SIG('E','R'): + p_stat->b3_rock = yep; + cdio_debug("ISO 9660 Extensions: "); + { + int p; + for(p=0;pu.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); + } + break; case SIG('N','M'): - p_stat->b_rock = yep; + /* Alternate name */ + p_stat->b3_rock = yep; if (truncate) break; if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) { i_namelen = sizeof(".."); @@ -153,16 +192,80 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, i_namelen += rr->len - 5; break; case SIG('P','X'): + /* POSIX file attributes */ p_stat->st_mode = from_733(rr->u.PX.st_mode); p_stat->st_nlinks = from_733(rr->u.PX.st_nlinks); p_stat->st_uid = from_733(rr->u.PX.st_uid); p_stat->st_gid = from_733(rr->u.PX.st_gid); - p_stat->b_rock = yep; + p_stat->b3_rock = yep; + break; + case SIG('S','L'): + { + /* Symbolic link */ + uint8_t slen; + iso_rock_sl_part_t * p_sl; + iso_rock_sl_part_t * p_oldsl; + slen = rr->len - 5; + p_sl = &rr->u.SL.link; + p_stat->i_symlink = symlink_len; + while (slen > 1){ + rootflag = 0; + switch(p_sl->flags &~1){ + case 0: + realloc_symlink(p_stat, p_sl->len); + memcpy(&(p_stat->psz_symlink[p_stat->i_symlink]), + p_sl->text, p_sl->len); + p_stat->i_symlink += p_sl->len; + break; + case 4: + realloc_symlink(p_stat, 1); + p_stat->psz_symlink[p_stat->i_symlink++] = '.'; + p_stat->i_symlink++; + /* continue into next case. */ + break; + case 2: + realloc_symlink(p_stat, 1); + p_stat->psz_symlink[p_stat->i_symlink++] = '.'; + p_stat->i_symlink++; + break; + case 8: + rootflag = 1; + realloc_symlink(p_stat, 1); + p_stat->psz_symlink[p_stat->i_symlink++] = '/'; + p_stat->i_symlink++; + break; + default: + cdio_warn("Symlink component flag not implemented"); + } + slen -= p_sl->len + 2; + p_oldsl = p_sl; + p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); + + if(slen < 2) { + if (((rr->u.SL.flags & 1) != 0) + && ((p_oldsl->flags & 1) == 0) ) p_stat->i_symlink += 1; + break; + } + + /* + * If this component record isn't continued, then append a '/'. + */ + if (!rootflag && (p_oldsl->flags & 1) == 0) { + realloc_symlink(p_stat, 1); + p_stat->psz_symlink[p_stat->i_symlink++] = '/'; + p_stat->i_symlink++; + } + } + } + symlink_len = p_stat->i_symlink; + realloc_symlink(p_stat, 1); + p_stat->psz_symlink[symlink_len]='\0'; break; case SIG('R','E'): free(buffer); return -1; case SIG('T','F'): + /* Time stamp(s) for a file */ { #ifdef TIME_FIXED int cnt = 0; /* Rock ridge never appears on a High Sierra disk */ @@ -187,7 +290,7 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, p_stat->st_ctime = rr->u.TF.times[cnt++].time; } #endif - p_stat->b_rock = yep; + p_stat->b3_rock = yep; break; } default: @@ -211,7 +314,7 @@ parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, int symlink_len = 0; CONTINUE_DECLS; - if (nope == p_stat->b_rock) return 0; + if (nope == p_stat->b3_rock) return 0; SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); if (regard_xa) @@ -242,7 +345,7 @@ parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, CHECK_CE; break; case SIG('E','R'): - p_stat->b_rock = yep; + p_stat->b3_rock = yep; cdio_debug("ISO 9660 Extensions: "); { int p; for(p=0;pu.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); @@ -302,49 +405,57 @@ parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, } #endif case SIG('S','L'): - {int slen; - iso_rock_sl_part_t *slp; - iso_rock_sl_part_t *oldslp; + /* Symbolic link. */ + { + int slen; + iso_rock_sl_part_t *p_sl; + iso_rock_sl_part_t *p_oldsl; slen = rr->len - 5; - slp = &rr->u.SL.link; - p_stat->i_size = symlink_len; + p_sl = &rr->u.SL.link; + p_stat->i_symlink = symlink_len; while (slen > 1){ rootflag = 0; - switch(slp->flags &~1){ + switch(p_sl->flags &~1){ case 0: - p_stat->i_size += slp->len; - break; - case 2: - p_stat->i_size += 1; + p_stat->i_symlink += p_sl->len; + /*memcpy(psz_rsymlink, p_sl->text, p_sl->len); + psz_rsymlink+=p_sl->len;*/ break; case 4: - p_stat->i_size += 2; + /**psz_rsymlink++='.';*/ + p_stat->i_symlink++; + /* continue into next case. */ + break; + case 2: + /**psz_rsymlink++='.';*/ + p_stat->i_symlink++; break; case 8: rootflag = 1; - p_stat->i_size += 1; + /**rootflag = 1;*/ + p_stat->i_symlink += 1; break; default: cdio_info("Symlink component flag not implemented"); } - slen -= slp->len + 2; - oldslp = slp; - slp = (iso_rock_sl_part_t *) (((char *) slp) + slp->len + 2); + slen -= p_sl->len + 2; + p_oldsl = p_sl; + p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2); if(slen < 2) { if( ((rr->u.SL.flags & 1) != 0) - && ((oldslp->flags & 1) == 0) ) p_stat->i_size += 1; + && ((p_oldsl->flags & 1) == 0) ) p_stat->i_symlink += 1; break; } /* * If this component record isn't continued, then append a '/'. */ - if (!rootflag && (oldslp->flags & 1) == 0) - p_stat->i_size += 1; + if (!rootflag && (p_oldsl->flags & 1) == 0) + p_stat->i_symlink += 1; } } - symlink_len = p_stat->i_size; + symlink_len = p_stat->i_symlink; break; case SIG('R','E'): cdio_warn("Attempt to read p_stat for relocated directory"); @@ -361,12 +472,12 @@ parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir, p_stat->st_nlinks = reloc->st_nlinks; p_stat->st_uid = reloc->st_uid; p_stat->st_gid = reloc->st_gid; - p_stat->i_rdev = reloc->i_rdev; - p_stat->i_size = reloc->i_size; - p_stat->i_blocks = reloc->i_blocks; - p_stat->i_atime = reloc->i_atime; - p_stat->i_ctime = reloc->i_ctime; - p_stat->i_mtime = reloc->i_mtime; + p_stat->i_rdev = reloc->i_rdev; + p_stat->i_symlink = reloc->i_symlink; + p_stat->i_blocks = reloc->i_blocks; + p_stat->i_atime = reloc->i_atime; + p_stat->i_ctime = reloc->i_ctime; + p_stat->i_mtime = reloc->i_mtime; iput(reloc); } break; @@ -392,7 +503,7 @@ parse_rock_ridge_stat(iso9660_dir_t *p_iso9660_dir, result = parse_rock_ridge_stat_internal(p_iso9660_dir, p_stat, 0); /* if Rock-Ridge flag was reset and we didn't look for attributes * behind eventual XA attributes, have a look there */ - if (0xFF == p_stat->s_rock_offset && nope != p_stat->b_rock) { + if (0xFF == p_stat->s_rock_offset && nope != p_stat->b3_rock) { result = parse_rock_ridge_stat_internal(p_iso9660_dir, p_stat, 14); } return result; diff --git a/src/cd-info.c b/src/cd-info.c index 93619907..c3b73ce7 100644 --- a/src/cd-info.c +++ b/src/cd-info.c @@ -1,5 +1,5 @@ /* - $Id: cd-info.c,v 1.117 2005/02/20 16:21:06 rocky Exp $ + $Id: cd-info.c,v 1.118 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 1996, 1997, 1998 Gerd Knorr @@ -600,7 +600,7 @@ print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[], char _fullname[4096] = { 0, }; char translated_name[MAX_ISONAME+1]; - if (yep != p_statbuf->b_rock || 1 == opts.no_rock_ridge) { + if (yep != p_statbuf->b3_rock || 1 == opts.no_rock_ridge) { iso9660_name_translate_ext(psz_iso_name, translated_name, i_joliet_level); } @@ -618,6 +618,10 @@ print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[], print_fs_attrs(p_statbuf, 0 == opts.no_rock_ridge, fs & CDIO_FS_ANAL_XA, psz_iso_name, translated_name); + if (p_statbuf->i_symlink) { + free(p_statbuf->psz_symlink); + p_statbuf->i_symlink = 0; + } } _cdio_list_free (p_entlist, true); diff --git a/src/iso-info.c b/src/iso-info.c index 05bfacb1..d3f0d088 100644 --- a/src/iso-info.c +++ b/src/iso-info.c @@ -1,5 +1,5 @@ /* - $Id: iso-info.c,v 1.26 2005/02/20 16:21:06 rocky Exp $ + $Id: iso-info.c,v 1.27 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein @@ -199,35 +199,40 @@ print_iso9660_recurse (iso9660_t *p_iso, const char pathname[]) _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *p_statbuf = _cdio_list_node_data (entnode); - char *iso_name = p_statbuf->filename; + char *psz_iso_name = p_statbuf->filename; char _fullname[4096] = { 0, }; char translated_name[MAX_ISONAME+1]; - if (yep != p_statbuf->b_rock || 1 == opts.no_rock_ridge) { - iso9660_name_translate_ext(iso_name, translated_name, i_joliet_level); + if (yep != p_statbuf->b3_rock || 1 == opts.no_rock_ridge) { + iso9660_name_translate_ext(psz_iso_name, translated_name, + i_joliet_level); snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, translated_name); } else { snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, - iso_name); + psz_iso_name); } strncat (_fullname, "/", sizeof (_fullname)); if (p_statbuf->type == _STAT_DIR - && strcmp (iso_name, ".") - && strcmp (iso_name, "..")) + && strcmp (psz_iso_name, ".") + && strcmp (psz_iso_name, "..")) _cdio_list_append (dirlist, strdup (_fullname)); if (opts.print_iso9660) { print_fs_attrs(p_statbuf, 0 == opts.no_rock_ridge, iso9660_ifs_is_xa(p_iso) && 0 == opts.no_xa, - iso_name, translated_name); + psz_iso_name, translated_name); } else - if ( strcmp (iso_name, ".") && strcmp (iso_name, "..")) + if ( strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, "..")) printf("%9u %s%s\n", p_statbuf->size, pathname, - yep == p_statbuf->b_rock ? iso_name : translated_name); + yep == p_statbuf->b3_rock ? psz_iso_name : translated_name); + if (p_statbuf->i_symlink) { + free(p_statbuf->psz_symlink); + p_statbuf->i_symlink = 0; + } } _cdio_list_free (entlist, true); @@ -275,9 +280,9 @@ init(void) #define print_vd_info(title, fn) \ if (fn(p_iso, &psz_str)) { \ printf(title ": %s\n", psz_str); \ - free(psz_str); \ - psz_str = NULL; \ - } + } \ + free(psz_str); \ + psz_str = NULL; /* ------------------------------------------------------------------------ */ diff --git a/src/util.c b/src/util.c index 5e2cd3b8..20e7d920 100644 --- a/src/util.c +++ b/src/util.c @@ -1,5 +1,5 @@ /* - $Id: util.c,v 1.40 2005/02/20 16:21:06 rocky Exp $ + $Id: util.c,v 1.41 2005/02/21 02:02:12 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -24,6 +24,10 @@ #include #include +#ifdef HAVE_SYS_STAT_H +# include +#endif + cdio_log_handler_t gl_default_cdio_log_handler = NULL; char *source_name = NULL; char *program_name; @@ -459,7 +463,7 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa, { char date_str[30]; - if (yep == p_statbuf->b_rock && b_rock) { + if (yep == p_statbuf->b3_rock && b_rock) { report (stdout, " %s %d %d %d [LSN %6lu] %9u", iso9660_get_rock_attr_str (p_statbuf->st_mode), p_statbuf->st_nlinks, @@ -489,9 +493,15 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa, (unsigned int) p_statbuf->size); } strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M ", &p_statbuf->tm); - report (stdout," %s %s\n", date_str, - yep == p_statbuf->b_rock && b_rock + report (stdout," %s %s", date_str, + yep == p_statbuf->b3_rock && b_rock ? psz_name_untranslated : psz_name_translated); + if (yep == p_statbuf->b3_rock && b_rock && S_ISLNK(p_statbuf->st_mode)) { + report(stdout, " -> %s", p_statbuf->psz_symlink); + } + + report(stdout, "\n"); + }