📄 iso9660_fs.c
字号:
if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { if (p_svd->escape_sequences[0] == 0x25 && p_svd->escape_sequences[1] == 0x2f) { switch (p_svd->escape_sequences[2]) { case 0x40: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) p_iso->i_joliet_level = 1; break; case 0x43: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) p_iso->i_joliet_level = 2; break; case 0x45: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) p_iso->i_joliet_level = 3; break; default: cdio_info("Supplementary Volume Descriptor found, but not Joliet"); } if (p_iso->i_joliet_level > 0) { cdio_info("Found Extension: Joliet Level %d", p_iso->i_joliet_level); } } } } return true;}/*! Read the Primary Volume Descriptor for of CD.*/bool iso9660_fs_read_pvd(const CdIo *p_cdio, /*out*/ iso9660_pvd_t *p_pvd){ /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ bool b_mode2; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; int i_rc; switch(cdio_get_track_format(p_cdio, 1)) { case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: b_mode2 = true; break; case TRACK_FORMAT_DATA: b_mode2 = false; break; case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_PSX: case TRACK_FORMAT_ERROR: default: return false; } i_rc = b_mode2 ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR, false) : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR, false); if (i_rc) { cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); return false; } /* The size of a PVD or SVD is smaller than a sector. So we allocated a bigger block above (buf) and now we'll copy just the part we need to save. */ cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t)); memcpy(p_pvd, buf, sizeof(iso9660_pvd_t)); return check_pvd(p_pvd);}/*! Read the Super block of an ISO 9660 image. This is the Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume Descriptor if (Joliet) extensions are acceptable.*/bool iso9660_fs_read_superblock (CdIo *p_cdio, iso_extension_mask_t iso_extension_mask){ if (!p_cdio) return false; { generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; iso9660_pvd_t *p_pvd = &(p_env->pvd); iso9660_svd_t *p_svd = &(p_env->svd); char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; bool b_mode2; int i_rc; /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ switch(cdio_get_track_format(p_cdio, 1)) { case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: b_mode2 = true; break; case TRACK_FORMAT_DATA: b_mode2 = false; break; case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_PSX: case TRACK_FORMAT_ERROR: default: return false; } if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) ) return false; p_env->i_joliet_level = 0; i_rc = (b_mode2) ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false) : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false); if (0 == i_rc) { /* The size of a PVD or SVD is smaller than a sector. So we allocated a bigger block above (buf) and now we'll copy just the part we need to save. */ cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t)); memcpy(p_svd, buf, sizeof(iso9660_svd_t)); if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { if (p_svd->escape_sequences[0] == 0x25 && p_svd->escape_sequences[1] == 0x2f) { switch (p_svd->escape_sequences[2]) { case 0x40: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) p_env->i_joliet_level = 1; break; case 0x43: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) p_env->i_joliet_level = 2; break; case 0x45: if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) p_env->i_joliet_level = 3; break; default: cdio_info("Supplementary Volume Descriptor found, but not Joliet"); } if (p_env->i_joliet_level > 0) { cdio_info("Found Extension: Joliet Level %d", p_env->i_joliet_level); } } } } } return true;}/*! Seek to a position and then read n blocks. Size read is returned.*/long int iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start, long int size){ long int ret; if (NULL == p_iso) return 0; ret = cdio_stream_seek (p_iso->stream, start * ISO_BLOCKSIZE, SEEK_SET); if (ret!=0) return 0; return cdio_stream_read (p_iso->stream, ptr, ISO_BLOCKSIZE, size);}static iso9660_stat_t *_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool b_mode2, uint8_t i_joliet_level){ iso9660_xa_t *xa_data = NULL; uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); unsigned int filename_len; unsigned int stat_len; iso9660_stat_t *stat; if (!dir_len) return NULL; filename_len = from_711(p_iso9660_dir->filename_len); /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */ stat_len = sizeof(iso9660_stat_t)+filename_len+2; stat = _cdio_malloc(stat_len); stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE; stat->lsn = from_733 (p_iso9660_dir->extent); stat->size = from_733 (p_iso9660_dir->size); stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE); if ('\0' == p_iso9660_dir->filename[0] && 1 == filename_len) strcpy (stat->filename, "."); else if ('\1' == p_iso9660_dir->filename[0] && 1 == filename_len) strcpy (stat->filename, ".."); else {#ifdef HAVE_JOLIET if (i_joliet_level) { int i_inlen = filename_len; int i_outlen = (i_inlen / 2); char *p_psz_out = NULL; ucs2be_to_locale(p_iso9660_dir->filename, i_inlen, &p_psz_out, i_outlen); strncpy(stat->filename, p_psz_out, filename_len); free(p_psz_out); } else#endif /*HAVE_JOLIET*/ strncpy (stat->filename, p_iso9660_dir->filename, filename_len); } iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(stat->tm)); cdio_assert (dir_len >= sizeof (iso9660_dir_t)); if (b_mode2) { int su_length = iso9660_get_dir_len(p_iso9660_dir) - sizeof (iso9660_dir_t); su_length -= filename_len; if (su_length % 2) su_length--; if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) return stat; xa_data = (void *) (((char *) p_iso9660_dir) + (iso9660_get_dir_len(p_iso9660_dir) - su_length)); if (xa_data->signature[0] != 'X' || xa_data->signature[1] != 'A') { cdio_warn ("XA signature not found in ISO9660's system use area;" " ignoring XA attributes for this file entry."); cdio_debug ("%d %d %d, '%c%c' (%d, %d)", iso9660_get_dir_len(p_iso9660_dir), filename_len, su_length, xa_data->signature[0], xa_data->signature[1], xa_data->signature[0], xa_data->signature[1]); return stat; } stat->xa = *xa_data; } return stat; }/*! Return the directory name stored in the iso9660_dir_t A string is allocated: the caller must deallocate. */char *iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir){ char namebuf[256] = { 0, }; uint8_t len=iso9660_get_dir_len(iso9660_dir); if (!len) return NULL; cdio_assert (len >= sizeof (iso9660_dir_t)); /* (iso9660_dir->file_flags & ISO_DIRECTORY) */ if (iso9660_dir->filename[0] == '\0') strcpy (namebuf, "."); else if (iso9660_dir->filename[0] == '\1') strcpy (namebuf, ".."); else strncpy (namebuf, iso9660_dir->filename, iso9660_dir->filename_len); return strdup (namebuf);}/* Return a pointer to a ISO 9660 stat buffer or NULL if there's an error*/static iso9660_stat_t *_fs_stat_root (CdIo *p_cdio){ if (!p_cdio) return NULL; { iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL; generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; bool b_mode2 = cdio_get_track_green(p_cdio, 1); iso9660_dir_t *p_iso9660_dir; iso9660_stat_t *p_stat; if (!p_env->i_joliet_level) iso_extension_mask &= ~ISO_EXTENSION_JOLIET; /* FIXME try also with Joliet.*/ if ( !iso9660_fs_read_superblock (p_cdio, iso_extension_mask) ) { cdio_warn("Could not read ISO-9660 Superblock."); return NULL; }#ifdef HAVE_JOLIET p_iso9660_dir = p_env->i_joliet_level ? &(p_env->svd.root_directory_record) : &(p_env->pvd.root_directory_record) ;#else p_iso9660_dir = &(p_env->pvd.root_directory_record) ;#endif p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_mode2, p_env->i_joliet_level); return p_stat; } }static iso9660_stat_t *_fs_stat_iso_root (iso9660_t *p_iso){ iso9660_stat_t *p_stat; iso9660_dir_t *p_iso9660_dir;#ifdef HAVE_JOLIET p_iso9660_dir = p_iso->i_joliet_level ? &(p_iso->svd.root_directory_record) : &(p_iso->pvd.root_directory_record) ;#else p_iso9660_dir = &(p_iso->pvd.root_directory_record) ;#endif p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, true, p_iso->i_joliet_level); return p_stat;}static iso9660_stat_t *_fs_stat_traverse (const CdIo *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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -