diff --git a/README.txt b/README.txt index cdca407f..f661f7a8 100644 --- a/README.txt +++ b/README.txt @@ -3,7 +3,7 @@ Rufus: The Reliable USB Formatting Utility Features: - Formats USB flash drives to FAT/FAT32/NTFS/exFAT - Creates DOS bootable USB drives, with no external files required -- Creates bootable USB drives from ISOs, such as Windows installation media +- Creates bootable USB drives from ISOs, such as Windows or Linux installation media - Twice as fast as Microsoft's USB/DVD tool or UNetbootin, on ISO->USB (1) - Bad blocks check - Modern UI, with UAC elevation for Windows Vista and later diff --git a/src/iso.c b/src/iso.c index cb1700dc..4d0fa670 100644 --- a/src/iso.c +++ b/src/iso.c @@ -64,6 +64,7 @@ int64_t iso_blocking_status = -1; #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) static const char *psz_extract_dir; static const char *bootmgr_name = "bootmgr"; +static const char *ldlinux_name = "ldlinux.sys"; static const char *isolinux_name[] = { "isolinux.cfg", "syslinux.cfg", "extlinux.conf"}; static uint64_t total_blocks, nb_blocks; static BOOL scan_only = FALSE; @@ -89,11 +90,15 @@ static __inline char* size_to_hr(int64_t size) return str_size; } -// Interruptible thread for handle closure on large files -DWORD WINAPI ISOCloseHandleThread(LPVOID param) +static void log_handler (cdio_log_level_t level, const char *message) { - CloseHandle((HANDLE)param); - ExitThread(0); + switch(level) { + case CDIO_LOG_DEBUG: + case CDIO_LOG_INFO: + return; + default: + uprintf("libcdio: %s\n", message); + } } // Returns 0 on success, nonzero on error @@ -151,6 +156,12 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha total_blocks++; safe_free(psz_fullpath); continue; + } else { + // In case there's an ldlinux.sys on the ISO, prevent it from overwriting ours + if ((*psz_path == 0) && (safe_strcmp(psz_basename, ldlinux_name) == 0)) { + uprintf("skipping % file from ISO image\n", ldlinux_name); + continue; + } } // Replace slashes with backslashes and append the size to the path for UI display nul_pos = safe_strlen(psz_fullpath); @@ -262,6 +273,12 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) if ((i_file_length != 0) && (i_file_length%ISO_BLOCKSIZE == 0)) total_blocks++; continue; + } else { + // In case there's an ldlinux.sys on the ISO, prevent it from overwriting ours + if ((*psz_path == 0) && (safe_strcmp(psz_basename, ldlinux_name) == 0)) { + uprintf("skipping % file from ISO image\n", ldlinux_name); + continue; + } } // Replace slashes with backslashes and append the size to the path for UI display nul_pos = safe_strlen(psz_fullpath); @@ -316,13 +333,14 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan) udf_t* p_udf = NULL; udf_dirent_t* p_udf_root; LONG progress_style; + char* vol_id; const char* scan_text = "Scanning ISO image...\n"; if ((src_iso == NULL) || (dest_dir == NULL)) return FALSE; scan_only = scan; - cdio_loglevel_default = CDIO_LOG_DEBUG; + cdio_log_set_handler(log_handler); psz_extract_dir = dest_dir; progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE); if (scan_only) { @@ -363,6 +381,10 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan) 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; @@ -373,6 +395,12 @@ try_iso: goto out; } uprintf("Disc image is an ISO9660 image\n"); + if (scan_only) { + if (iso9660_ifs_get_volume_id(p_iso, &vol_id)) + safe_strcpy(iso_report.label, sizeof(iso_report.label), vol_id); + else + iso_report.label[0] = 0; + } r = iso_extract_files(p_iso, ""); out: diff --git a/src/libcdio/cdio/udf.h b/src/libcdio/cdio/udf.h index 2d87e9e3..21cdec4e 100644 --- a/src/libcdio/cdio/udf.h +++ b/src/libcdio/cdio/udf.h @@ -115,7 +115,7 @@ extern "C" { /** * Gets the Volume Identifier string, in 8bit unicode (latin-1) * psz_volid, place to put the string - * i_volid_size, size of the buffer volid points to + * i_volid, size of the buffer psz_volid points to * returns the size of buffer needed for all data */ int udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, @@ -125,14 +125,24 @@ extern "C" { * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) * WARNING This is not a null terminated string * volsetid, place to put the data - * volsetid_size, size of the buffer volsetid points to + * i_volsetid, size of the buffer psz_volsetid points to * the buffer should be >=128 bytes to store the whole volumesetidentifier * returns the size of the available volsetid information (128) * or 0 on error */ int udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid, unsigned int i_volsetid); - + + /** + * Gets the Logical Volume Identifier string, in 8bit unicode (latin-1) + * psz_logvolid, place to put the string + * i_logvolid, size of the buffer psz_logvolid points to + * returns the size of buffer needed for all data + * A call to udf_get_root() should have been issued before this call + */ + int udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, + unsigned int i_logvolid); + /*! Return a file pointer matching psz_name. */ diff --git a/src/libcdio/driver/_cdio_stdio.c b/src/libcdio/driver/_cdio_stdio.c index d89625af..d9853c6a 100644 --- a/src/libcdio/driver/_cdio_stdio.c +++ b/src/libcdio/driver/_cdio_stdio.c @@ -39,6 +39,7 @@ #ifdef HAVE_ERRNO_H #include #endif +#include #include #include @@ -225,17 +226,34 @@ cdio_stdio_new(const char pathname[]) cdio_stream_io_functions funcs = { NULL, NULL, NULL, NULL, NULL, NULL }; _UserData *ud = NULL; struct CDIO_STAT statbuf; - - if (CDIO_STAT (pathname, &statbuf) == -1) + char* pathdup; + + if (pathname == NULL) + return NULL; + + pathdup = strdup(pathname); + if (pathdup == NULL) + return NULL; + +#ifdef __MINGW32__ + /* _stati64 requires using native Windows paths => convert "/c/..." to "c:/..." */ + if ((strlen(pathdup) > 3) && (pathdup[0] == '/') && (pathdup[2] == '/') && (isalpha(pathdup[1]))) + { + pathdup[0] = pathdup[1]; + pathdup[1] = ':'; + } +#endif + if (CDIO_STAT (pathdup, &statbuf) == -1) { cdio_warn ("could not retrieve file info for `%s': %s", - pathname, strerror (errno)); + pathdup, strerror (errno)); + free(pathdup); return NULL; } ud = calloc (1, sizeof (_UserData)); - ud->pathname = strdup(pathname); + ud->pathname = pathdup; ud->st_size = statbuf.st_size; /* let's hope it doesn't change... */ funcs.open = _stdio_open; diff --git a/src/libcdio/udf/udf_fs.c b/src/libcdio/udf/udf_fs.c index 5241d8dc..601df95f 100644 --- a/src/libcdio/udf/udf_fs.c +++ b/src/libcdio/udf/udf_fs.c @@ -427,7 +427,7 @@ udf_open (const char *psz_path) /** * Gets the Volume Identifier string, in 8bit unicode (latin-1) * psz_volid, place to put the string - * i_volid_size, size of the buffer volid points to + * i_volid, size of the buffer psz_volid points to * returns the size of buffer needed for all data */ int @@ -458,7 +458,7 @@ udf_get_volume_id(udf_t *p_udf, /*out*/ char *psz_volid, unsigned int i_volid) * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) * WARNING This is not a null terminated string * volsetid, place to put the data - * volsetid_size, size of the buffer volsetid points to + * i_volsetid, size of the buffer psz_volsetid points to * the buffer should be >=128 bytes to store the whole volumesetidentifier * returns the size of the available volsetid information (128) * or 0 on error @@ -483,6 +483,31 @@ udf_get_volumeset_id(udf_t *p_udf, /*out*/ uint8_t *volsetid, return UDF_VOLSET_ID_SIZE; } +/** + * Gets the Logical Volume Identifier string, in 8bit unicode (latin-1) + * psz_logvolid, place to put the string (should be at least 64 bytes) + * i_logvolid, size of the buffer psz_logvolid points to + * returns the size of buffer needed for all data + * A call to udf_get_root() should have been issued before this call + */ +int +udf_get_logical_volume_id(udf_t *p_udf, /*out*/ char *psz_logvolid, unsigned int i_logvolid) +{ + uint8_t data[UDF_BLOCKSIZE]; + logical_vol_desc_t *p_logvol = (logical_vol_desc_t *) &data; + int logvolid_len; + + if (DRIVER_OP_SUCCESS != udf_read_sectors (p_udf, p_logvol, p_udf->lvd_lba, 1) ) + return 0; + + logvolid_len = (p_logvol->logvol_id[127]+1)/2; + if (i_logvolid > logvolid_len) + i_logvolid = logvolid_len; + + unicode16_decode((uint8_t *) p_logvol->logvol_id, 2*i_logvolid, psz_logvolid); + return logvolid_len; +} + /*! Get the root in p_udf. If b_any_partition is false then the root must be in the given partition. diff --git a/src/rufus.c b/src/rufus.c index 4b9cc590..ec6c27cb 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -963,7 +963,8 @@ DWORD WINAPI ISOScanThread(LPVOID param) PrintStatus(0, TRUE, "Failed to scan ISO image."); goto out; } - uprintf("ISO size: %lld bytes, 4GB:%c, bootmgr:%c, isolinux:%c\n", iso_report.projected_size, + uprintf("ISO label: '%s'\n size: %lld bytes, 4GB:%c, bootmgr:%c, isolinux:%c\n", + iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?'Y':'N', iso_report.has_bootmgr?'Y':'N', iso_report.has_isolinux?'Y':'N'); if ((!iso_report.has_bootmgr) && (!iso_report.has_isolinux)) { MessageBoxU(hMainDialog, "This version of Rufus only supports bootable ISOs\n" @@ -973,6 +974,11 @@ DWORD WINAPI ISOScanThread(LPVOID param) } else { for (i=(int)safe_strlen(iso_path); (i>0)&&(iso_path[i]!='\\'); i--); PrintStatus(0, TRUE, "Using ISO: '%s'\n", &iso_path[i+1]); + // Some Linux distros, such as Arch Linux, require the USB drive to have + // a specific label => copy the one we got from the ISO image + if (iso_report.label[0] != 0) { + SetWindowTextU(hLabel, iso_report.label); + } } out: diff --git a/src/rufus.h b/src/rufus.h index cb88fd5b..7d97ecb3 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -145,6 +145,7 @@ typedef struct { /* ISO details that the application may want */ typedef struct { + char label[64]; uint64_t projected_size; BOOL has_4GB_file; BOOL has_bootmgr; diff --git a/src/rufus.rc b/src/rufus.rc index 004a26b6..39ec2846 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 278 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.1.0.132" +CAPTION "Rufus v1.1.0.133" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 @@ -71,7 +71,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.1.0 (Build 132)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.1.0 (Build 133)",IDC_STATIC,46,19,78,8 PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -222,8 +222,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,0,132 - PRODUCTVERSION 1,1,0,132 + FILEVERSION 1,1,0,133 + PRODUCTVERSION 1,1,0,133 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -240,13 +240,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.1.0.132" + VALUE "FileVersion", "1.1.0.133" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.1.0.132" + VALUE "ProductVersion", "1.1.0.133" END END BLOCK "VarFileInfo"