📄 iso9660_fs.c
字号:
} 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_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, char **splitpath, bool translate){ unsigned offset = 0; uint8_t *_dirbuf = NULL; int ret; if (!splitpath[0]) { iso9660_stat_t *p_stat; 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); ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize); if (ret!=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, true, p_iso->i_joliet_level); if (translate) { char *trans_fname = malloc(strlen(p_stat->filename)+1); 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_iso->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_iso_stat_traverse (p_iso, p_stat, &splitpath[1], 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;}/*! Get file status for pathname into stat. NULL is returned on error. */iso9660_stat_t *iso9660_fs_stat (CdIo *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;}/*! 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 *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_ifs_stat (iso9660_t *p_iso, const char pathname[]){ iso9660_stat_t *p_root; char **splitpath; iso9660_stat_t *stat; if (!p_iso) return NULL; if (!pathname) return NULL; p_root = _fs_stat_iso_root (p_iso); if (!p_root) return NULL; splitpath = _cdio_strsplit (pathname, '/'); stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath, false); free(p_root); /*** FIXME _cdio_strfreev (splitpath); ***/ return 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_ifs_stat_translate (iso9660_t *p_iso, const char pathname[]){ iso9660_stat_t *p_root; char **p_psz_splitpath; iso9660_stat_t *p_stat; if (!p_iso) return NULL; if (!pathname) return NULL; p_root = _fs_stat_iso_root (p_iso); if (NULL == p_root) return NULL; p_psz_splitpath = _cdio_strsplit (pathname, '/'); p_stat = _fs_iso_stat_traverse (p_iso, p_root, p_psz_splitpath, true); free(p_root); _cdio_strfreev (p_psz_splitpath); return p_stat;}/*! 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 * iso9660_fs_readdir (CdIo *p_cdio, const char pathname[], bool b_mode2){ generic_img_private_t *p_env; iso9660_stat_t *p_stat; if (!p_cdio) return NULL; if (!pathname) return NULL; p_env = (generic_img_private_t *) p_cdio->env; 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 *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; }}/*! 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 * 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 *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; }}static iso9660_stat_t *find_fs_lsn_recurse (CdIo *p_cdio, const char pathname[], lsn_t lsn){ CdioList *entlist = iso9660_fs_readdir (p_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) { 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); 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; } } _cdio_list_free (entlist, true); /* now recurse/descend over directories encountered */ _CDIO_LIST_FOREACH (entnode, dirlist) { char *_fullname = _cdio_list_node_data (entnode); iso9660_stat_t *ret_stat = find_fs_lsn_recurse (p_cdio, _fullname, lsn); if (NULL != ret_stat) { _cdio_list_free (dirlist, true); return ret_stat; } } _cdio_list_free (dirlist, true); return NULL;}/*! Given a directory pointer, find the filesystem entry that contains lsn and return information about it. Returns stat_t of entry if we found lsn, or NULL otherwise. */iso9660_stat_t *iso9660_find_fs_lsn(CdIo *p_cdio, lsn_t i_lsn){ return find_fs_lsn_recurse (p_cdio, "/", i_lsn);}/*! Return true if ISO 9660 image has extended attrributes (XA).*/bool iso9660_ifs_is_xa (const iso9660_t * p_iso) { if (!p_iso) return false; return p_iso->b_xa;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -