static void print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[], cdio_fs_anal_t fs) { CdioList_t *p_entlist; CdioList_t *p_dirlist = _cdio_list_new (); CdioListNode_t *entnode; uint8_t i_joliet_level; i_joliet_level = (opts.no_joliet) ? 0 : cdio_get_joliet_level(p_cdio); p_entlist = iso9660_fs_readdir (p_cdio, pathname, false); printf ("%s:\n", pathname); if (NULL == p_entlist) { report( stderr, "Error getting above directory information\n" ); return; } /* Iterate over files in this directory */ _CDIO_LIST_FOREACH (entnode, p_entlist) { iso9660_stat_t *p_statbuf = _cdio_list_node_data (entnode); char *psz_iso_name = p_statbuf->filename; char _fullname[4096] = { 0, }; char translated_name[MAX_ISONAME+1]; if (yep != p_statbuf->rr.b3_rock || 1 == opts.no_rock_ridge) { iso9660_name_translate_ext(psz_iso_name, translated_name, i_joliet_level); } snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, psz_iso_name); strncat (_fullname, "/", sizeof (_fullname)); if (p_statbuf->type == _STAT_DIR && strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, "..")) _cdio_list_append (p_dirlist, strdup (_fullname)); print_fs_attrs(p_statbuf, 0 == opts.no_rock_ridge, fs & CDIO_FS_ANAL_XA, psz_iso_name, translated_name); if (p_statbuf->rr.i_symlink) { free(p_statbuf->rr.psz_symlink); p_statbuf->rr.i_symlink = 0; } }
// Builds a filename-to-ID hash map for a given ISO file. This // function is recursive, and the top-level call should have a // path == "". void ResourceFile::Build_hash (const string& path) { uint8_t i_joliet_level = iso_file.get_joliet_level(); stat_vector_t entlist; if (!iso_file.readdir(path.c_str(), entlist)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error getting above directory information: %s\n", path.c_str()); return; } for (auto i: entlist) { iso9660_stat_t* p_statbuf = i->p_stat; string full_name = p_statbuf->filename; if (p_statbuf->rr.b3_rock != yep) { // Overwrite the name with a translated name. Note that // we're using the assumption that the translated name // will be shorter, and we're overwriting it in memory. iso9660_name_translate_ext(full_name.c_str(), (char *) full_name.c_str(), i_joliet_level); } full_name = full_name.insert(0, path); // Recursively descend into subdirectories if (p_statbuf->type == 2 /* _STAT_DIR */ && strcmp (p_statbuf->filename, ".") && strcmp (p_statbuf->filename, "..")) { full_name.append("/"); Build_hash(full_name); } // For regular files, add them to the hash table if (p_statbuf->type == 1) { // There is an initial slash in this filename that needs to go // full_name.erase(0,1); printf("%s\n", full_name.c_str()); xiso_file_hash[Quick_hash(full_name)] = full_name; SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Resource Hash: adding \"%s\" as %x", full_name.c_str(), Quick_hash(full_name)); } } }
// Returns 0 on success, nonzero on error static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) { HANDLE file_handle = NULL; DWORD buf_size, wr_size, err; BOOL s, is_syslinux_cfg, is_old_c32[NB_OLD_C32], is_symlink; int i_length, r = 1; char tmp[128], psz_fullpath[1024], *psz_basename; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; unsigned char buf[ISO_BLOCKSIZE]; CdioListNode_t* p_entnode; iso9660_stat_t *p_statbuf; CdioList_t* p_entlist; size_t i, j, nul_pos; lsn_t lsn; int64_t i_file_length; if ((p_iso == NULL) || (psz_path == NULL)) return 1; i_length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path); if (i_length < 0) return 1; psz_basename = &psz_fullpath[i_length]; p_entlist = iso9660_ifs_readdir(p_iso, psz_path); if (!p_entlist) { uprintf("Could not access directory %s\n", psz_path); return 1; } _CDIO_LIST_FOREACH(p_entnode, p_entlist) { if (FormatStatus) goto out; p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); // Eliminate . and .. entries if ( (strcmp(p_statbuf->filename, ".") == 0) || (strcmp(p_statbuf->filename, "..") == 0) ) continue; // Rock Ridge requires an exception is_symlink = FALSE; if ((p_statbuf->rr.b3_rock == yep) && enable_rockridge) { safe_strcpy(psz_basename, sizeof(psz_fullpath)-i_length-1, p_statbuf->filename); if (safe_strlen(p_statbuf->filename) > 64) iso_report.has_long_filename = TRUE; // libcdio has a memleak for Rock Ridge symlinks. It doesn't look like there's an easy fix there as // a generic list that's unaware of RR extensions is being used, so we prevent that memleak ourselves is_symlink = (p_statbuf->rr.psz_symlink != NULL); if (is_symlink) iso_report.has_symlinks = TRUE; if (scan_only) safe_free(p_statbuf->rr.psz_symlink); } else { iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level); } if (p_statbuf->type == _STAT_DIR) { if (!scan_only) _mkdirU(psz_fullpath); if (iso_extract_files(p_iso, psz_iso_name)) goto out; } else { i_file_length = p_statbuf->size; if (check_iso_props(psz_path, &is_syslinux_cfg, is_old_c32, i_file_length, psz_basename, psz_fullpath)) { continue; } // Replace slashes with backslashes and append the size to the path for UI display nul_pos = safe_strlen(psz_fullpath); for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '/') psz_fullpath[i] = '\\'; safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(i_file_length, TRUE, FALSE)); uprintf("Extracting: %s\n", psz_fullpath); safe_sprintf(&psz_fullpath[nul_pos], 24, " (%s)", SizeToHumanReadable(i_file_length, FALSE, FALSE)); SetWindowTextU(hISOFileName, psz_fullpath); // ISO9660 cannot handle backslashes for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '\\') psz_fullpath[i] = '/'; psz_fullpath[nul_pos] = 0; for (i=0; i<NB_OLD_C32; i++) { if (is_old_c32[i] && use_own_c32[i]) { static_sprintf(tmp, "%s/syslinux-%s/%s", FILES_DIR, embedded_sl_version_str[0], old_c32_name[i]); if (CopyFileA(tmp, psz_fullpath, FALSE)) { uprintf(" Replaced with local version\n"); break; } uprintf(" Could not replace file: %s\n", WindowsErrorString()); } } if (i < NB_OLD_C32) continue; if (sanitize_filename(psz_fullpath)) uprintf(" File name sanitized to '%s'\n", psz_fullpath); if (is_symlink) { if (i_file_length == 0) uprintf(" Ignoring Rock Ridge symbolic link to '%s'\n", p_statbuf->rr.psz_symlink); safe_free(p_statbuf->rr.psz_symlink); } file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) { err = GetLastError(); uprintf(" Unable to create file: %s\n", WindowsErrorString()); if ((err == ERROR_ACCESS_DENIED) && (safe_strcmp(&psz_fullpath[3], autorun_name) == 0)) uprintf(stupid_antivirus); else goto out; } else for (i=0; i_file_length>0; i++) { if (FormatStatus) goto out; memset(buf, 0, ISO_BLOCKSIZE); lsn = p_statbuf->lsn + (lsn_t)i; if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { uprintf(" Error reading ISO9660 file %s at LSN %lu\n", psz_iso_name, (long unsigned int)lsn); goto out; } buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); for (j=0; j<WRITE_RETRIES; j++) { ISO_BLOCKING(s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL)); if ((!s) || (buf_size != wr_size)) { uprintf(" Error writing file: %s", WindowsErrorString()); if (j < WRITE_RETRIES-1) uprintf(" RETRYING...\n"); } else { break; } } if (j >= WRITE_RETRIES) goto out; i_file_length -= ISO_BLOCKSIZE; if (nb_blocks++ % PROGRESS_THRESHOLD == 0) { SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0); UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } } ISO_BLOCKING(safe_closehandle(file_handle)); if (is_syslinux_cfg) { if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label, TRUE) != NULL) uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label); } } } r = 0; out: ISO_BLOCKING(safe_closehandle(file_handle)); _cdio_list_free(p_entlist, true); return r; }
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_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, char **splitpath) { 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 = calloc(1, len); if (!p_stat) { cdio_warn("Couldn't calloc(1, %d)", len); return NULL; } 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); _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); if (!_dirbuf) { cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); return NULL; } 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, p_iso->b_xa, p_iso->u_joliet_level); cmp = strcmp(splitpath[0], p_stat->filename); if ( 0 != cmp && 0 == p_iso->u_joliet_level && yep != p_stat->rr.b3_rock ) { char *trans_fname = NULL; unsigned int i_trans_fname=strlen(p_stat->filename); 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)); free(p_stat); return NULL; } iso9660_name_translate_ext(p_stat->filename, trans_fname, p_iso->u_joliet_level); cmp = strcmp(splitpath[0], trans_fname); free(trans_fname); } } if (!cmp) { iso9660_stat_t *ret_stat = _fs_iso_stat_traverse (p_iso, 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; }
/*! Convert an ISO-9660 file name which is in the format usually stored in a ISO 9660 directory entry into what's usually listed as the file name in a listing. Lowercase name, and remove trailing ;1's or .;1's and turn the other ;'s into version numbers. @param psz_oldname the ISO-9660 filename to be translated. @param psz_newname returned string. The caller allocates this and it should be at least the size of psz_oldname. @return length of the translated string is returned. It will be no greater than the length of psz_oldname. */ int iso9660_name_translate(const char *psz_oldname, char *psz_newname) { return iso9660_name_translate_ext(psz_oldname, psz_newname, 0); }
static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) { FILE *fd = NULL; int i_length, r = 1; char psz_fullpath[4096], *psz_basename; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; unsigned char buf[ISO_BLOCKSIZE]; CdioListNode_t* p_entnode; iso9660_stat_t *p_statbuf; CdioList_t* p_entlist; size_t i; lsn_t lsn; int64_t i_file_length; if ((p_iso == NULL) || (psz_path == NULL)) return 1; i_length = snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path); if (i_length < 0) return 1; psz_basename = &psz_fullpath[i_length]; p_entlist = iso9660_ifs_readdir(p_iso, psz_path); if (!p_entlist) { printf("Could not access %s\n", psz_path); return 1; } _CDIO_LIST_FOREACH (p_entnode, p_entlist) { p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); /* Eliminate . and .. entries */ if ( (strcmp(p_statbuf->filename, ".") == 0) || (strcmp(p_statbuf->filename, "..") == 0) ) continue; iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level); if (p_statbuf->type == _STAT_DIR) { _mkdir(psz_fullpath); if (iso_extract_files(p_iso, psz_iso_name)) goto out; } else { printf("Extracting: %s\n", psz_fullpath); fd = fopen(psz_fullpath, "wb"); if (fd == NULL) { fprintf(stderr, " Unable to create file\n"); goto out; } i_file_length = p_statbuf->size; for (i = 0; i_file_length > 0; i++) { memset(buf, 0, ISO_BLOCKSIZE); lsn = p_statbuf->lsn + i; if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { fprintf(stderr, " Error reading ISO9660 file %s at LSN %lu\n", psz_iso_name, (long unsigned int)lsn); goto out; } fwrite(buf, (size_t)MIN(i_file_length, ISO_BLOCKSIZE), 1, fd); if (ferror(fd)) { fprintf(stderr, " Error writing file %s: %s\n", psz_iso_name, strerror(errno)); goto out; } i_file_length -= ISO_BLOCKSIZE; } fclose(fd); fd = NULL; } }
static void print_iso9660_recurse (iso9660_t *p_iso, const char psz_path[]) { CdioList_t *entlist; CdioList_t *dirlist = _cdio_list_new (); CdioListNode_t *entnode; uint8_t i_joliet_level = iso9660_ifs_get_joliet_level(p_iso); char *translated_name = (char *) malloc(4096); size_t translated_name_size = 4096; entlist = iso9660_ifs_readdir (p_iso, psz_path); if (opts.print_iso9660) { printf ("%s:\n", psz_path); } if (NULL == entlist) { report( stderr, "Error getting above directory information\n" ); return; } /* Iterate over files in this directory */ _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *p_statbuf = _cdio_list_node_data (entnode); char *psz_iso_name = p_statbuf->filename; char _fullname[4096] = { 0, }; if (strlen(psz_iso_name) >= translated_name_size) { translated_name_size = strlen(psz_iso_name)+1; free(translated_name); translated_name = (char *) malloc(translated_name_size); if (!translated_name) { report( stderr, "Error allocating memory\n" ); return; } } if (yep != p_statbuf->rr.b3_rock || 1 == opts.no_rock_ridge) { iso9660_name_translate_ext(psz_iso_name, translated_name, i_joliet_level); snprintf (_fullname, sizeof (_fullname), "%s%s", psz_path, translated_name); } else { snprintf (_fullname, sizeof (_fullname), "%s%s", psz_path, psz_iso_name); } strncat (_fullname, "/", sizeof (_fullname)); if (p_statbuf->type == _STAT_DIR && strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, "..")) _cdio_list_append (dirlist, strdup (_fullname)); if (opts.print_iso9660) { print_fs_attrs(p_statbuf, 0 == opts.no_rock_ridge, iso9660_ifs_is_xa(p_iso) && 0 == opts.no_xa, psz_iso_name, translated_name); } else if ( strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, "..")) printf("%9u %s%s\n", (unsigned int) p_statbuf->size, psz_path, yep == p_statbuf->rr.b3_rock ? psz_iso_name : translated_name); if (p_statbuf->rr.i_symlink) { free(p_statbuf->rr.psz_symlink); p_statbuf->rr.i_symlink = 0; } }
// Returns 0 on success, nonzero on error static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) { HANDLE file_handle = NULL; DWORD buf_size, wr_size, err; EXTRACT_PROPS props; BOOL is_symlink, is_identical; int i_length, r = 1; char tmp[128], psz_fullpath[MAX_PATH], *psz_basename, *psz_sanpath; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; unsigned char buf[ISO_BLOCKSIZE]; CdioListNode_t* p_entnode; iso9660_stat_t *p_statbuf; CdioList_t* p_entlist; size_t i; lsn_t lsn; int64_t i_file_length; if ((p_iso == NULL) || (psz_path == NULL)) return 1; i_length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path); if (i_length < 0) return 1; psz_basename = &psz_fullpath[i_length]; p_entlist = iso9660_ifs_readdir(p_iso, psz_path); if (!p_entlist) { uprintf("Could not access directory %s", psz_path); return 1; } _CDIO_LIST_FOREACH(p_entnode, p_entlist) { if (FormatStatus) goto out; p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); // Eliminate . and .. entries if ( (strcmp(p_statbuf->filename, ".") == 0) || (strcmp(p_statbuf->filename, "..") == 0) ) continue; // Rock Ridge requires an exception is_symlink = FALSE; if ((p_statbuf->rr.b3_rock == yep) && enable_rockridge) { safe_strcpy(psz_basename, sizeof(psz_fullpath)-i_length-1, p_statbuf->filename); if (safe_strlen(p_statbuf->filename) > 64) img_report.has_long_filename = TRUE; // libcdio has a memleak for Rock Ridge symlinks. It doesn't look like there's an easy fix there as // a generic list that's unaware of RR extensions is being used, so we prevent that memleak ourselves is_symlink = (p_statbuf->rr.psz_symlink != NULL); if (is_symlink) img_report.has_symlinks = TRUE; if (scan_only) safe_free(p_statbuf->rr.psz_symlink); } else { iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level); } if (p_statbuf->type == _STAT_DIR) { if (!scan_only) { psz_sanpath = sanitize_filename(psz_fullpath, &is_identical); IGNORE_RETVAL(_mkdirU(psz_sanpath)); if (preserve_timestamps) { LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm)); set_directory_timestamp(psz_sanpath, ft, ft, ft); } safe_free(psz_sanpath); } if (iso_extract_files(p_iso, psz_iso_name)) goto out; } else { i_file_length = p_statbuf->size; if (check_iso_props(psz_path, i_file_length, psz_basename, psz_fullpath, &props)) { continue; } print_extracted_file(psz_fullpath, i_file_length); for (i=0; i<NB_OLD_C32; i++) { if (props.is_old_c32[i] && use_own_c32[i]) { static_sprintf(tmp, "%s/syslinux-%s/%s", FILES_DIR, embedded_sl_version_str[0], old_c32_name[i]); if (CopyFileU(tmp, psz_fullpath, FALSE)) { uprintf(" Replaced with local version %s", IsFileInDB(tmp)?"✓":"✗"); break; } uprintf(" Could not replace file: %s", WindowsErrorString()); } } if (i < NB_OLD_C32) continue; psz_sanpath = sanitize_filename(psz_fullpath, &is_identical); if (!is_identical) uprintf(" File name sanitized to '%s'", psz_sanpath); if (is_symlink) { if (i_file_length == 0) uprintf(" Ignoring Rock Ridge symbolic link to '%s'", p_statbuf->rr.psz_symlink); safe_free(p_statbuf->rr.psz_symlink); } file_handle = CreateFileU(psz_sanpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) { err = GetLastError(); uprintf(" Unable to create file: %s", WindowsErrorString()); if ((err == ERROR_ACCESS_DENIED) && (safe_strcmp(&psz_sanpath[3], autorun_name) == 0)) uprintf(stupid_antivirus); else goto out; } else for (i=0; i_file_length>0; i++) { if (FormatStatus) goto out; memset(buf, 0, ISO_BLOCKSIZE); lsn = p_statbuf->lsn + (lsn_t)i; if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { uprintf(" Error reading ISO9660 file %s at LSN %lu", psz_iso_name, (long unsigned int)lsn); goto out; } buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); if (!r) { uprintf(" Error writing file: %s", WindowsErrorString()); goto out; } i_file_length -= ISO_BLOCKSIZE; if (nb_blocks++ % PROGRESS_THRESHOLD == 0) UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } if (preserve_timestamps) { LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm)); if (!SetFileTime(file_handle, ft, ft, ft)) uprintf(" Could not set timestamp: %s", WindowsErrorString()); } ISO_BLOCKING(safe_closehandle(file_handle)); if (props.is_syslinux_cfg || props.is_grub_cfg) fix_config(psz_sanpath, psz_path, psz_basename, &props); safe_free(psz_sanpath); } } r = 0; out: ISO_BLOCKING(safe_closehandle(file_handle)); _cdio_list_free(p_entlist, true); return r; }
static void print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[], cdio_fs_anal_t fs, bool b_mode2) { CdioList_t *entlist; CdioList_t *dirlist = _cdio_list_new (); CdioListNode_t *entnode; uint8_t i_joliet_level; i_joliet_level = (opts.no_joliet) ? 0 : cdio_get_joliet_level(p_cdio); entlist = iso9660_fs_readdir (p_cdio, pathname, b_mode2); sprintf (temp_msg, "%s:\n", pathname); report(stdout, temp_msg); if (NULL == entlist) { report( stderr, "Error getting above directory information\n" ); return; } /* Iterate over files in this directory */ _CDIO_LIST_FOREACH (entnode, entlist) { iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); char *iso_name = statbuf->filename; char _fullname[4096] = { 0, }; char translated_name[MAX_ISONAME+1]; #define DATESTR_SIZE 30 char date_str[DATESTR_SIZE]; iso9660_name_translate_ext(iso_name, translated_name, i_joliet_level); snprintf (_fullname, sizeof (_fullname), "%s%s", pathname, iso_name); strncat (_fullname, "/", sizeof (_fullname)); if (statbuf->type == _STAT_DIR && strcmp (iso_name, ".") && strcmp (iso_name, "..")) _cdio_list_append (dirlist, strdup (_fullname)); if (fs & CDIO_FS_ANAL_XA) { sprintf (temp_msg, " %c %s %d %d [fn %.2d] [LSN %6lu] ", (statbuf->type == _STAT_DIR) ? 'd' : '-', iso9660_get_xa_attr_str (statbuf->xa.attributes), uint16_from_be (statbuf->xa.user_id), uint16_from_be (statbuf->xa.group_id), statbuf->xa.filenum, (long unsigned int) statbuf->lsn); report(stdout, temp_msg); if (uint16_from_be(statbuf->xa.attributes) & XA_ATTR_MODE2FORM2) { sprintf (temp_msg, "%9u (%9u)", (unsigned int) statbuf->secsize * M2F2_SECTOR_SIZE, (unsigned int) statbuf->size); report(stdout, temp_msg); } else { printf ("%9u", (unsigned int) statbuf->size); } } strftime(date_str, DATESTR_SIZE, "%b %d %Y %H:%M ", &statbuf->tm); sprintf (temp_msg, " %s %s\n", date_str, translated_name); report(stdout, temp_msg); }
/*! Convert ISO-9660 file name that stored in a directory entry into what's usually listed as the file name in a listing. Lowercase name, and remove trailing ;1's or .;1's and turn the other ;'s into version numbers. The length of the translated string is returned. */ int iso9660_name_translate(const char *psz_old, char *psz_new) { return iso9660_name_translate_ext(psz_old, psz_new, 0); }
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; }
// Returns 0 on success, nonzero on error static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) { HANDLE file_handle = NULL; DWORD buf_size, wr_size; BOOL s, is_syslinux_cfg, is_old_vesamenu; int i_length, r = 1; char psz_fullpath[1024], *psz_basename; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; unsigned char buf[ISO_BLOCKSIZE]; CdioListNode_t* p_entnode; iso9660_stat_t *p_statbuf; CdioList_t* p_entlist; size_t i, nul_pos; lsn_t lsn; int64_t i_file_length; if ((p_iso == NULL) || (psz_path == NULL)) return 1; i_length = safe_sprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path); if (i_length < 0) return 1; psz_basename = &psz_fullpath[i_length]; p_entlist = iso9660_ifs_readdir(p_iso, psz_path); if (!p_entlist) { uprintf("Could not access directory %s\n", psz_path); return 1; } _CDIO_LIST_FOREACH(p_entnode, p_entlist) { if (FormatStatus) goto out; p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); /* Eliminate . and .. entries */ if ( (strcmp(p_statbuf->filename, ".") == 0) || (strcmp(p_statbuf->filename, "..") == 0) ) continue; iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level); if (p_statbuf->type == _STAT_DIR) { if (!scan_only) _mkdirU(psz_fullpath); if (iso_extract_files(p_iso, psz_iso_name)) goto out; } else { i_file_length = p_statbuf->size; if (check_iso_props(psz_path, &is_syslinux_cfg, &is_old_vesamenu, i_file_length, psz_basename, psz_fullpath)) { continue; } // Replace slashes with backslashes and append the size to the path for UI display nul_pos = safe_strlen(psz_fullpath); for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '/') psz_fullpath[i] = '\\'; safe_strcpy(&psz_fullpath[nul_pos], 24, size_to_hr(i_file_length)); uprintf("Extracting: %s\n", psz_fullpath); SetWindowTextU(hISOFileName, psz_fullpath); // ISO9660 cannot handle backslashes for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '\\') psz_fullpath[i] = '/'; psz_fullpath[nul_pos] = 0; if (is_old_vesamenu && use_own_vesamenu) { if (CopyFileA("vesamenu.c32", psz_fullpath, FALSE)) { uprintf(" Replaced with local version\n"); continue; } uprintf(" Could not replace file: %s\n", WindowsErrorString()); } file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) { uprintf(" Unable to create file: %s\n", WindowsErrorString()); goto out; } for (i = 0; i_file_length > 0; i++) { if (FormatStatus) goto out; memset(buf, 0, ISO_BLOCKSIZE); lsn = p_statbuf->lsn + (lsn_t)i; if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { uprintf(" Error reading ISO9660 file %s at LSN %lu\n", psz_iso_name, (long unsigned int)lsn); goto out; } buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); ISO_BLOCKING(s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL)); if ((!s) || (buf_size != wr_size)) { uprintf(" Error writing file: %s\n", WindowsErrorString()); goto out; } i_file_length -= ISO_BLOCKSIZE; if (nb_blocks++ % PROGRESS_THRESHOLD == 0) { SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0); UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } } ISO_BLOCKING(safe_closehandle(file_handle)); if (is_syslinux_cfg) { if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label, TRUE) != NULL) uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label); } } } r = 0; out: ISO_BLOCKING(safe_closehandle(file_handle)); _cdio_list_free(p_entlist, true); return r; }