mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[iso] improve write performance during ISO extraction
* Now preallocate the file size for each extracted file, to help the target filesystem avoid fragmentation issues and thus increase writing speed. * Closes #1170
This commit is contained in:
parent
dbc92e3adc
commit
d4a4506b16
2 changed files with 55 additions and 40 deletions
85
src/iso.c
85
src/iso.c
|
@ -361,6 +361,15 @@ static void __inline set_directory_timestamp(char* path, LPFILETIME creation, LP
|
||||||
safe_closehandle(dir_handle);
|
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
|
// 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)
|
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);
|
uprintf(stupid_antivirus);
|
||||||
else
|
else
|
||||||
goto out;
|
goto out;
|
||||||
} else while (file_length > 0) {
|
} else {
|
||||||
if (FormatStatus) goto out;
|
preallocate_filesize(file_handle, file_length);
|
||||||
memset(buf, 0, UDF_BLOCKSIZE);
|
while (file_length > 0) {
|
||||||
read = udf_read_block(p_udf_dirent, buf, 1);
|
if (FormatStatus) goto out;
|
||||||
if (read < 0) {
|
memset(buf, 0, UDF_BLOCKSIZE);
|
||||||
uprintf(" Error reading UDF file %s", &psz_fullpath[strlen(psz_extract_dir)]);
|
read = udf_read_block(p_udf_dirent, buf, 1);
|
||||||
goto out;
|
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)),
|
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)))))
|
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);
|
uprintf(stupid_antivirus);
|
||||||
else
|
else
|
||||||
goto out;
|
goto out;
|
||||||
} else for (j=0; j<p_statbuf->extents; j++) {
|
} else {
|
||||||
extent_length = p_statbuf->extsize[j];
|
preallocate_filesize(file_handle, file_length);
|
||||||
for (i=0; extent_length>0; i++) {
|
for (j=0; j<p_statbuf->extents; j++) {
|
||||||
if (FormatStatus) goto out;
|
extent_length = p_statbuf->extsize[j];
|
||||||
memset(buf, 0, ISO_BLOCKSIZE);
|
for (i=0; extent_length>0; i++) {
|
||||||
lsn = p_statbuf->lsn[j] + (lsn_t)i;
|
if (FormatStatus) goto out;
|
||||||
if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) {
|
memset(buf, 0, ISO_BLOCKSIZE);
|
||||||
uprintf(" Error reading ISO9660 file %s at LSN %lu",
|
lsn = p_statbuf->lsn[j] + (lsn_t)i;
|
||||||
psz_iso_name, (long unsigned int)lsn);
|
if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) {
|
||||||
goto out;
|
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) {
|
if (preserve_timestamps) {
|
||||||
|
|
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 3.1.1322"
|
CAPTION "Rufus 3.1.1323"
|
||||||
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
|
||||||
|
@ -389,8 +389,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 3,1,1322,0
|
FILEVERSION 3,1,1323,0
|
||||||
PRODUCTVERSION 3,1,1322,0
|
PRODUCTVERSION 3,1,1323,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -407,13 +407,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "3.1.1322"
|
VALUE "FileVersion", "3.1.1323"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||||
VALUE "OriginalFilename", "rufus.exe"
|
VALUE "OriginalFilename", "rufus.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "3.1.1322"
|
VALUE "ProductVersion", "3.1.1323"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Reference in a new issue