/*! Get file status for pathname into stat. As with libc's stat, 0 is returned if no error and -1 on error. */ int iso9660_fs_stat (const CdIo *cdio, const char pathname[], /*out*/ iso9660_stat_t *stat, bool is_mode2) { iso9660_stat_t _root; int retval; char **splitpath; cdio_assert (cdio != NULL); cdio_assert (pathname != NULL); cdio_assert (stat != NULL); _fs_stat_root (cdio, &_root, is_mode2); splitpath = _cdio_strsplit (pathname, '/'); retval = _fs_stat_traverse (cdio, &_root, splitpath, stat, is_mode2); _cdio_strfreev (splitpath); return retval; }
/*! Get file status for psz_path into stat. NULL is returned on error. */ iso9660_stat_t * iso9660_fs_stat (CdIo_t *p_cdio, const char psz_path[]) { iso9660_stat_t *p_root; char **p_psz_splitpath; iso9660_stat_t *p_stat; if (!p_cdio) return NULL; if (!psz_path) return NULL; p_root = _fs_stat_root (p_cdio); if (!p_root) return NULL; p_psz_splitpath = _cdio_strsplit (psz_path, '/'); p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath); free(p_root); _cdio_strfreev (p_psz_splitpath); return p_stat; }
/*! Get file status for pathname into stat. NULL is returned on error. pathname version numbers in the ISO 9660 name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names are lowercased. */ iso9660_stat_t * iso9660_fs_stat_translate (CdIo_t *p_cdio, const char pathname[], bool b_mode2) { iso9660_stat_t *p_root; char **p_psz_splitpath; iso9660_stat_t *p_stat; if (!p_cdio) return NULL; if (pathname) return NULL; p_root = _fs_stat_root (p_cdio); if (!p_root) return NULL; p_psz_splitpath = _cdio_strsplit (pathname, '/'); p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, true); free(p_root); _cdio_strfreev (p_psz_splitpath); return p_stat; }
/*! Get file status for pathname into stat. NULL is returned on error. */ iso9660_stat_t * iso9660_fs_stat (CdIo_t *p_cdio, const char pathname[]) { iso9660_stat_t *p_root; char **p_psz_splitpath; iso9660_stat_t *p_stat; /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ bool b_mode2; if (!p_cdio) return NULL; if (!pathname) return NULL; p_root = _fs_stat_root (p_cdio); if (!p_root) return NULL; b_mode2 = cdio_get_track_green(p_cdio, 1); p_psz_splitpath = _cdio_strsplit (pathname, '/'); p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, false); free(p_root); _cdio_strfreev (p_psz_splitpath); return p_stat; }
static iso9660_stat_t * _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, char **splitpath) { unsigned offset = 0; uint8_t *_dirbuf = NULL; iso9660_stat_t *p_stat; generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; if (!splitpath[0]) { unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; p_stat = calloc(1, len); memcpy(p_stat, _root, len); p_stat->rr.psz_symlink = calloc(1, p_stat->rr.i_symlink_max); memcpy(p_stat->rr.psz_symlink, _root->rr.psz_symlink, p_stat->rr.i_symlink_max); return p_stat; } if (_root->type == _STAT_FILE) return NULL; cdio_assert (_root->type == _STAT_DIR); if (_root->size != ISO_BLOCKSIZE * _root->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) _root->size, (unsigned long int) ISO_BLOCKSIZE * _root->secsize); } _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); if (!_dirbuf) { cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); return NULL; } if (cdio_read_data_sectors (p_cdio, _dirbuf, _root->lsn, ISO_BLOCKSIZE, _root->secsize)) return NULL; while (offset < (_root->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_stat; int cmp; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, dunno, p_env->i_joliet_level); cmp = strcmp(splitpath[0], p_stat->filename); if ( 0 != cmp && 0 == p_env->i_joliet_level && yep != p_stat->rr.b3_rock ) { char *trans_fname = NULL; unsigned int i_trans_fname=strlen(p_stat->filename); int trans_len; if (i_trans_fname) { trans_fname = calloc(1, i_trans_fname+1); if (!trans_fname) { cdio_warn("can't allocate %lu bytes", (long unsigned int) strlen(p_stat->filename)); return NULL; } trans_len = iso9660_name_translate_ext(p_stat->filename, trans_fname, p_env->i_joliet_level); cmp = strcmp(splitpath[0], trans_fname); free(trans_fname); } } if (!cmp) { iso9660_stat_t *ret_stat = _fs_stat_traverse (p_cdio, p_stat, &splitpath[1]); free(p_stat->rr.psz_symlink); free(p_stat); free (_dirbuf); return ret_stat; } free(p_stat->rr.psz_symlink); free(p_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); return NULL; }
static iso9660_stat_t * _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, char **splitpath, bool b_mode2, bool translate) { unsigned offset = 0; uint8_t *_dirbuf = NULL; iso9660_stat_t *p_stat; generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; if (!splitpath[0]) { unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; p_stat = _cdio_malloc(len); memcpy(p_stat, _root, len); return p_stat; } if (_root->type == _STAT_FILE) return NULL; cdio_assert (_root->type == _STAT_DIR); if (_root->size != ISO_BLOCKSIZE * _root->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) _root->size, (unsigned long int) ISO_BLOCKSIZE * _root->secsize); } _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); if (b_mode2) { if (cdio_read_mode2_sectors (p_cdio, _dirbuf, _root->lsn, false, _root->secsize)) return NULL; } else { if (cdio_read_mode1_sectors (p_cdio, _dirbuf, _root->lsn, false, _root->secsize)) return NULL; } while (offset < (_root->secsize * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_stat; int cmp; if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_mode2, p_env->i_joliet_level); if (translate) { char *trans_fname = malloc(strlen(p_stat->filename)); int trans_len; if (trans_fname == NULL) { cdio_warn("can't allocate %lu bytes", (long unsigned int) strlen(p_stat->filename)); return NULL; } trans_len = iso9660_name_translate_ext(p_stat->filename, trans_fname, p_env->i_joliet_level); cmp = strcmp(splitpath[0], trans_fname); free(trans_fname); } else { cmp = strcmp(splitpath[0], p_stat->filename); } if (!cmp) { iso9660_stat_t *ret_stat = _fs_stat_traverse (p_cdio, p_stat, &splitpath[1], b_mode2, translate); free(p_stat); free (_dirbuf); return ret_stat; } free(p_stat); offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); return NULL; }
static int _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root, char **splitpath, /*out*/ iso9660_stat_t *buf, bool is_mode2) { unsigned offset = 0; uint8_t *_dirbuf = NULL; if (!splitpath[0]) { *buf = *_root; return 0; } if (_root->type == _STAT_FILE) return -1; cdio_assert (_root->type == _STAT_DIR); if (_root->size != ISO_BLOCKSIZE * _root->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", (unsigned) _root->size, (unsigned long int) ISO_BLOCKSIZE * _root->secsize); } _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); if (is_mode2) { if (cdio_read_mode2_sectors (cdio, _dirbuf, _root->lsn, false, _root->secsize)) cdio_assert_not_reached (); } else { if (cdio_read_mode1_sectors (cdio, _dirbuf, _root->lsn, false, _root->secsize)) cdio_assert_not_reached (); } while (offset < (_root->secsize * ISO_BLOCKSIZE)) { const iso9660_dir_t *idr = (void *) &_dirbuf[offset]; iso9660_stat_t stat; char *name; if (!iso9660_get_dir_len(idr)) { offset++; continue; } name = _idr2name (idr); _idr2statbuf (idr, &stat, is_mode2); if (!strcmp (splitpath[0], name)) { int retval = _fs_stat_traverse (cdio, &stat, &splitpath[1], buf, is_mode2); free (name); free (_dirbuf); return retval; } free (name); offset += iso9660_get_dir_len(idr); } cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); return -1; }