Exemple #1
0
int
main(int argc, const char *argv[])
{
  udf_t *p_udf;
  char const *psz_udf_image;

  if (argc > 1) 
    psz_udf_image = argv[1];
  else 
    psz_udf_image = UDF_IMAGE;

  p_udf = udf_open (psz_udf_image);
  
  if (NULL == p_udf) {
    fprintf(stderr, "Sorry, couldn't open %s as something using UDF\n", 
	    psz_udf_image);
    return 1;
  } else {
    udf_dirent_t *p_udf_root = udf_get_root(p_udf, true, 0);
    if (NULL == p_udf_root) {
      fprintf(stderr, "Sorry, couldn't find / in %s\n", 
	      psz_udf_image);
      return 1;
    }
    
    {
      char vol_id[UDF_VOLID_SIZE] = "";
      char volset_id[UDF_VOLSET_ID_SIZE+1] = "";
      
      if (0 < udf_get_volume_id(p_udf, vol_id, sizeof(vol_id)) )
	printf("volume id: %s\n", vol_id);

      if (0 < udf_get_volume_id(p_udf, volset_id, sizeof(volset_id)) ) {
	volset_id[UDF_VOLSET_ID_SIZE]='\0';
	printf("volume set id: %s\n", volset_id);
      }

      printf("partition number: %d\n", udf_get_part_number(p_udf));


    }
    
    list_files(p_udf, p_udf_root, "");
  }
  
  udf_close(p_udf);
  return 0;
}
Exemple #2
0
int64_t ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file)
{
	size_t i;
	ssize_t read_size;
	int64_t file_length, r = 0;
	char buf[UDF_BLOCKSIZE];
	DWORD buf_size, wr_size;
	BOOL s;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL; 
	udf_dirent_t *p_udf_root = NULL, *p_udf_file = NULL;
	iso9660_stat_t *p_statbuf = NULL;
	lsn_t lsn;
	HANDLE file_handle = INVALID_HANDLE_VALUE;

	file_handle = CreateFileU(dest_file, 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: %s\n", dest_file, WindowsErrorString());
		goto out;
	}

	/* First try to open as UDF - fallback to ISO if it failed */
	p_udf = udf_open(iso);
	if (p_udf == NULL)
		goto try_iso;

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("Couldn't locate UDF root directory\n");
		goto out;
	}
	p_udf_file = udf_fopen(p_udf_root, iso_file);
	if (!p_udf_file) {
		uprintf("Couldn't locate file %s in ISO image\n", iso_file);
		goto out;
	}
	file_length = udf_get_file_length(p_udf_file);
	while (file_length > 0) {
		memset(buf, 0, UDF_BLOCKSIZE);
		read_size = udf_read_block(p_udf_file, buf, 1);
		if (read_size < 0) {
			uprintf("Error reading UDF file %s\n", iso_file);
			goto out;
		}
		buf_size = (DWORD)MIN(file_length, read_size);
		s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL);
		if ((!s) || (buf_size != wr_size)) {
			uprintf("  Error writing file %s: %s\n", dest_file, WindowsErrorString());
			goto out;
		}
		file_length -= read_size;
		r += read_size;
	}
	goto out;

try_iso:
	p_iso = iso9660_open(iso);
	if (p_iso == NULL) {
		uprintf("Unable to open image '%s'.\n", iso);
		goto out;
	}

	p_statbuf = iso9660_ifs_stat_translate(p_iso, iso_file);
	if (p_statbuf == NULL) {
		uprintf("Could not get ISO-9660 file information for file %s\n", iso_file);
		goto out;
	}

	file_length = p_statbuf->size;
	for (i = 0; file_length > 0; i++) {
		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", iso_file, (long unsigned int)lsn);
			goto out;
		}
		buf_size = (DWORD)MIN(file_length, ISO_BLOCKSIZE);
		s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL);
		if ((!s) || (buf_size != wr_size)) {
			uprintf("  Error writing file %s: %s\n", dest_file, WindowsErrorString());
			goto out;
		}
		file_length -= ISO_BLOCKSIZE;
		r += ISO_BLOCKSIZE;
	}

out:
	safe_closehandle(file_handle);
	if (p_statbuf != NULL)
		safe_free(p_statbuf->rr.psz_symlink);
	safe_free(p_statbuf);
	if (p_udf_root != NULL)
		udf_dirent_free(p_udf_root);
	if (p_udf_file != NULL)
		udf_dirent_free(p_udf_file);
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	return r;
}
Exemple #3
0
int main(int argc, char** argv)
{
  iso9660_t* p_iso = NULL;
  udf_t* p_udf = NULL;
  udf_dirent_t* p_udf_root;
  char *psz_str = NULL;
  char vol_id[UDF_VOLID_SIZE] = "";
  char volset_id[UDF_VOLSET_ID_SIZE+1] = "";
  int r = 0;

  cdio_log_set_handler (log_handler);

  if (argc < 3) {
    fprintf(stderr, "Usage: extract <iso_image> <extraction_dir>\n");
    return 1;
  }

  /* Warn if LFS doesn't appear to be enabled */
  if (sizeof(off_t) < 8) {
    fprintf(stderr, "INFO: Large File Support not detected (required for files >2GB)\n");
  }

  psz_extract_dir = argv[2];
  if (_mkdir(psz_extract_dir) == 0) {
    printf("-- Creating directory: %s\n", psz_extract_dir);
  } else if (errno != EEXIST) {
    fprintf(stderr, "Unable to create extraction directory %s\n", psz_extract_dir);
    return 1;
  }

  /* First try to open as UDF - fallback to ISO if it failed */
  p_udf = udf_open(argv[1]);
  if (p_udf == NULL)
    goto try_iso;

  p_udf_root = udf_get_root(p_udf, true, 0);
  if (p_udf_root == NULL) {
    fprintf(stderr, "Couldn't locate UDF root directory\n");
    goto out;
  }
  vol_id[0] = 0; volset_id[0] = 0;

  /* Show basic UDF Volume info */
  if (udf_get_volume_id(p_udf, vol_id, sizeof(vol_id)) > 0)
    printf("-- Volume id: %s\n", vol_id);
  if (udf_get_volume_id(p_udf, volset_id, sizeof(volset_id)) >0 ) {
    volset_id[UDF_VOLSET_ID_SIZE]='\0';
    printf("-- Volume set id: %s\n", volset_id);
  }
  printf("-- Partition number: %d\n", udf_get_part_number(p_udf));

  /* Recursively extract files */
  r = udf_extract_files(p_udf, p_udf_root, "");

  goto out;

try_iso:
  p_iso = iso9660_open_ext(argv[1], ISO_EXTENSION_ALL);
  if (p_iso == NULL) {
    fprintf(stderr, "Unable to open image '%s'.\n", argv[1]);
    r = 1;
    goto out;
  }
  i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);

  /* Show basic ISO9660 info from the Primary Volume Descriptor. */
  print_vd_info("Application", iso9660_ifs_get_application_id);
  print_vd_info("Preparer   ", iso9660_ifs_get_preparer_id);
  print_vd_info("Publisher  ", iso9660_ifs_get_publisher_id);
  print_vd_info("System     ", iso9660_ifs_get_system_id);
  print_vd_info("Volume     ", iso9660_ifs_get_volume_id);
  print_vd_info("Volume Set ", iso9660_ifs_get_volumeset_id);

  r = iso_extract_files(p_iso, "");

out:
  if (p_iso != NULL)
    iso9660_close(p_iso);
  if (p_udf != NULL)
    udf_close(p_udf);

  return r;
}
Exemple #4
0
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
{
	size_t i, size;
	int j;
	uint16_t sl_version;
	FILE* fd;
	int r = 1;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL; 
	udf_dirent_t* p_udf_root;
	char *tmp, *buf, *ext;
	char path[MAX_PATH], path2[16];
	const char* basedir[] = { "i386", "minint" };
	const char* tmp_sif = ".\\txtsetup.sif~";
	iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;

	if ((!enable_iso) || (src_iso == NULL) || (dest_dir == NULL))
		return FALSE;

	scan_only = scan;
	cdio_log_set_handler(log_handler);
	psz_extract_dir = dest_dir;
	// Change progress style to marquee for scanning
	if (scan_only) {
		SendMessage(hMainDialog, UM_PROGRESS_INIT, PBS_MARQUEE, 0);
		total_blocks = 0;
		memset(&iso_report, 0, sizeof(iso_report));
		has_ldlinux_c32 = FALSE;
		// String array of all isolinux/syslinux locations
		StrArrayCreate(&config_path, 8);
		StrArrayCreate(&isolinux_path, 8);
		PrintInfo(0, MSG_202);
	} else {
		uprintf("Extracting files...\n");
		IGNORE_RETVAL(_chdirU(app_dir));
		PrintInfo(0, MSG_231);
		if (total_blocks == 0) {
			uprintf("Error: ISO has not been properly scanned.\n");
			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
			goto out;
		}
		nb_blocks = 0;
		iso_blocking_status = 0;
	}

	/* First try to open as UDF - fallback to ISO if it failed */
	p_udf = udf_open(src_iso);
	if (p_udf == NULL)
		goto try_iso;
	uprintf("Disc image is an UDF image\n");

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("Could not locate UDF root directory\n");
		goto out;
	}
	if (scan_only) {
		if (udf_get_logical_volume_id(p_udf, iso_report.label, sizeof(iso_report.label)) <= 0)
			iso_report.label[0] = 0;
	}
	r = udf_extract_files(p_udf, p_udf_root, "");
	goto out;

try_iso:
	// Perform our first scan with Joliet disabled (if Rock Ridge is enabled), so that we can find if
	// there exists a Rock Ridge file with a name > 64 chars or if there are symlinks. If that is the
	// case then we also disable Joliet during the extract phase.
	if ((!enable_joliet) || (enable_rockridge && (scan_only || iso_report.has_long_filename || iso_report.has_symlinks))) {
		iso_extension_mask &= ~ISO_EXTENSION_JOLIET;
	}
	if (!enable_rockridge) {
		iso_extension_mask &= ~ISO_EXTENSION_ROCK_RIDGE;
	}

	p_iso = iso9660_open_ext(src_iso, iso_extension_mask);
	if (p_iso == NULL) {
		uprintf("'%s' doesn't look like an ISO image\n", src_iso);
		r = 1;
		goto out;
	}
	uprintf("Disc image is an ISO9660 image\n");
	i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
	if (scan_only) {
		if (iso9660_ifs_get_volume_id(p_iso, &tmp)) {
			safe_strcpy(iso_report.label, sizeof(iso_report.label), tmp);
			safe_free(tmp);
		} else
			iso_report.label[0] = 0;
	} else {
		if (iso_extension_mask & (ISO_EXTENSION_JOLIET|ISO_EXTENSION_ROCK_RIDGE))
			uprintf("This image will be extracted using %s extensions (if present)", 
				(iso_extension_mask & ISO_EXTENSION_JOLIET)?"Joliet":"Rock Ridge");
		else
			uprintf("This image will not be extracted using any ISO extensions");
	}
	r = iso_extract_files(p_iso, "");

out:
	iso_blocking_status = -1;
	if (scan_only) {
		// Remove trailing spaces from the label
		for (j=(int)safe_strlen(iso_report.label)-1; ((j>=0)&&(isspaceU(iso_report.label[j]))); j--)
			iso_report.label[j] = 0;
		// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
		iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
		// We will link the existing isolinux.cfg from a syslinux.cfg we create
		// If multiple config files exist, choose the one with the shortest path
		// (so that a '/syslinux.cfg' is preferred over a '/isolinux/isolinux.cfg')
		if (!IsStrArrayEmpty(config_path)) {
			// Set the iso_report.cfg_path string to maximum length, so that we don't have to
			// do a special case for StrArray entry 0.
			memset(iso_report.cfg_path, '_', sizeof(iso_report.cfg_path)-1);
			iso_report.cfg_path[sizeof(iso_report.cfg_path)-1] = 0;
			for (i=0; i<config_path.Index; i++) {
				// OpenSuse based Live image have a /syslinux.cfg that doesn't work, so we enforce
				// the use of the one in '/boot/[i386|x86_64]/loader/isolinux.cfg' if present.
				// Note that, because the openSuse live script are not designed to handle anything but
				// an ISO9660 filesystem for the live device, this still won't allow for proper boot.
				// See https://github.com/openSUSE/kiwi/issues/354
				if ( (_stricmp(config_path.String[i], "/boot/i386/loader/isolinux.cfg") == 0) ||
					 (_stricmp(config_path.String[i], "/boot/x86_64/loader/isolinux.cfg") == 0)) {
					safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.String[i]);
					iso_report.needs_syslinux_overwrite = TRUE;
					break;
				}
				// Tails uses an '/EFI/BOOT/isolinux.cfg' along with a '/isolinux/isolinux.cfg'
				// which are the exact same length. However, only the /isolinux one will work,
				// so for now, at equal length, always pick the latest.
				// We may have to revisit this and prefer a path that contains '/isolinux' if
				// this hack is not enough for other images.
				if (safe_strlen(iso_report.cfg_path) >= safe_strlen(config_path.String[i]))
					safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.String[i]);
			}
			uprintf("Will use '%s' for Syslinux\n", iso_report.cfg_path);
			// Extract all of the isolinux.bin files we found to identify their versions
			for (i=0; i<isolinux_path.Index; i++) {
				size = (size_t)ExtractISOFile(src_iso, isolinux_path.String[i], dot_isolinux_bin, FILE_ATTRIBUTE_NORMAL);
				if (size == 0) {
					uprintf("Could not access %s\n", isolinux_path.String[i]);
				} else {
					buf = (char*)calloc(size, 1);
					if (buf == NULL) break;
					fd = fopen(dot_isolinux_bin, "rb");
					if (fd == NULL) {
						free(buf);
						continue;
					}
					fread(buf, 1, size, fd);
					fclose(fd);
					sl_version = GetSyslinuxVersion(buf, size, &ext);
					if (iso_report.sl_version == 0) {
						safe_strcpy(iso_report.sl_version_ext, sizeof(iso_report.sl_version_ext), ext);
						iso_report.sl_version = sl_version;
						j = (int)i;
					} else if ((iso_report.sl_version != sl_version) || (safe_strcmp(iso_report.sl_version_ext, ext) != 0)) {
						uprintf("Found conflicting %s versions:\n  '%s' (%d.%02d%s) vs '%s' (%d.%02d%s)\n", isolinux_bin,
							isolinux_path.String[j], SL_MAJOR(iso_report.sl_version), SL_MINOR(iso_report.sl_version),
							iso_report.sl_version_ext, isolinux_path.String[i], SL_MAJOR(sl_version), SL_MINOR(sl_version), ext);
					}
					free(buf);
					_unlink(dot_isolinux_bin);
				}
			}
			if (iso_report.sl_version != 0) {
				static_sprintf(iso_report.sl_version_str, "%d.%02d",
					SL_MAJOR(iso_report.sl_version), SL_MINOR(iso_report.sl_version));
				uprintf("Detected Isolinux version: %s%s (from '%s')",
					iso_report.sl_version_str, iso_report.sl_version_ext, isolinux_path.String[j]);
				if ( (has_ldlinux_c32 && (SL_MAJOR(iso_report.sl_version) < 5))
				  || (!has_ldlinux_c32 && (SL_MAJOR(iso_report.sl_version) >= 5)) )
					uprintf("Warning: Conflict between Isolinux version and the presence of ldlinux.c32...\n");
			} else {
				// Couldn't find a version from isolinux.bin. Force set to the versions we embed
				iso_report.sl_version = embedded_sl_version[has_ldlinux_c32?1:0];
				static_sprintf(iso_report.sl_version_str, "%d.%02d",
					SL_MAJOR(iso_report.sl_version), SL_MINOR(iso_report.sl_version));
				uprintf("Warning: Could not detect Isolinux version - Forcing to %s (embedded)",
					iso_report.sl_version_str);
			}
		}
		if (IS_WINPE(iso_report.winpe)) {
			// In case we have a WinPE 1.x based iso, we extract and parse txtsetup.sif
			// during scan, to see if /minint was provided for OsLoadOptions, as it decides
			// whether we should use 0x80 or 0x81 as the disk ID in the MBR
			safe_sprintf(path, sizeof(path), "/%s/txtsetup.sif", 
				basedir[((iso_report.winpe&WINPE_I386) == WINPE_I386)?0:1]);
			ExtractISOFile(src_iso, path, tmp_sif, FILE_ATTRIBUTE_NORMAL);
			tmp = get_token_data_file("OsLoadOptions", tmp_sif);
			if (tmp != NULL) {
				for (i=0; i<strlen(tmp); i++)
					tmp[i] = (char)tolower(tmp[i]);
				uprintf("Checking txtsetup.sif:\n  OsLoadOptions = %s\n", tmp);
				iso_report.uses_minint = (strstr(tmp, "/minint") != NULL);
			}
			_unlink(tmp_sif);
			safe_free(tmp);
		}
		if (iso_report.has_grub2) {
			// In case we have a GRUB2 based iso, we extract boot/grub/i386-pc/normal.mod to parse its version
			iso_report.grub2_version[0] = 0;
			if ((GetTempPathU(sizeof(path), path) != 0) && (GetTempFileNameU(path, APPLICATION_NAME, 0, path) != 0)) {
				size = (size_t)ExtractISOFile(src_iso, "boot/grub/i386-pc/normal.mod", path, FILE_ATTRIBUTE_NORMAL);
				buf = (char*)calloc(size, 1);
				fd = fopen(path, "rb");
				if ((size == 0) || (buf == NULL) || (fd == NULL)) {
					uprintf("Could not read Grub version from 'boot/grub/i386-pc/normal.mod'");
				} else {
					fread(buf, 1, size, fd);
					fclose(fd);
					GetGrubVersion(buf, size);
				}
				free(buf);
				_unlink(path);
			}
			if (iso_report.grub2_version[0] != 0)
				uprintf("Detected Grub version: %s", iso_report.grub2_version);
			else {
				uprintf("Could not detect Grub version");
				iso_report.has_grub2 = FALSE;
			}
		}
		StrArrayDestroy(&config_path);
		StrArrayDestroy(&isolinux_path);
		SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0);
	} else if (HAS_SYSLINUX(iso_report)) {
		safe_sprintf(path, sizeof(path), "%s\\syslinux.cfg", dest_dir);
		// Create a /syslinux.cfg (if none exists) that points to the existing isolinux cfg
		fd = fopen(path, "r");
		if (fd != NULL && iso_report.needs_syslinux_overwrite) {
			fclose(fd);
			fd = NULL;
			safe_sprintf(path2, sizeof(path2), "%s\\syslinux.org", dest_dir);
			uprintf("Renaming: %s ⇨ %s", path, path2);
			IGNORE_RETVAL(rename(path, path2));
		}
		if (fd == NULL) {
			fd = fopen(path, "w");	// No "/syslinux.cfg" => create a new one
			if (fd == NULL) {
				uprintf("Unable to create %s - booting from USB will not work\n", path);
				r = 1;
			} else {
				fprintf(fd, "DEFAULT loadconfig\n\nLABEL loadconfig\n  CONFIG %s\n", iso_report.cfg_path);
				for (i=safe_strlen(iso_report.cfg_path); (i>0)&&(iso_report.cfg_path[i]!='/'); i--);
				if (i>0) {
					iso_report.cfg_path[i] = 0;
					fprintf(fd, "  APPEND %s/\n", iso_report.cfg_path);
					iso_report.cfg_path[i] = '/';
				}
				uprintf("Created: %s\n", path);
			}
		}
		if (fd != NULL)
			fclose(fd);
	}
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	if ((r != 0) && (FormatStatus == 0))
		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
	return (r == 0);
}
Exemple #5
0
uint32_t GetInstallWimVersion(const char* iso)
{
	char *wim_path = NULL, *p, buf[UDF_BLOCKSIZE] = { 0 };
	uint32_t* wim_header = (uint32_t*)buf, r = 0xffffffff;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL;
	udf_dirent_t *p_udf_root = NULL, *p_udf_file = NULL;
	iso9660_stat_t *p_statbuf = NULL;

	wim_path = safe_strdup(&img_report.install_wim_path[2]);
	if (wim_path == NULL)
		goto out;
	// UDF indiscriminately accepts slash or backslash delimiters,
	// but ISO-9660 requires slash
	for (p = wim_path; *p != 0; p++)
		if (*p == '\\') *p = '/';

	// First try to open as UDF - fallback to ISO if it failed
	p_udf = udf_open(iso);
	if (p_udf == NULL)
		goto try_iso;

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("Could not locate UDF root directory\n");
		goto out;
	}
	p_udf_file = udf_fopen(p_udf_root, wim_path);
	if (!p_udf_file) {
		uprintf("Could not locate file %s in ISO image\n", wim_path);
		goto out;
	}
	if (udf_read_block(p_udf_file, buf, 1) != UDF_BLOCKSIZE) {
		uprintf("Error reading UDF file %s\n", wim_path);
		goto out;
	}
	r = wim_header[3];
	goto out;

try_iso:
	p_iso = iso9660_open(iso);
	if (p_iso == NULL) {
		uprintf("Unable to open image '%s'.\n", iso);
		goto out;
	}
	p_statbuf = iso9660_ifs_stat_translate(p_iso, wim_path);
	if (p_statbuf == NULL) {
		uprintf("Could not get ISO-9660 file information for file %s\n", wim_path);
		goto out;
	}
	if (iso9660_iso_seek_read(p_iso, buf, p_statbuf->lsn, 1) != ISO_BLOCKSIZE) {
		uprintf("Error reading ISO9660 file %s at LSN %lu\n", wim_path, (long unsigned int)p_statbuf->lsn);
		goto out;
	}
	r = wim_header[3];

out:
	if (p_statbuf != NULL)
		safe_free(p_statbuf->rr.psz_symlink);
	safe_free(p_statbuf);
	if (p_udf_root != NULL)
		udf_dirent_free(p_udf_root);
	if (p_udf_file != NULL)
		udf_dirent_free(p_udf_file);
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	safe_free(wim_path);
	return bswap_uint32(r);
}
Exemple #6
0
int
main(int argc, const char *argv[])
{
  udf_t *p_udf;
  FILE *p_outfd;
  char const *psz_udf_image;
  char const *psz_udf_fname;
  char const *psz_local_fname;

  if (argc > 1) 
    psz_udf_image = argv[1];
  else 
    psz_udf_image = UDF_IMAGE;

  if (argc > 2) 
    psz_udf_fname = argv[2];
  else 
    psz_udf_fname = UDF_FILENAME;

  if (argc > 3) 
    psz_local_fname = argv[3];
  else 
    psz_local_fname = LOCAL_FILENAME;


  p_udf = udf_open (psz_udf_image);
  
  if (NULL == p_udf) {
    fprintf(stderr, "Sorry, couldn't open %s as something using UDF\n", 
	    psz_udf_image);
    return 1;
  } else {
    udf_dirent_t *p_udf_root = udf_get_root(p_udf, true, 0);
    udf_dirent_t *p_udf_file = NULL;
    if (NULL == p_udf_root) {
      fprintf(stderr, "Sorry, couldn't find / in %s\n", 
	      psz_udf_image);
      return 1;
    }
    
    p_udf_file = udf_fopen(p_udf_root, psz_udf_fname);
    if (!p_udf_file) {
      fprintf(stderr, "Sorry, couldn't find %s in %s\n", 
	      psz_udf_fname, psz_udf_image);
      return 2;
      
    }

    if (!(p_outfd = fopen (psz_local_fname, "wb")))
      {
	perror ("fopen()");
	return 3;
    }

    {
      uint64_t i_file_length = udf_get_file_length(p_udf_file);
      const unsigned int i_blocks = (unsigned int) CEILING(i_file_length, UDF_BLOCKSIZE);
      unsigned int i;
      for (i = 0; i < i_blocks ; i++) {
	char buf[UDF_BLOCKSIZE] = {'\0',};
	ssize_t i_read = udf_read_block(p_udf_file, buf, 1);

	if ( i_read < 0 ) {
	  fprintf(stderr, "Error reading UDF file %s at block %u\n",
		  psz_local_fname, i);
	  return 4;
	}

	fwrite (buf, i_read, 1, p_outfd);

	if (ferror (p_outfd)) {
	  perror ("fwrite()");
	  return 5;
	}
      }

      fflush (p_outfd);
      udf_dirent_free(p_udf_root);
      udf_close(p_udf);
      /* Make sure the file size has the exact same byte size. Without the
	 truncate below, the file will a multiple of UDF_BLOCKSIZE.
      */
      if (ftruncate (fileno (p_outfd), i_file_length))
	perror ("ftruncate()");
      
      printf("Extraction of file '%s' from %s successful.\n", 
	     psz_local_fname, psz_udf_image);
      
      return 0;
    }
  }
}
Exemple #7
0
BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan)
{
	size_t i;
	int j;
	FILE* fd;
	BOOL r = FALSE;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL; 
	udf_dirent_t* p_udf_root;
	LONG progress_style;
	char* tmp;
	char path[64];
	const char* scan_text = "Scanning ISO image...";
	const char* basedir[] = { "i386", "minint" };
	const char* tmp_sif = ".\\txtsetup.sif~";

	if ((src_iso == NULL) || (dest_dir == NULL))
		return FALSE;

	scan_only = scan;
	cdio_log_set_handler(log_handler);
	psz_extract_dir = dest_dir;
	progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE);
	if (scan_only) {
		total_blocks = 0;
		memset(&iso_report, 0, sizeof(iso_report));
		// String array of all isolinux/syslinux locations
		StrArrayCreate(&config_path, 8);
		// Change the Window title and static text
		SetWindowTextU(hISOProgressDlg, scan_text);
		SetWindowTextU(hISOFileName, scan_text);
		// Change progress style to marquee for scanning
		SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style | PBS_MARQUEE);
		SendMessage(hISOProgressBar, PBM_SETMARQUEE, TRUE, 0);
	} else {
		uprintf("Extracting files...\n");
		if (total_blocks == 0) {
			uprintf("Error: ISO has not been properly scanned.\n");
			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
			goto out;
		}
		nb_blocks = 0;
		iso_blocking_status = 0;
		SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
		SendMessage(hISOProgressBar, PBM_SETPOS, 0, 0);
	}
	ShowWindow(hISOProgressDlg, SW_SHOW);
	UpdateWindow(hISOProgressDlg);

	/* First try to open as UDF - fallback to ISO if it failed */
	p_udf = udf_open(src_iso);
	if (p_udf == NULL)
		goto try_iso;
	uprintf("Disc image is an UDF image\n");

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("Couldn't locate UDF root directory\n");
		goto out;
	}
	if (scan_only) {
		if (udf_get_logical_volume_id(p_udf, iso_report.label, sizeof(iso_report.label)) <= 0)
			iso_report.label[0] = 0;
	}
	r = udf_extract_files(p_udf, p_udf_root, "");
	goto out;

try_iso:
	p_iso = iso9660_open_ext(src_iso, ISO_EXTENSION_ALL);
	if (p_iso == NULL) {
		uprintf("Unable to open image '%s'.\n", src_iso);
		goto out;
	}
	i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
	uprintf("Disc image is an ISO9660 image\n");
	if (scan_only) {
		if (iso9660_ifs_get_volume_id(p_iso, &tmp)) {
			safe_strcpy(iso_report.label, sizeof(iso_report.label), tmp);
			safe_free(tmp);
		} else
			iso_report.label[0] = 0;
	}
	r = iso_extract_files(p_iso, "");

out:
	iso_blocking_status = -1;
	if (scan_only) {
		// Remove trailing spaces from the label
		for (j=safe_strlen(iso_report.label)-1; ((j>=0)&&(isspace(iso_report.label[j]))); j--)
			iso_report.label[j] = 0;
		// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
		iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
		// We will link the existing isolinux.cfg from a syslinux.cfg we create
		// If multiple config file exist, choose the one with the shortest path
		if (iso_report.has_isolinux) {
			safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.Table[0]);
			for (i=1; i<config_path.Index; i++) {
				if (safe_strlen(iso_report.cfg_path) > safe_strlen(config_path.Table[i]))
					safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.Table[i]);
			}
			uprintf("Will use %s for Syslinux\n", iso_report.cfg_path);
		}
		if (IS_WINPE(iso_report.winpe)) {
			// In case we have a WinPE 1.x based iso, we extract and parse txtsetup.sif
			// during scan, to see if /minint was provided for OsLoadOptions, as it decides
			// whether we should use 0x80 or 0x81 as the disk ID in the MBR
			safe_sprintf(path, sizeof(path), "/%s/txtsetup.sif", 
				basedir[((iso_report.winpe&WINPE_I386) == WINPE_I386)?0:1]);
			ExtractISOFile(src_iso, path, tmp_sif);
			tmp = get_token_data(tmp_sif, "OsLoadOptions");
			if (tmp != NULL) {
				for (i=0; i<strlen(tmp); i++)
					tmp[i] = (char)tolower(tmp[i]);
				uprintf("Checking txtsetup.sif:\n  OsLoadOptions = %s\n", tmp);
				iso_report.uses_minint = (strstr(tmp, "/minint") != NULL);
			}
			_unlink(tmp_sif);
			safe_free(tmp);
		}
		StrArrayDestroy(&config_path);
	} else if (iso_report.has_isolinux) {
		safe_sprintf(path, sizeof(path), "%s\\syslinux.cfg", dest_dir);
		// Create a /syslinux.cfg (if none exists) that points to the existing isolinux cfg
		fd = fopen(path, "r");
		if (fd == NULL) {
			fd = fopen(path, "w");	// No "/syslinux.cfg" => create a new one
			if (fd == NULL) {
				uprintf("Unable to create %s - booting from USB will not work\n", path);
				r = 1;
			} else {
				fprintf(fd, "DEFAULT loadconfig\n\nLABEL loadconfig\n  CONFIG %s\n", iso_report.cfg_path);
				for (i=safe_strlen(iso_report.cfg_path); (i>0)&&(iso_report.cfg_path[i]!='/'); i--);
				if (i>0) {
					iso_report.cfg_path[i] = 0;
					fprintf(fd, "  APPEND %s/\n", iso_report.cfg_path);
					iso_report.cfg_path[i] = '/';
				}
				uprintf("Created: %s\n", path);
			}
		}
		if (fd != NULL)
			fclose(fd);
	}
	ShowWindow(hISOProgressDlg, SW_HIDE);
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	if ((r != 0) && (FormatStatus == 0))
		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
	return (r == 0);
}
Exemple #8
-2
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
{
	size_t i, k, size;
	int j;
	uint16_t sl_version;
	FILE* fd;
	int r = 1;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL; 
	udf_dirent_t* p_udf_root;
	LONG progress_style;
	char *tmp, *buf;
	char path[MAX_PATH];
	const char* basedir[] = { "i386", "minint" };
	const char* tmp_sif = ".\\txtsetup.sif~";
	const char ISOLINUX[] = { 'I', 'S', 'O', 'L', 'I', 'N', 'U', 'X', ' ' };
	iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;

	if ((src_iso == NULL) || (dest_dir == NULL))
		return FALSE;

	scan_only = scan;
	cdio_log_set_handler(log_handler);
	psz_extract_dir = dest_dir;
	progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE);
	if (scan_only) {
		total_blocks = 0;
		memset(&iso_report, 0, sizeof(iso_report));
		has_ldlinux_c32 = FALSE;
		// String array of all isolinux/syslinux locations
		StrArrayCreate(&config_path, 8);
		StrArrayCreate(&isolinux_path, 8);
		// Change the Window title and static text
		SetWindowTextU(hISOProgressDlg, lmprintf(MSG_202));
		SetWindowTextU(hISOFileName, lmprintf(MSG_202));
		// Change progress style to marquee for scanning
		SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style | PBS_MARQUEE);
		SendMessage(hISOProgressBar, PBM_SETMARQUEE, TRUE, 0);
	} else {
		uprintf("Extracting files...\n");
		IGNORE_RETVAL(_chdirU(app_dir));
		SetWindowTextU(hISOProgressDlg, lmprintf(MSG_231));
		if (total_blocks == 0) {
			uprintf("Error: ISO has not been properly scanned.\n");
			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
			goto out;
		}
		nb_blocks = 0;
		iso_blocking_status = 0;
		SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
		SendMessage(hISOProgressBar, PBM_SETPOS, 0, 0);
	}
	SendMessage(hISOProgressDlg, UM_ISO_INIT, 0, 0);

	/* First try to open as UDF - fallback to ISO if it failed */
	p_udf = udf_open(src_iso);
	if (p_udf == NULL)
		goto try_iso;
	uprintf("Disc image is an UDF image\n");

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("Couldn't locate UDF root directory\n");
		goto out;
	}
	if (scan_only) {
		if (udf_get_logical_volume_id(p_udf, iso_report.label, sizeof(iso_report.label)) <= 0)
			iso_report.label[0] = 0;
	}
	r = udf_extract_files(p_udf, p_udf_root, "");
	goto out;

try_iso:
	// Perform our first scan with Joliet disabled (if Rock Ridge is enabled), so that we can find if
	// there exists a Rock Ridge file with a name > 64 chars or if there are symlinks. If that is the
	// case then we also disable Joliet during the extract phase.
	if ((!enable_joliet) || (enable_rockridge && (scan_only || iso_report.has_long_filename || iso_report.has_symlinks))) {
		iso_extension_mask &= ~ISO_EXTENSION_JOLIET;
	}
	if (!enable_rockridge) {
		iso_extension_mask &= ~ISO_EXTENSION_ROCK_RIDGE;
	}

	p_iso = iso9660_open_ext(src_iso, iso_extension_mask);
	if (p_iso == NULL) {
		uprintf("Unable to open '%s' as an ISO image.\n", src_iso);
		r = 1;
		goto out;
	}
	uprintf("Disc image is an ISO9660 image\n");
	i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
	if (scan_only) {
		if (iso9660_ifs_get_volume_id(p_iso, &tmp)) {
			safe_strcpy(iso_report.label, sizeof(iso_report.label), tmp);
			safe_free(tmp);
		} else
			iso_report.label[0] = 0;
	} else {
		if (iso_extension_mask & (ISO_EXTENSION_JOLIET|ISO_EXTENSION_ROCK_RIDGE))
			uprintf("This image will be extracted using %s extensions (if present)", 
				(iso_extension_mask & ISO_EXTENSION_JOLIET)?"Joliet":"Rock Ridge");
		else
			uprintf("This image will not be extracted using any ISO extensions");
	}
	r = iso_extract_files(p_iso, "");

out:
	iso_blocking_status = -1;
	if (scan_only) {
		// Remove trailing spaces from the label
		for (j=(int)safe_strlen(iso_report.label)-1; ((j>=0)&&(isspaceU(iso_report.label[j]))); j--)
			iso_report.label[j] = 0;
		// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
		iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
		// We will link the existing isolinux.cfg from a syslinux.cfg we create
		// If multiple config files exist, choose the one with the shortest path
		// (so that a '/syslinux.cfg' is preferred over a '/isolinux/isolinux.cfg')
		if (!IsStrArrayEmpty(config_path)) {
			safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.String[0]);
			for (i=1; i<config_path.Index; i++) {
				if (safe_strlen(iso_report.cfg_path) > safe_strlen(config_path.String[i]))
					safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.String[i]);
			}
			uprintf("Will use %s for Syslinux\n", iso_report.cfg_path);
			// Extract all of the isolinux.bin files we found to identify their versions
			for (i=0; i<isolinux_path.Index; i++) {
				size = (size_t)ExtractISOFile(src_iso, isolinux_path.String[i], dot_isolinux_bin);
				if (size == 0) {
					uprintf("Could not access %s\n", isolinux_path.String[i]);
				} else {
					buf = (char*)calloc(size, 1);
					if (buf == NULL) break;
					fd = fopen(dot_isolinux_bin, "rb");
					if (fd == NULL) {
						free(buf);
						continue;
					}
					fread(buf, 1, size, fd);
					fclose(fd);
					for (k=0; k<size-16; k++) {
						if (memcmp(&buf[k], ISOLINUX, sizeof(ISOLINUX)) == 0) {
							k += sizeof(ISOLINUX);
							sl_version = (((uint8_t)strtoul(&buf[k], &tmp, 10))<<8) + (uint8_t)strtoul(&tmp[1], NULL, 10);
							if (iso_report.sl_version == 0) {
								iso_report.sl_version = sl_version;
								j = (int)i;
							} else if (iso_report.sl_version != sl_version) {
								uprintf("Found conflicting %s versions:\n  '%s' (%d.%02d) vs '%s' (%d.%02d)\n", isolinux_bin,
									isolinux_path.String[j], SL_MAJOR(iso_report.sl_version), SL_MINOR(iso_report.sl_version),
									isolinux_path.String[i], SL_MAJOR(sl_version), SL_MINOR(sl_version));
							}
							break;
						}
					}
					free(buf);
					_unlink(dot_isolinux_bin);
				}
			}
			if (iso_report.sl_version != 0) {
				static_sprintf(iso_report.sl_version_str, "%d.%02d",
					SL_MAJOR(iso_report.sl_version), SL_MINOR(iso_report.sl_version));
				uprintf("Detected Isolinux version: %s (from '%s')",
					iso_report.sl_version_str, isolinux_path.String[j]);
				if ( (has_ldlinux_c32 && (SL_MAJOR(iso_report.sl_version) < 5))
				  || (!has_ldlinux_c32 && (SL_MAJOR(iso_report.sl_version) >= 5)) )
					uprintf("Warning: Conflict between Isolinux version and the presence of ldlinux.c32...\n");
			} else {
				// Couldn't find a version from isolinux.bin. Force set to the versions we embed
				iso_report.sl_version = embedded_sl_version[has_ldlinux_c32?1:0];
				static_sprintf(iso_report.sl_version_str, "%d.%02d",
					SL_MAJOR(iso_report.sl_version), SL_MINOR(iso_report.sl_version));
				uprintf("Warning: Could not detect Isolinux version - Forcing to %s (embedded)",
					iso_report.sl_version_str);
			}
		}
		if (IS_WINPE(iso_report.winpe)) {
			// In case we have a WinPE 1.x based iso, we extract and parse txtsetup.sif
			// during scan, to see if /minint was provided for OsLoadOptions, as it decides
			// whether we should use 0x80 or 0x81 as the disk ID in the MBR
			safe_sprintf(path, sizeof(path), "/%s/txtsetup.sif", 
				basedir[((iso_report.winpe&WINPE_I386) == WINPE_I386)?0:1]);
			ExtractISOFile(src_iso, path, tmp_sif);
			tmp = get_token_data_file("OsLoadOptions", tmp_sif);
			if (tmp != NULL) {
				for (i=0; i<strlen(tmp); i++)
					tmp[i] = (char)tolower(tmp[i]);
				uprintf("Checking txtsetup.sif:\n  OsLoadOptions = %s\n", tmp);
				iso_report.uses_minint = (strstr(tmp, "/minint") != NULL);
			}
			_unlink(tmp_sif);
			safe_free(tmp);
		}
		StrArrayDestroy(&config_path);
		StrArrayDestroy(&isolinux_path);
	} else if (HAS_SYSLINUX(iso_report)) {
		safe_sprintf(path, sizeof(path), "%s\\syslinux.cfg", dest_dir);
		// Create a /syslinux.cfg (if none exists) that points to the existing isolinux cfg
		fd = fopen(path, "r");
		if (fd == NULL) {
			fd = fopen(path, "w");	// No "/syslinux.cfg" => create a new one
			if (fd == NULL) {
				uprintf("Unable to create %s - booting from USB will not work\n", path);
				r = 1;
			} else {
				fprintf(fd, "DEFAULT loadconfig\n\nLABEL loadconfig\n  CONFIG %s\n", iso_report.cfg_path);
				for (i=safe_strlen(iso_report.cfg_path); (i>0)&&(iso_report.cfg_path[i]!='/'); i--);
				if (i>0) {
					iso_report.cfg_path[i] = 0;
					fprintf(fd, "  APPEND %s/\n", iso_report.cfg_path);
					iso_report.cfg_path[i] = '/';
				}
				uprintf("Created: %s\n", path);
			}
		}
		if (fd != NULL)
			fclose(fd);
	}
	SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0);
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	if ((r != 0) && (FormatStatus == 0))
		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
	return (r == 0);
}