/*! Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ CdioList_t * iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[]) { iso9660_stat_t *p_stat; if (!p_iso) return NULL; if (!pathname) return NULL; p_stat = iso9660_ifs_stat (p_iso, pathname); if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { free(p_stat); return NULL; } { long int ret; unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned int) p_stat->size, (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize); } _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE); ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize); if (ret != ISO_BLOCKSIZE*p_stat->secsize) return NULL; while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_iso9660_stat; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, true, p_iso->i_joliet_level); _cdio_list_append (retval, p_iso9660_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); free (_dirbuf); free (p_stat); return retval; } }
void * /* list of char* -- caller must free it */ iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) { iso9660_stat_t stat; cdio_assert (cdio != NULL); cdio_assert (pathname != NULL); if (iso9660_fs_stat (cdio, pathname, &stat, is_mode2)) return NULL; if (stat.type != _STAT_DIR) return NULL; { unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList *retval = _cdio_list_new (); if (stat.size != ISO_BLOCKSIZE * stat.secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) stat.size, (unsigned long int) ISO_BLOCKSIZE * stat.secsize); } _dirbuf = _cdio_malloc (stat.secsize * ISO_BLOCKSIZE); if (is_mode2) { if (cdio_read_mode2_sectors (cdio, _dirbuf, stat.lsn, false, stat.secsize)) cdio_assert_not_reached (); } else { if (cdio_read_mode1_sectors (cdio, _dirbuf, stat.lsn, false, stat.secsize)) cdio_assert_not_reached (); } while (offset < (stat.secsize * ISO_BLOCKSIZE)) { const iso9660_dir_t *idr = (void *) &_dirbuf[offset]; if (!iso9660_get_dir_len(idr)) { offset++; continue; } _cdio_list_append (retval, _idr2name (idr)); offset += iso9660_get_dir_len(idr); } cdio_assert (offset == (stat.secsize * ISO_BLOCKSIZE)); free (_dirbuf); return retval; } }
static void print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[], cdio_fs_anal_t fs) { CdioList_t *p_entlist; CdioList_t *p_dirlist = _cdio_list_new (); CdioListNode_t *entnode; uint8_t i_joliet_level; i_joliet_level = (opts.no_joliet) ? 0 : cdio_get_joliet_level(p_cdio); p_entlist = iso9660_fs_readdir (p_cdio, pathname, false); printf ("%s:\n", pathname); if (NULL == p_entlist) { report( stderr, "Error getting above directory information\n" ); return; } /* Iterate over files in this directory */ _CDIO_LIST_FOREACH (entnode, p_entlist) { iso9660_stat_t *p_statbuf = _cdio_list_node_data (entnode); char *psz_iso_name = p_statbuf->filename; char _fullname[4096] = { 0, }; char translated_name[MAX_ISONAME+1]; if (yep != p_statbuf->rr.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, psz_iso_name); strncat (_fullname, "/", sizeof (_fullname)); if (p_statbuf->type == _STAT_DIR && strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, "..")) _cdio_list_append (p_dirlist, strdup (_fullname)); print_fs_attrs(p_statbuf, 0 == opts.no_rock_ridge, fs & CDIO_FS_ANAL_XA, psz_iso_name, translated_name); if (p_statbuf->rr.i_symlink) { free(p_statbuf->rr.psz_symlink); p_statbuf->rr.i_symlink = 0; } }
static iso9660_stat_t * find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir, const char psz_path[], lsn_t lsn, /*out*/ char **ppsz_full_filename) { CdioList_t *entlist = iso9660_readdir (p_image, psz_path); CdioList_t *dirlist = _cdio_list_new (); CdioListNode_t *entnode; cdio_assert (entlist != NULL); /* iterate over each entry in the directory */ _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); const char *psz_filename = (char *) statbuf->filename; const unsigned int len = strlen(psz_path) + strlen(psz_filename)+2; if (*ppsz_full_filename != NULL) free(*ppsz_full_filename); *ppsz_full_filename = calloc(1, len); snprintf (*ppsz_full_filename, len, "%s%s/", psz_path, psz_filename); if (statbuf->type == _STAT_DIR && strcmp ((char *) statbuf->filename, ".") && strcmp ((char *) statbuf->filename, "..")) { _cdio_list_append (dirlist, strdup(*ppsz_full_filename)); } if (statbuf->lsn == lsn) { unsigned int len=sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1; iso9660_stat_t *ret_stat = calloc(1, len); if (!ret_stat) { cdio_warn("Couldn't calloc(1, %d)", len); return NULL; } memcpy(ret_stat, statbuf, len); _cdio_list_free (entlist, true); _cdio_list_free (dirlist, true); return ret_stat; } }
static iso9660_stat_t * find_fs_lsn_recurse (CdIo_t *p_cdio, const char pathname[], lsn_t lsn) { CdioList_t *entlist = iso9660_fs_readdir (p_cdio, pathname, true); CdioList_t *dirlist = _cdio_list_new (); CdioListNode_t *entnode; cdio_assert (entlist != NULL); /* iterate over each entry in the directory */ _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); char _fullname[4096] = { 0, }; char *filename = (char *) statbuf->filename; snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, filename); strncat (_fullname, "/", sizeof (_fullname)); if (statbuf->type == _STAT_DIR && strcmp ((char *) statbuf->filename, ".") && strcmp ((char *) statbuf->filename, "..")) _cdio_list_append (dirlist, strdup (_fullname)); if (statbuf->lsn == lsn) { unsigned int len=sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1; iso9660_stat_t *ret_stat = _cdio_malloc(len); memcpy(ret_stat, statbuf, len); _cdio_list_free (entlist, true); _cdio_list_free (dirlist, true); return ret_stat; } }
static bool find_fs_lsn_recurse (const CdIo *cdio, const char pathname[], /*out*/ iso9660_stat_t *statbuf, lsn_t lsn) { CdioList *entlist = iso9660_fs_readdir (cdio, pathname, true); CdioList *dirlist = _cdio_list_new (); CdioListNode *entnode; cdio_assert (entlist != NULL); /* iterate over each entry in the directory */ _CDIO_LIST_FOREACH (entnode, entlist) { char *name = _cdio_list_node_data (entnode); char _fullname[4096] = { 0, }; snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, name); if (iso9660_fs_stat (cdio, _fullname, statbuf, true)) cdio_assert_not_reached (); strncat (_fullname, "/", sizeof (_fullname)); if (statbuf->type == _STAT_DIR && strcmp (name, ".") && strcmp (name, "..")) _cdio_list_append (dirlist, strdup (_fullname)); if (statbuf->lsn == lsn) { _cdio_list_free (entlist, true); _cdio_list_free (dirlist, true); return true; } }
/*! Read psz_path (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. b_mode2 is historical. It is not used. */ CdioList_t * iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) { generic_img_private_t *p_env; iso9660_stat_t *p_stat; if (!p_cdio) return NULL; if (!psz_path) return NULL; p_env = (generic_img_private_t *) p_cdio->env; p_stat = iso9660_fs_stat (p_cdio, psz_path); if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { free(p_stat->rr.psz_symlink); free(p_stat); return NULL; } { unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) p_stat->size, (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize); } _dirbuf = calloc(1, p_stat->secsize * ISO_BLOCKSIZE); if (!_dirbuf) { cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize * ISO_BLOCKSIZE); return NULL; } if (cdio_read_data_sectors (p_cdio, _dirbuf, p_stat->lsn, ISO_BLOCKSIZE, p_stat->secsize)) return NULL; while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_iso9660_stat; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, dunno, p_env->i_joliet_level); _cdio_list_append (retval, p_iso9660_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); free (_dirbuf); free (p_stat); return retval; } }
/*! Read psz_path (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ CdioList_t * iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) { iso9660_stat_t *p_stat; if (!p_iso) return NULL; if (!psz_path) return NULL; p_stat = iso9660_ifs_stat (p_iso, psz_path); if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { free(p_stat->rr.psz_symlink); free(p_stat); return NULL; } { long int ret; unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); _dirbuf = calloc(1, p_stat->secsize * ISO_BLOCKSIZE); if (!_dirbuf) { cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize * ISO_BLOCKSIZE); return NULL; } ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize); if (ret != ISO_BLOCKSIZE*p_stat->secsize) { free (_dirbuf); return NULL; } while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_iso9660_stat; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, p_iso->b_xa, p_iso->u_joliet_level); if (p_iso9660_stat) _cdio_list_append (retval, p_iso9660_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } free (_dirbuf); if (offset != (p_stat->secsize * ISO_BLOCKSIZE)) { free (p_stat); _cdio_list_free (retval, true); return NULL; } free (p_stat->rr.psz_symlink); free (p_stat); return retval; } }
/* Updates internal track TOC, so we can later simulate ioctl(CDROMREADTOCENTRY). */ static void _register_mapping (_img_private_t *env, lsn_t start_lsn, uint32_t sec_count, uint64_t img_offset, uint32_t blocksize, track_format_t track_format, bool track_green) { const int track_num=env->gen.i_tracks; track_info_t *this_track=&(env->tocent[env->gen.i_tracks]); _mapping_t *_map = calloc(1, sizeof (_mapping_t)); _map->start_lsn = start_lsn; _map->sec_count = sec_count; _map->img_offset = img_offset; _map->blocksize = blocksize; if (!env->mapping) env->mapping = _cdio_list_new (); _cdio_list_append (env->mapping, _map); env->size = MAX (env->size, (start_lsn + sec_count)); /* Update *this_track and track_num. These structures are in a sense redundant witht the obj->mapping list. Perhaps one or the other can be eliminated. */ cdio_lba_to_msf (cdio_lsn_to_lba(start_lsn), &(this_track->start_msf)); this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf); this_track->track_num = track_num+1; this_track->blocksize = blocksize; if (env->is_cues) this_track->datastart = img_offset; else this_track->datastart = 0; if (track_green) this_track->datastart += CDIO_CD_SUBHEADER_SIZE; this_track->sec_count = sec_count; this_track->track_format= track_format; this_track->track_green = track_green; switch (this_track->track_format) { case TRACK_FORMAT_AUDIO: this_track->blocksize = CDIO_CD_FRAMESIZE_RAW; this_track->datasize = CDIO_CD_FRAMESIZE_RAW; /*this_track->datastart = 0;*/ this_track->endsize = 0; break; case TRACK_FORMAT_CDI: this_track->datasize=CDIO_CD_FRAMESIZE; break; case TRACK_FORMAT_XA: if (track_green) { this_track->blocksize = CDIO_CD_FRAMESIZE; /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/ this_track->datasize = M2RAW_SECTOR_SIZE; this_track->endsize = 0; } else { /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE;*/ this_track->datasize = CDIO_CD_FRAMESIZE; this_track->endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE; } break; case TRACK_FORMAT_DATA: if (track_green) { /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/ this_track->datasize = CDIO_CD_FRAMESIZE; this_track->endsize = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; } else { /* Is the below correct? */ /*this_track->datastart = 0;*/ this_track->datasize = CDIO_CD_FRAMESIZE; this_track->endsize = 0; } break; default: /*this_track->datasize=CDIO_CD_FRAMESIZE_RAW;*/ cdio_warn ("track %d has unknown format %d", env->gen.i_tracks, this_track->track_format); } env->gen.i_tracks++; cdio_debug ("start lsn: %lu sector count: %0lu -> %8ld (%08lx)", (long unsigned int) start_lsn, (long unsigned int) sec_count, (long unsigned int) img_offset, (long unsigned int) img_offset); }
static void print_iso9660_recurse (iso9660_t *p_iso, const char psz_path[]) { CdioList_t *entlist; CdioList_t *dirlist = _cdio_list_new (); CdioListNode_t *entnode; uint8_t i_joliet_level = iso9660_ifs_get_joliet_level(p_iso); char *translated_name = (char *) malloc(4096); size_t translated_name_size = 4096; entlist = iso9660_ifs_readdir (p_iso, psz_path); if (opts.print_iso9660) { printf ("%s:\n", psz_path); } if (NULL == entlist) { report( stderr, "Error getting above directory information\n" ); return; } /* Iterate over files in this directory */ _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *p_statbuf = _cdio_list_node_data (entnode); char *psz_iso_name = p_statbuf->filename; char _fullname[4096] = { 0, }; if (strlen(psz_iso_name) >= translated_name_size) { translated_name_size = strlen(psz_iso_name)+1; free(translated_name); translated_name = (char *) malloc(translated_name_size); if (!translated_name) { report( stderr, "Error allocating memory\n" ); return; } } if (yep != p_statbuf->rr.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", psz_path, translated_name); } else { snprintf (_fullname, sizeof (_fullname), "%s%s", psz_path, psz_iso_name); } strncat (_fullname, "/", sizeof (_fullname)); if (p_statbuf->type == _STAT_DIR && 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, psz_iso_name, translated_name); } else if ( strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, "..")) printf("%9u %s%s\n", (unsigned int) p_statbuf->size, psz_path, yep == p_statbuf->rr.b3_rock ? psz_iso_name : translated_name); if (p_statbuf->rr.i_symlink) { free(p_statbuf->rr.psz_symlink); p_statbuf->rr.i_symlink = 0; } }
static void print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[], cdio_fs_anal_t fs, bool b_mode2) { CdioList_t *entlist; CdioList_t *dirlist = _cdio_list_new (); CdioListNode_t *entnode; uint8_t i_joliet_level; i_joliet_level = (opts.no_joliet) ? 0 : cdio_get_joliet_level(p_cdio); entlist = iso9660_fs_readdir (p_cdio, pathname, b_mode2); sprintf (temp_msg, "%s:\n", pathname); report(stdout, temp_msg); if (NULL == entlist) { report( stderr, "Error getting above directory information\n" ); return; } /* Iterate over files in this directory */ _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); char *iso_name = statbuf->filename; char _fullname[4096] = { 0, }; char translated_name[MAX_ISONAME+1]; #define DATESTR_SIZE 30 char date_str[DATESTR_SIZE]; iso9660_name_translate_ext(iso_name, translated_name, i_joliet_level); snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, iso_name); strncat (_fullname, "/", sizeof (_fullname)); if (statbuf->type == _STAT_DIR && strcmp (iso_name, ".") && strcmp (iso_name, "..")) _cdio_list_append (dirlist, strdup (_fullname)); if (fs & CDIO_FS_ANAL_XA) { sprintf (temp_msg, " %c %s %d %d [fn %.2d] [LSN %6lu] ", (statbuf->type == _STAT_DIR) ? 'd' : '-', iso9660_get_xa_attr_str (statbuf->xa.attributes), uint16_from_be (statbuf->xa.user_id), uint16_from_be (statbuf->xa.group_id), statbuf->xa.filenum, (long unsigned int) statbuf->lsn); report(stdout, temp_msg); if (uint16_from_be(statbuf->xa.attributes) & XA_ATTR_MODE2FORM2) { sprintf (temp_msg, "%9u (%9u)", (unsigned int) statbuf->secsize * M2F2_SECTOR_SIZE, (unsigned int) statbuf->size); report(stdout, temp_msg); } else { printf ("%9u", (unsigned int) statbuf->size); } } strftime(date_str, DATESTR_SIZE, "%b %d %Y %H:%M ", &statbuf->tm); sprintf (temp_msg, " %s %s\n", date_str, translated_name); report(stdout, temp_msg); }
/*! Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ CdioList_t * iso9660_fs_readdir (CdIo_t *p_cdio, const char pathname[], bool b_mode2) { iso9660_stat_t *p_stat; generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; if (!p_cdio) return NULL; if (!pathname) return NULL; p_stat = iso9660_fs_stat (p_cdio, pathname); if (!p_stat) return NULL; if (p_stat->type != _STAT_DIR) { free(p_stat); return NULL; } { unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) p_stat->size, (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize); } _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE); if (b_mode2) { if (cdio_read_mode2_sectors (p_cdio, _dirbuf, p_stat->lsn, false, p_stat->secsize)) cdio_assert_not_reached (); } else { if (cdio_read_mode1_sectors (p_cdio, _dirbuf, p_stat->lsn, false, p_stat->secsize)) cdio_assert_not_reached (); } while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_iso9660_stat; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, b_mode2, p_env->i_joliet_level); _cdio_list_append (retval, p_iso9660_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); free (_dirbuf); free (p_stat); return retval; } }