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 _fs_stat_root (const CdIo *cdio, iso9660_stat_t *stat, bool is_mode2) { char block[ISO_BLOCKSIZE] = { 0, }; const iso9660_pvd_t *pvd = (void *) █ const iso9660_dir_t *idr = (void *) pvd->root_directory_record; if (is_mode2) { if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false)) cdio_assert_not_reached (); } else { if (cdio_read_mode1_sector (cdio, &block, ISO_PVD_SECTOR, false)) cdio_assert_not_reached (); } _idr2statbuf (idr, stat, is_mode2); }
int main (int argc, const char *argv[]) { cdio_assert (argc < 2); cdio_assert_not_reached (); return 0; }
static void cdio_logv (cdio_log_level_t level, const char format[], va_list args) { char buf[1024] = { 0, }; static int in_recursion = 0; if (in_recursion) cdio_assert_not_reached (); in_recursion = 1; vsnprintf(buf, sizeof(buf)-1, format, args); _handler(level, buf); in_recursion = 0; }
static void default_cdio_log_handler (cdio_log_level_t level, const char message[]) { switch (level) { case CDIO_LOG_ERROR: if (level >= cdio_loglevel_default) { fprintf (stderr, "**ERROR: %s\n", message); fflush (stderr); } exit (EXIT_FAILURE); break; case CDIO_LOG_DEBUG: if (level >= cdio_loglevel_default) { fprintf (stdout, "--DEBUG: %s\n", message); } break; case CDIO_LOG_WARN: if (level >= cdio_loglevel_default) { fprintf (stdout, "++ WARN: %s\n", message); } break; case CDIO_LOG_INFO: if (level >= cdio_loglevel_default) { fprintf (stdout, " INFO: %s\n", message); } break; case CDIO_LOG_ASSERT: if (level >= cdio_loglevel_default) { fprintf (stderr, "!ASSERT: %s\n", message); fflush (stderr); } abort (); break; default: cdio_assert_not_reached (); break; } fflush (stdout); }
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; } }
/*! Pad string src with spaces to size len and copy this to dst. If len is less than the length of src, dst will be truncated to the first len characters of src. src can also be scanned to see if it contains only ACHARs, DCHARs, 7-bit ASCII chars depending on the enumeration _check. In addition to getting changed, dst is the return value. Note: this string might not be NULL terminated. */ char * iso9660_strncpy_pad(char dst[], const char src[], size_t len, enum strncpy_pad_check _check) { size_t rlen; cdio_assert (dst != NULL); cdio_assert (src != NULL); cdio_assert (len > 0); switch (_check) { int idx; case ISO9660_NOCHECK: break; case ISO9660_7BIT: for (idx = 0; src[idx]; idx++) if ((int8_t) src[idx] < 0) { cdio_warn ("string '%s' fails 7bit constraint (pos = %d)", src, idx); break; } break; case ISO9660_ACHARS: for (idx = 0; src[idx]; idx++) if (!iso9660_is_achar (src[idx])) { cdio_warn ("string '%s' fails a-character constraint (pos = %d)", src, idx); break; } break; case ISO9660_DCHARS: for (idx = 0; src[idx]; idx++) if (!iso9660_is_dchar (src[idx])) { cdio_warn ("string '%s' fails d-character constraint (pos = %d)", src, idx); break; } break; default: cdio_assert_not_reached (); break; } rlen = strlen (src); if (rlen > len) cdio_warn ("string '%s' is getting truncated to %d characters", src, (unsigned int) len); strncpy (dst, src, len); if (rlen < len) memset(dst+rlen, ' ', len-rlen); return dst; }
/*! 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; }