mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-29 14:05:22 -04:00
[iso] increase write buffer size to work around a bug in the AMI UEFI NTFS driver
* The AMI UEFI NTFS driver (version 0x10000), which is used in many modern systems from ASUS, Gigabyte, intel and so on, has a major bug whereas depending on the size of the buffers that are used to write the data onto the NTFS volume from Windows, as well as read the data from the NTFS volume from UEFI, the data being read may be incorrect (for details on this, see https://github.com/pbatard/AmiNtfsBug). * Especially, it appears that if the size of the buffer used to write data on Windows is smaller than the NTFS cluster size, the bug may be triggered. * Because of this, we increase the size of ISO write buffer to 64 KB since, per https://support.microsoft.com/en-gb/topic/default-cluster-size-for-ntfs-fat-and-exfat-9772e6f1-e31a-00d7-e18f-73169155af95 this is the maximum cluster size that can be used for NTFS volumes. * This increase in size should also help with performance somewhat. * Also add support for C11's _Static_assert() which may come handy.
This commit is contained in:
parent
8738e7a7de
commit
abc33122a0
3 changed files with 67 additions and 43 deletions
93
src/iso.c
93
src/iso.c
|
@ -52,9 +52,10 @@
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
#include "bled/bled.h"
|
#include "bled/bled.h"
|
||||||
|
|
||||||
// How often should we update the progress bar (in 2K blocks) as updating
|
// How often should we update the progress bar, as updating the
|
||||||
// the progress bar for every block will bring extraction to a crawl
|
// progress bar too frequently will bring extraction to a crawl
|
||||||
#define PROGRESS_THRESHOLD 128
|
_Static_assert(256 * KB >= ISO_BLOCKSIZE, "Can't set PROGRESS_THRESHOLD");
|
||||||
|
#define PROGRESS_THRESHOLD ((256 * KB) / ISO_BLOCKSIZE)
|
||||||
|
|
||||||
// Needed for UDF symbolic link testing
|
// Needed for UDF symbolic link testing
|
||||||
#define S_IFLNK 0xA000
|
#define S_IFLNK 0xA000
|
||||||
|
@ -122,7 +123,7 @@ static const char* stupid_antivirus = " NOTE: This is usually caused by a poorl
|
||||||
const char* old_c32_name[NB_OLD_C32] = OLD_C32_NAMES;
|
const char* old_c32_name[NB_OLD_C32] = OLD_C32_NAMES;
|
||||||
static const int64_t old_c32_threshold[NB_OLD_C32] = OLD_C32_THRESHOLD;
|
static const int64_t old_c32_threshold[NB_OLD_C32] = OLD_C32_THRESHOLD;
|
||||||
static uint8_t joliet_level = 0;
|
static uint8_t joliet_level = 0;
|
||||||
static uint64_t total_blocks, extra_blocks, nb_blocks;
|
static uint64_t total_blocks, extra_blocks, nb_blocks, last_nb_blocks;
|
||||||
static BOOL scan_only = FALSE;
|
static BOOL scan_only = FALSE;
|
||||||
static StrArray config_path, isolinux_path, modified_path;
|
static StrArray config_path, isolinux_path, modified_path;
|
||||||
static char symlinked_syslinux[MAX_PATH];
|
static char symlinked_syslinux[MAX_PATH];
|
||||||
|
@ -594,14 +595,16 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
EXTRACT_PROPS props;
|
EXTRACT_PROPS props;
|
||||||
BOOL r, is_identical;
|
BOOL r, is_identical;
|
||||||
int length;
|
int length;
|
||||||
size_t i;
|
size_t i, nb;
|
||||||
char tmp[128], *psz_fullpath = NULL, *psz_sanpath = NULL;
|
char tmp[128], *psz_fullpath = NULL, *psz_sanpath = NULL;
|
||||||
const char* psz_basename;
|
const char* psz_basename;
|
||||||
udf_dirent_t *p_udf_dirent2;
|
udf_dirent_t *p_udf_dirent2;
|
||||||
uint8_t buf[UDF_BLOCKSIZE];
|
_Static_assert(ISO_BUFFER_SIZE % UDF_BLOCKSIZE == 0,
|
||||||
|
"ISO_BUFFER_SIZE is not a multiple of UDF_BLOCKSIZE");
|
||||||
|
uint8_t* buf = malloc(ISO_BUFFER_SIZE);
|
||||||
int64_t read, file_length;
|
int64_t read, file_length;
|
||||||
|
|
||||||
if ((p_udf_dirent == NULL) || (psz_path == NULL))
|
if ((p_udf_dirent == NULL) || (psz_path == NULL) || (buf == NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (psz_path[0] == 0)
|
if (psz_path[0] == 0)
|
||||||
|
@ -672,22 +675,26 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
while (file_length > 0) {
|
while (file_length > 0) {
|
||||||
if (FormatStatus) goto out;
|
if (FormatStatus)
|
||||||
memset(buf, 0, UDF_BLOCKSIZE);
|
goto out;
|
||||||
read = udf_read_block(p_udf_dirent, buf, 1);
|
nb = MIN(ISO_BUFFER_SIZE / UDF_BLOCKSIZE, (file_length + UDF_BLOCKSIZE - 1) / UDF_BLOCKSIZE);
|
||||||
|
read = udf_read_block(p_udf_dirent, buf, nb);
|
||||||
if (read < 0) {
|
if (read < 0) {
|
||||||
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]);
|
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_size = (DWORD)MIN(file_length, read);
|
buf_size = (DWORD)MIN(file_length, read);
|
||||||
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
||||||
if (!r) {
|
if (!r || (wr_size != buf_size)) {
|
||||||
uprintf(" Error writing file: %s", WindowsErrorString());
|
uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
file_length -= read;
|
file_length -= wr_size;
|
||||||
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
|
nb_blocks += nb;
|
||||||
|
if (nb_blocks - last_nb_blocks >= PROGRESS_THRESHOLD) {
|
||||||
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks);
|
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks);
|
||||||
|
last_nb_blocks = nb_blocks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)),
|
if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)),
|
||||||
|
@ -706,6 +713,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
}
|
}
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
}
|
}
|
||||||
|
safe_free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -713,6 +721,7 @@ out:
|
||||||
ISO_BLOCKING(safe_closehandle(file_handle));
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
safe_free(psz_sanpath);
|
safe_free(psz_sanpath);
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
|
safe_free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,26 +736,28 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
char psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL;
|
char psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL;
|
||||||
char tmp[128], target_path[256];
|
char tmp[128], target_path[256];
|
||||||
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
|
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
|
||||||
unsigned char buf[ISO_BLOCKSIZE];
|
_Static_assert(ISO_BUFFER_SIZE % ISO_BLOCKSIZE == 0,
|
||||||
|
"ISO_BUFFER_SIZE is not a multiple of ISO_BLOCKSIZE");
|
||||||
|
uint8_t* buf = malloc(ISO_BUFFER_SIZE);
|
||||||
CdioListNode_t* p_entnode;
|
CdioListNode_t* p_entnode;
|
||||||
iso9660_stat_t *p_statbuf;
|
iso9660_stat_t *p_statbuf;
|
||||||
CdioISO9660FileList_t* p_entlist;
|
CdioISO9660FileList_t* p_entlist = NULL;
|
||||||
size_t i;
|
size_t i, nb;
|
||||||
lsn_t lsn;
|
lsn_t lsn;
|
||||||
int64_t file_length;
|
int64_t file_length;
|
||||||
|
|
||||||
if ((p_iso == NULL) || (psz_path == NULL))
|
if ((p_iso == NULL) || (psz_path == NULL) || (buf == NULL))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path);
|
length = _snprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path);
|
||||||
if (length < 0)
|
if (length < 0)
|
||||||
return 1;
|
goto out;
|
||||||
psz_basename = &psz_fullpath[length];
|
psz_basename = &psz_fullpath[length];
|
||||||
|
|
||||||
p_entlist = iso9660_ifs_readdir(p_iso, psz_path);
|
p_entlist = iso9660_ifs_readdir(p_iso, psz_path);
|
||||||
if (!p_entlist) {
|
if (!p_entlist) {
|
||||||
uprintf("Could not access directory %s", psz_path);
|
uprintf("Could not access directory %s", psz_path);
|
||||||
return 1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psz_path[0] == 0)
|
if (psz_path[0] == 0)
|
||||||
|
@ -913,25 +924,29 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
uprintf(" Error writing file: %s", WindowsErrorString());
|
uprintf(" Error writing file: %s", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else for (i = 0; file_length > 0; i++) {
|
} else for (i = 0; file_length > 0; i += nb) {
|
||||||
if (FormatStatus) goto out;
|
if (FormatStatus)
|
||||||
memset(buf, 0, ISO_BLOCKSIZE);
|
goto out;
|
||||||
lsn = p_statbuf->lsn + (lsn_t)i;
|
lsn = p_statbuf->lsn + (lsn_t)i;
|
||||||
if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) {
|
nb = MIN(ISO_BUFFER_SIZE / ISO_BLOCKSIZE, (file_length + ISO_BLOCKSIZE - 1) / ISO_BLOCKSIZE);
|
||||||
|
if (iso9660_iso_seek_read(p_iso, buf, lsn, (long)nb) != (nb * ISO_BLOCKSIZE)) {
|
||||||
uprintf(" Error reading ISO9660 file %s at LSN %lu",
|
uprintf(" Error reading ISO9660 file %s at LSN %lu",
|
||||||
psz_iso_name, (long unsigned int)lsn);
|
psz_iso_name, (long unsigned int)lsn);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_size = (DWORD)MIN(file_length, ISO_BLOCKSIZE);
|
buf_size = (DWORD)MIN(file_length, ISO_BUFFER_SIZE);
|
||||||
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES));
|
||||||
if (!r) {
|
if (!r || wr_size != buf_size) {
|
||||||
uprintf(" Error writing file: %s", WindowsErrorString());
|
uprintf(" Error writing file: %s", r ? "Short write detected" : WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
file_length -= ISO_BLOCKSIZE;
|
file_length -= wr_size;
|
||||||
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
|
nb_blocks += nb;
|
||||||
|
if (nb_blocks - last_nb_blocks >= PROGRESS_THRESHOLD) {
|
||||||
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks +
|
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks +
|
||||||
((fs_type != FS_NTFS) ? extra_blocks : 0));
|
((fs_type != FS_NTFS) ? extra_blocks : 0));
|
||||||
|
last_nb_blocks = nb_blocks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (preserve_timestamps) {
|
if (preserve_timestamps) {
|
||||||
LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm));
|
LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm));
|
||||||
|
@ -951,8 +966,10 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ISO_BLOCKING(safe_closehandle(file_handle));
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
iso9660_filelist_free(p_entlist);
|
if (p_entlist != NULL)
|
||||||
|
iso9660_filelist_free(p_entlist);
|
||||||
safe_free(psz_sanpath);
|
safe_free(psz_sanpath);
|
||||||
|
safe_free(buf);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,20 +1056,19 @@ void GetGrubVersion(char* buf, size_t buf_size)
|
||||||
|
|
||||||
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
|
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
|
||||||
{
|
{
|
||||||
size_t i, j, size, sl_index = 0;
|
const char* basedir[] = { "i386", "amd64", "minint" };
|
||||||
uint16_t sl_version;
|
const char* tmp_sif = ".\\txtsetup.sif~";
|
||||||
FILE* fd;
|
|
||||||
int k, r = 1;
|
int k, r = 1;
|
||||||
|
char* tmp, * buf, * ext, * spacing = " ";
|
||||||
|
char path[MAX_PATH], path2[16];
|
||||||
|
uint16_t sl_version;
|
||||||
|
size_t i, j, size, sl_index = 0;
|
||||||
|
FILE* fd;
|
||||||
iso9660_t* p_iso = NULL;
|
iso9660_t* p_iso = NULL;
|
||||||
iso9660_pvd_t pvd;
|
iso9660_pvd_t pvd;
|
||||||
udf_t* p_udf = NULL;
|
udf_t* p_udf = NULL;
|
||||||
udf_dirent_t* p_udf_root;
|
udf_dirent_t* p_udf_root;
|
||||||
char *tmp, *buf, *ext;
|
|
||||||
char path[MAX_PATH], path2[16];
|
|
||||||
const char* basedir[] = { "i386", "amd64", "minint" };
|
|
||||||
const char* tmp_sif = ".\\txtsetup.sif~";
|
|
||||||
iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
|
iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
|
||||||
char* spacing = " ";
|
|
||||||
|
|
||||||
if ((!enable_iso) || (src_iso == NULL) || (dest_dir == NULL))
|
if ((!enable_iso) || (src_iso == NULL) || (dest_dir == NULL))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1082,6 +1098,7 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
nb_blocks = 0;
|
nb_blocks = 0;
|
||||||
|
last_nb_blocks = 0;
|
||||||
iso_blocking_status = 0;
|
iso_blocking_status = 0;
|
||||||
symlinked_syslinux[0] = 0;
|
symlinked_syslinux[0] = 0;
|
||||||
StrArrayCreate(&modified_path, 8);
|
StrArrayCreate(&modified_path, 8);
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
#define FAT32_CLUSTER_THRESHOLD 1.011f // For FAT32, cluster size changes don't occur at power of 2 boundaries but slightly above
|
#define FAT32_CLUSTER_THRESHOLD 1.011f // For FAT32, cluster size changes don't occur at power of 2 boundaries but slightly above
|
||||||
#define DD_BUFFER_SIZE (32 * 1024 * 1024) // Minimum size of buffer to use for DD operations
|
#define DD_BUFFER_SIZE (32 * 1024 * 1024) // Minimum size of buffer to use for DD operations
|
||||||
#define UBUFFER_SIZE 4096
|
#define UBUFFER_SIZE 4096
|
||||||
|
#define ISO_BUFFER_SIZE (64 * KB) // Buffer size used for ISO data extraction
|
||||||
#define RSA_SIGNATURE_SIZE 256
|
#define RSA_SIGNATURE_SIZE 256
|
||||||
#define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256)
|
#define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256)
|
||||||
#if defined(RUFUS_TEST)
|
#if defined(RUFUS_TEST)
|
||||||
|
@ -142,6 +143,12 @@
|
||||||
#define IMOP_WINTOGO 0x01
|
#define IMOP_WINTOGO 0x01
|
||||||
#define IMOP_PERSISTENCE 0x02
|
#define IMOP_PERSISTENCE 0x02
|
||||||
|
|
||||||
|
#if (_MSC_VER >= 1900)
|
||||||
|
#define _Static_assert static_assert
|
||||||
|
#else
|
||||||
|
#define _Static_assert(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ComboBox_GetCurItemData(hCtrl) ComboBox_GetItemData(hCtrl, ComboBox_GetCurSel(hCtrl))
|
#define ComboBox_GetCurItemData(hCtrl) ComboBox_GetItemData(hCtrl, ComboBox_GetCurSel(hCtrl))
|
||||||
|
|
||||||
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
|
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_ACCEPTFILES
|
EXSTYLE WS_EX_ACCEPTFILES
|
||||||
CAPTION "Rufus 4.5.2114"
|
CAPTION "Rufus 4.5.2115"
|
||||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||||
|
@ -392,8 +392,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 4,5,2114,0
|
FILEVERSION 4,5,2115,0
|
||||||
PRODUCTVERSION 4,5,2114,0
|
PRODUCTVERSION 4,5,2115,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -411,13 +411,13 @@ BEGIN
|
||||||
VALUE "Comments", "https://rufus.ie"
|
VALUE "Comments", "https://rufus.ie"
|
||||||
VALUE "CompanyName", "Akeo Consulting"
|
VALUE "CompanyName", "Akeo Consulting"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "4.5.2114"
|
VALUE "FileVersion", "4.5.2115"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2024 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2024 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
VALUE "OriginalFilename", "rufus-4.5.exe"
|
VALUE "OriginalFilename", "rufus-4.5.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "4.5.2114"
|
VALUE "ProductVersion", "4.5.2115"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue