/*! Read a data sector @param p_cdio object to read from @param p_buf place to read data into. The caller should make sure this location can store at least ISO_BLOCKSIZE, M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE depending on the kind of sector getting read. If you don't know whether you have a Mode 1/2, Form 1/ Form 2/Formless sector best to reserve space for the maximum, M2RAW_SECTOR_SIZE. @param i_lsn sector to read @param i_blocksize size of block. Should be either ISO_BLOCKSIZE M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under p_buf. */ driver_return_code_t read_data_sectors_image ( void *p_user_data, void *p_buf, lsn_t i_lsn, uint16_t i_blocksize, uint32_t i_blocks ) { const _img_private_t *p_env = p_user_data; if (!p_env || !p_env->gen.cdio) return DRIVER_OP_UNINIT; { CdIo_t *p_cdio = p_env->gen.cdio; track_t i_track = cdio_get_track(p_cdio, i_lsn); track_format_t e_track_format = cdio_get_track_format(p_cdio, i_track); switch(e_track_format) { case TRACK_FORMAT_PSX: case TRACK_FORMAT_AUDIO: case TRACK_FORMAT_ERROR: return DRIVER_OP_ERROR; case TRACK_FORMAT_DATA: return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); case TRACK_FORMAT_CDI: case TRACK_FORMAT_XA: return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); } } return DRIVER_OP_ERROR; }
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; } }
/*! Reads a number of sectors (AKA blocks). @param p_buf place to read data into. The caller should make sure this location is large enough. See below for size information. @param read_mode the kind of "mode" to use in reading. @param i_lsn sector to read @param i_blocks number of sectors to read @return DRIVER_OP_SUCCESS (0) if no error, other (negative) enumerations are returned on error. If read_mode is CDIO_MODE_AUDIO, *p_buf should hold at least CDIO_FRAMESIZE_RAW * i_blocks bytes. If read_mode is CDIO_MODE_DATA, *p_buf should hold at least i_blocks times either ISO_BLOCKSIZE, M1RAW_SECTOR_SIZE or M2F2_SECTOR_SIZE depending on the kind of sector getting read. If you don't know whether you have a Mode 1/2, Form 1/ Form 2/Formless sector best to reserve space for the maximum which is M2RAW_SECTOR_SIZE. If read_mode is CDIO_MODE_M2F1, *p_buf should hold at least M2RAW_SECTOR_SIZE * i_blocks bytes. If read_mode is CDIO_MODE_M2F2, *p_buf should hold at least CDIO_CD_FRAMESIZE * i_blocks bytes. */ driver_return_code_t cdio_read_sectors(const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, cdio_read_mode_t read_mode, uint32_t i_blocks) { switch(read_mode) { case CDIO_READ_MODE_AUDIO: return cdio_read_audio_sectors (p_cdio, p_buf, i_lsn, i_blocks); case CDIO_READ_MODE_M1F1: return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); case CDIO_READ_MODE_M1F2: return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, true, i_blocks); case CDIO_READ_MODE_M2F1: return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks); case CDIO_READ_MODE_M2F2: return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, true, i_blocks); } /* Can't happen. Just to shut up gcc. */ return DRIVER_OP_ERROR; }
/*! Reads a mode 2 sector @param p_cdio object to read from @param buf place to read data into @param lsn sector to read @param b_form2 true for reading mode 2 form 2 sectors or false for mode 2 form 1 sectors. */ driver_return_code_t cdio_read_mode2_sector (const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, bool b_form2) { check_lsn(i_lsn); if (p_cdio->op.read_mode2_sector) return p_cdio->op.read_mode2_sector (p_cdio->env, p_buf, i_lsn, b_form2); /* fallback */ if (p_cdio->op.read_mode2_sectors != NULL) return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, b_form2, 1); return DRIVER_OP_UNSUPPORTED; }
/*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */ int cdio_read_mode2_sector (const CdIo *cdio, void *buf, lsn_t lsn, bool is_form2) { cdio_assert (cdio != NULL); cdio_assert (buf != NULL); cdio_assert (cdio->op.read_mode2_sector != NULL || cdio->op.read_mode2_sectors != NULL); if (cdio->op.read_mode2_sector) return cdio->op.read_mode2_sector (cdio->env, buf, lsn, is_form2); /* fallback */ if (cdio->op.read_mode2_sectors != NULL) return cdio_read_mode2_sectors (cdio, buf, lsn, is_form2, 1); return 1; }
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; }
/*! 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; } }
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; }