diff --git a/src/iso.c b/src/iso.c index 446af75a..5661f792 100644 --- a/src/iso.c +++ b/src/iso.c @@ -361,6 +361,15 @@ static void __inline set_directory_timestamp(char* path, LPFILETIME creation, LP safe_closehandle(dir_handle); } +// Preallocates the target size of a newly created file in order to prevent fragmentation from repeated writes +static void __inline preallocate_filesize(HANDLE hFile, int64_t file_length) +{ + SetFileInformationByHandle(hFile, FileEndOfFileInfo, &file_length, sizeof(file_length)); + + // FileAllocationInfo does not require the size to be a multiple of the cluster size; the FS driver takes care of this. + SetFileInformationByHandle(hFile, FileAllocationInfo, &file_length, sizeof(file_length)); +} + // Returns 0 on success, nonzero on error static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path) { @@ -440,23 +449,26 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha uprintf(stupid_antivirus); else goto out; - } else while (file_length > 0) { - if (FormatStatus) goto out; - memset(buf, 0, UDF_BLOCKSIZE); - read = udf_read_block(p_udf_dirent, buf, 1); - if (read < 0) { - uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]); - goto out; + } else { + preallocate_filesize(file_handle, file_length); + while (file_length > 0) { + if (FormatStatus) goto out; + memset(buf, 0, UDF_BLOCKSIZE); + read = udf_read_block(p_udf_dirent, buf, 1); + if (read < 0) { + uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]); + goto out; + } + buf_size = (DWORD)MIN(file_length, read); + ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); + if (!r) { + uprintf(" Error writing file: %s", WindowsErrorString()); + goto out; + } + file_length -= read; + if (nb_blocks++ % PROGRESS_THRESHOLD == 0) + UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } - buf_size = (DWORD)MIN(file_length, read); - ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); - if (!r) { - uprintf(" Error writing file: %s", WindowsErrorString()); - goto out; - } - file_length -= read; - if (nb_blocks++ % PROGRESS_THRESHOLD == 0) - UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } if ((preserve_timestamps) && (!SetFileTime(file_handle, to_filetime(udf_get_attribute_time(p_udf_dirent)), to_filetime(udf_get_access_time(p_udf_dirent)), to_filetime(udf_get_modification_time(p_udf_dirent))))) @@ -586,26 +598,29 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) uprintf(stupid_antivirus); else goto out; - } else for (j=0; jextents; j++) { - extent_length = p_statbuf->extsize[j]; - for (i=0; extent_length>0; i++) { - if (FormatStatus) goto out; - memset(buf, 0, ISO_BLOCKSIZE); - lsn = p_statbuf->lsn[j] + (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; + } else { + preallocate_filesize(file_handle, file_length); + for (j=0; jextents; j++) { + extent_length = p_statbuf->extsize[j]; + for (i=0; extent_length>0; i++) { + if (FormatStatus) goto out; + memset(buf, 0, ISO_BLOCKSIZE); + lsn = p_statbuf->lsn[j] + (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(extent_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; + } + extent_length -= ISO_BLOCKSIZE; + if (nb_blocks++ % PROGRESS_THRESHOLD == 0) + UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } - buf_size = (DWORD)MIN(extent_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; - } - extent_length -= ISO_BLOCKSIZE; - if (nb_blocks++ % PROGRESS_THRESHOLD == 0) - UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } } if (preserve_timestamps) { diff --git a/src/rufus.rc b/src/rufus.rc index 033e75d9..06a27776 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 3.1.1322" +CAPTION "Rufus 3.1.1323" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -389,8 +389,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,1,1322,0 - PRODUCTVERSION 3,1,1322,0 + FILEVERSION 3,1,1323,0 + PRODUCTVERSION 3,1,1323,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -407,13 +407,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.1.1322" + VALUE "FileVersion", "3.1.1323" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.1.1322" + VALUE "ProductVersion", "3.1.1323" END END BLOCK "VarFileInfo"