From 2b5b6d2d7ce76c32129d09d9a4628e1f8d357a7b Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 21 Jun 2026 14:21:28 +0100 Subject: [PATCH] [cmp] update Bled to latest and get projected size for compressed disk images * The latest Bled, when compiled with the BLED_EXPECT_DISK_IMAGE option, allows us to get the size of the decompressed disk image, even for compression formats that do not report the decompressed size natively, so use that. --- .vs/bled.vcxproj | 12 ++++---- src/bled/Makefile.am | 2 +- src/bled/Makefile.in | 2 +- src/bled/bb_archive.h | 3 ++ src/bled/bled.c | 31 +++++++++++++++++-- src/bled/bled_size.c | 69 +++++++++++++++++++++++++++++++++++++------ src/rufus.c | 5 +++- src/rufus.rc | 10 +++---- src/vhd.c | 3 ++ 9 files changed, 111 insertions(+), 26 deletions(-) diff --git a/.vs/bled.vcxproj b/.vs/bled.vcxproj index f4b7c146..de587bfb 100644 --- a/.vs/bled.vcxproj +++ b/.vs/bled.vcxproj @@ -162,7 +162,7 @@ Level3 ProgramDatabase Disabled - _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + BLED_EXPECT_DISK_IMAGE;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug ..\src CompileAsC @@ -181,7 +181,7 @@ Level3 ProgramDatabase Disabled - _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + BLED_EXPECT_DISK_IMAGE;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug ..\src /utf-8 %(AdditionalOptions) @@ -200,7 +200,7 @@ ProgramDatabase EnableFastChecks Disabled - _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) + BLED_EXPECT_DISK_IMAGE;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug ..\src CompileAsC @@ -217,7 +217,7 @@ Level3 - _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + BLED_EXPECT_DISK_IMAGE;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) MultiThreaded ..\src CompileAsC @@ -238,7 +238,7 @@ Level3 true - _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + BLED_EXPECT_DISK_IMAGE;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) MultiThreaded ..\src /utf-8 %(AdditionalOptions) @@ -257,7 +257,7 @@ Level3 - _OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) + BLED_EXPECT_DISK_IMAGE;_OFF_T_DEFINED;_off_t=__int64;off_t=_off_t;_FILE_OFFSET_BITS=64;%(PreprocessorDefinitions) MultiThreaded ..\src CompileAsC diff --git a/src/bled/Makefile.am b/src/bled/Makefile.am index 3e059834..3827cc51 100644 --- a/src/bled/Makefile.am +++ b/src/bled/Makefile.am @@ -7,4 +7,4 @@ libbled_a_SOURCES = bled.c bled_size.c crc32.c data_align.c data_extract_all.c d init_handle.c open_transformer.c seek_by_jump.c seek_by_read.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c \ xxhash.c zstd_common.c zstd_decompress.c zstd_decompress_block.c zstd_ddict.c zstd_entropy_common.c \ zstd_error_private.c -libbled_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -Wno-undef -Wno-strict-aliasing +libbled_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -DBLED_EXPECT_DISK_IMAGE -Wno-undef -Wno-strict-aliasing diff --git a/src/bled/Makefile.in b/src/bled/Makefile.in index 1a59d13a..f0a4c484 100644 --- a/src/bled/Makefile.in +++ b/src/bled/Makefile.in @@ -285,7 +285,7 @@ libbled_a_SOURCES = bled.c bled_size.c crc32.c data_align.c data_extract_all.c d xxhash.c zstd_common.c zstd_decompress.c zstd_decompress_block.c zstd_ddict.c zstd_entropy_common.c \ zstd_error_private.c -libbled_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -Wno-undef -Wno-strict-aliasing +libbled_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -DBLED_EXPECT_DISK_IMAGE -Wno-undef -Wno-strict-aliasing all: all-am .SUFFIXES: diff --git a/src/bled/bb_archive.h b/src/bled/bb_archive.h index 284bbffb..2e8a6ff6 100644 --- a/src/bled/bb_archive.h +++ b/src/bled/bb_archive.h @@ -254,6 +254,9 @@ typedef struct transformer_state_t { } magic; } transformer_state_t; +typedef int64_t(*unpacker_t)(transformer_state_t* xstate); +typedef int64_t(*get_uncompressed_size_t)(int fd); +int64_t get_uncompressed_size(int fd, int type); void init_transformer_state(transformer_state_t *xstate) FAST_FUNC; ssize_t transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; ssize_t xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize) FAST_FUNC; diff --git a/src/bled/bled.c b/src/bled/bled.c index 37331b43..c421cab5 100644 --- a/src/bled/bled.c +++ b/src/bled/bled.c @@ -15,9 +15,6 @@ #include "bb_archive.h" #include "bled.h" -typedef int64_t(*unpacker_t)(transformer_state_t *xstate); -extern int64_t get_uncompressed_size(int fd, int type); - /* Globals */ smallint bb_got_signal; uint64_t bb_total_rb, bb_total_wb; @@ -303,6 +300,34 @@ int64_t bled_uncompress_from_buffer_to_buffer(const char* src, const size_t src_ return ret; } +/* Get the decompressed size of file 'src', compressed using 'type' */ +int64_t bled_get_uncompressed_size(const char* src, int type) +{ + int fd = -1; + int64_t ret = -1; + + if (!bled_initialized) { + bb_error_msg("The library has not been initialized"); + return -1; + } + + if ((type < 0) || (type >= BLED_COMPRESSION_MAX)) { + bb_error_msg("Unsupported compression format"); + goto err; + } + + fd = _openU(src, _O_RDONLY | _O_BINARY, 0); + if (fd < 0) + return -1; + + ret = get_uncompressed_size(fd, type); + +err: + if (fd > 0) + _close(fd); + return ret; +} + /* Initialize the library. * When the parameters are not NULL or zero you can: * - specify the buffer size to use (must be larger than 256KB and a power of two) diff --git a/src/bled/bled_size.c b/src/bled/bled_size.c index ee5a9736..403c3e2b 100644 --- a/src/bled/bled_size.c +++ b/src/bled/bled_size.c @@ -15,8 +15,6 @@ #include "bb_archive.h" #include "bled.h" -typedef int64_t(*get_uncompressed_size_t)(int fd); - /* ------------------------------------------------------------------------- * Internal helpers * ---------------------------------------------------------------------- */ @@ -702,6 +700,61 @@ static int64_t get_uncompress_size_zstd(int fd) return (int64_t)size; } +#if defined(BLED_EXPECT_DISK_IMAGE) +extern progress_t bled_progress; +extern unpacker_t unpacker[BLED_COMPRESSION_MAX]; +int64_t get_uncompressed_size_from_disk_image(int fd, int type) +{ + progress_t old_bled_progress = bled_progress; + int64_t size = DECOMP_SIZE_UNKNOWN; + uint8_t buf[8192]; + transformer_state_t xstate; + + bled_progress = NULL; /* Can't have progress on this operation */ + init_transformer_state(&xstate); + xstate.src_fd = fd; + xstate.dst_fd = -1; + xstate.mem_output_buf = buf; + xstate.mem_output_size = 0; + xstate.mem_output_size_max = sizeof(buf); + + if (setjmp(bb_error_jmp)) + goto out; + + lseek(fd, 0, SEEK_SET); + size = unpacker[type](&xstate); + if (size != sizeof(buf) || buf[0x1fe] != 0x55 || buf[0x1ff] != 0xaa) { + size = DECOMP_SIZE_UNKNOWN; + goto out; + } + if (buf[0x1c2] == 0xee) { + /* Protective EFI MBR => look for the primary GPT, which'll also give us the sector size */ + if (memcmp("EFI PART", &buf[0x200], 8) == 0) { + /* The address of the backup GPT is assumed to be the last LBA for the disk */ + size = get_le64(&buf[0x220]) * 512; + goto out; + } + if (memcmp("EFI PART", &buf[0x1000], 8) == 0) { + size = get_le64(&buf[0x1020]) * 8192; + goto out; + } + } + if (buf[0x1be] == 0x80) { + /* Regular bootable MBR => compute the max LBA (using primary partitions only) */ + uint32_t max_lba = 1; + for (int i = 0; i < 4; i++) + max_lba = MAX(max_lba, get_le32(&buf[0x1be + 0x10 * i + 8]) + get_le32(&buf[0x1be + 0x10 * i + 0xc])); + size = max_lba * 512; /* assume 512-byte sectors for anything MBR based */ + if (size < 8192) + size = DECOMP_SIZE_UNKNOWN; + } + +out: + bled_progress = old_bled_progress; + return size; +} +#endif + static get_uncompressed_size_t _get_uncompressed_size[BLED_COMPRESSION_MAX] = { get_uncompress_size_none, get_uncompress_size_zip, @@ -718,13 +771,11 @@ static get_uncompressed_size_t _get_uncompressed_size[BLED_COMPRESSION_MAX] = { /* Get the decompressed size of file 'fd', compressed using 'type' */ int64_t get_uncompressed_size(int fd, int type) { - int64_t size = -1; - - if ((type < 0) || (type >= BLED_COMPRESSION_MAX)) { - bb_error_msg("Unsupported compression format"); - return -1; - } - size = _get_uncompressed_size[type](fd); + int64_t size = _get_uncompressed_size[type](fd); +#if defined(BLED_EXPECT_DISK_IMAGE) + if (size < 0) + size = get_uncompressed_size_from_disk_image(fd, type); +#endif /* Make sure to reset our file pointer */ lseek(fd, 0, SEEK_SET); diff --git a/src/rufus.c b/src/rufus.c index 09e34c45..4a92d6a0 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1391,6 +1391,8 @@ DWORD WINAPI ImageScanThread(LPVOID param) (img_report.compression_type != BLED_COMPRESSION_NONE && img_report.compression_type < BLED_COMPRESSION_MAX) ? "compressed " : "", img_report.is_vhd ? "VHD" : "disk"); selection_default = BT_IMAGE; + if (img_report.projected_size > 0) + uprintf(" Size: %s (Projected)", SizeToHumanReadable(img_report.projected_size, FALSE, FALSE)); } if (img_report.is_iso) { @@ -1525,7 +1527,8 @@ static DWORD WINAPI BootCheckThread(LPVOID param) Notification(MB_OK | MB_ICONERROR, lmprintf(MSG_358), lmprintf(MSG_359)); goto out; } - if ((size_check) && (img_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) { + /* Add 4 KB extra margin for VHD footers and so on */ + if ((size_check) && (img_report.projected_size > (uint64_t)SelectedDrive.DiskSize) + 4 * KB) { // This ISO image is too big for the selected target Notification(MB_OK | MB_ICONERROR, lmprintf(MSG_088), lmprintf(MSG_089)); goto out; diff --git a/src/rufus.rc b/src/rufus.rc index e388f48f..a4631124 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.15.2393" +CAPTION "Rufus 4.15.2394" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -409,8 +409,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,15,2393,0 - PRODUCTVERSION 4,15,2393,0 + FILEVERSION 4,15,2394,0 + PRODUCTVERSION 4,15,2394,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -428,13 +428,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.15.2393" + VALUE "FileVersion", "4.15.2394" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.15.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.15.2393" + VALUE "ProductVersion", "4.15.2394" END END BLOCK "VarFileInfo" diff --git a/src/vhd.c b/src/vhd.c index d0faa1f5..7444ee17 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -99,6 +99,9 @@ static int8_t IsCompressedBootableImage(const char* path) ErrorStatus = 0; if (img_report.compression_type < BLED_COMPRESSION_MAX) { bled_init(0, uprintf, NULL, NULL, NULL, NULL, &ErrorStatus); + dc = bled_get_uncompressed_size(path, file_assoc[i].type); + if (dc > 0) + img_report.projected_size = dc; dc = bled_uncompress_to_buffer(path, (char*)buf, MBR_SIZE, file_assoc[i].type); bled_exit(); } else if (img_report.compression_type == BLED_COMPRESSION_MAX) {