diff --git a/.vs/ext2fs.vcxproj b/.vs/ext2fs.vcxproj index 24402fba..dfcb71f2 100644 --- a/.vs/ext2fs.vcxproj +++ b/.vs/ext2fs.vcxproj @@ -197,7 +197,7 @@ MultiThreadedDebug ..\src;..\src\msvc-missing CompileAsC - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -214,7 +214,7 @@ _CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug ..\src;..\src\msvc-missing - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -231,7 +231,7 @@ _CRT_SECURE_NO_WARNINGS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions) MultiThreadedDebug ..\src;..\src\msvc-missing - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -250,7 +250,7 @@ MultiThreadedDebug ..\src;..\src\msvc-missing CompileAsC - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -266,7 +266,7 @@ MultiThreaded ..\src;..\src\msvc-missing CompileAsC - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -285,7 +285,7 @@ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded ..\src;..\src\msvc-missing - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -303,7 +303,7 @@ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded ..\src;..\src\msvc-missing - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true @@ -321,7 +321,7 @@ MultiThreaded ..\src;..\src\msvc-missing CompileAsC - 4018;4146;4244;4267 + 4018;4146;4244;4267;4996 true diff --git a/src/drive.c b/src/drive.c index b2a91fb6..5e7c4def 100644 --- a/src/drive.c +++ b/src/drive.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Drive access function calls - * Copyright © 2011-2018 Pete Batard + * Copyright © 2011-2019 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,6 +57,10 @@ const GUID PARTITION_MSFT_RESERVED_GUID = const GUID PARTITION_SYSTEM_GUID = { 0xc12a7328L, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} }; #endif +#if !defined(PARTITION_LINUX_HOME_GUID) +const GUID PARTITION_LINUX_HOME_GUID = + { 0x933ac7e1l, 0x2eb4, 0x4f13, {0xb8, 0x44, 0x0e, 0x14, 0xe2, 0xae, 0xf9, 0x15 } }; +#endif #if defined(__MINGW32__) const IID CLSID_VdsLoader = { 0x9c38ed61, 0xd565, 0x4728, { 0xae, 0xee, 0xc8, 0x09, 0x52, 0xf0, 0xec, 0xde } }; @@ -75,6 +79,7 @@ PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryVolumeInformationFile, (HANDLE, PIO_STATUS_ */ RUFUS_DRIVE_INFO SelectedDrive; BOOL installed_uefi_ntfs; +uint64_t persistence_size = 0; const char* sfd_name = "Super Floppy Disk"; /* @@ -1159,22 +1164,30 @@ BOOL MountVolume(char* drive_name, char *drive_guid) } if (!SetVolumeMountPointA(drive_name, drive_guid)) { - // If we get ERROR_DIR_NOT_EMPTY, check that mountpoints match... if (GetLastError() == ERROR_DIR_NOT_EMPTY) { if (!GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid))) { uprintf("%s is already mounted, but volume GUID could not be checked: %s", drive_name, WindowsErrorString()); - return FALSE; - } - if (safe_strcmp(drive_guid, mounted_guid) != 0) { + } else if (safe_strcmp(drive_guid, mounted_guid) != 0) { uprintf("%s is mounted, but volume GUID doesn't match:\r\n expected %s, got %s", drive_name, drive_guid, mounted_guid); - return FALSE; + } else { + uprintf("%s is already mounted as %C:", drive_guid, drive_name[0]); + return TRUE; + } + uprintf("Retrying after dismount..."); + if (!DeleteVolumeMountPointA(drive_name)) + uprintf("Warning: Could not delete volume mountpoint: %s", WindowsErrorString()); + if (SetVolumeMountPointA(drive_name, drive_guid)) + return TRUE; + if ((GetLastError() == ERROR_DIR_NOT_EMPTY) && + GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid)) && + (safe_strcmp(drive_guid, mounted_guid) == 0)) { + uprintf("%s was remounted as %C: (second time lucky!)", drive_guid, drive_name[0]); + return TRUE; } - uprintf("%s is already mounted as %C:", drive_guid, drive_name[0]); - } else { - return FALSE; } + return FALSE; } return TRUE; } @@ -1403,10 +1416,14 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m else ms_efi_size = 1200*MB; // That'll teach you to have a nonstandard disk! extra_part_size_in_tracks = (ms_efi_size + bytes_per_track - 1) / bytes_per_track; - } else if (extra_partitions & XP_UEFI_NTFS) + } else if (extra_partitions & XP_UEFI_NTFS) { extra_part_size_in_tracks = (max(MIN_EXTRA_PART_SIZE, uefi_ntfs_size) + bytes_per_track - 1) / bytes_per_track; - else if (extra_partitions & XP_COMPAT) + } else if (extra_partitions & XP_COMPAT) { extra_part_size_in_tracks = 1; // One track for the extra partition + } else if ((extra_partitions & XP_CASPER)) { + assert(persistence_size != 0); + extra_part_size_in_tracks = persistence_size / bytes_per_track; + } uprintf("Reserved %" PRIi64" tracks (%s) for extra partition", extra_part_size_in_tracks, SizeToHumanReadable(extra_part_size_in_tracks * bytes_per_track, TRUE, FALSE)); main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.SectorsPerTrack) - @@ -1449,15 +1466,37 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart = (extra_partitions & XP_UEFI_NTFS)?uefi_ntfs_size: extra_part_size_in_tracks * SelectedDrive.SectorsPerTrack * SelectedDrive.SectorSize; if (partition_style == PARTITION_STYLE_GPT) { - DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = (extra_partitions & XP_UEFI_NTFS)? - PARTITION_BASIC_DATA_GUID:PARTITION_SYSTEM_GUID; + const wchar_t* name = L"Basic Data"; + const GUID* guid = &PARTITION_BASIC_DATA_GUID; + if (extra_partitions & XP_MSR) { + guid = &PARTITION_SYSTEM_GUID; + name = L"EFI system partition"; + } else if (extra_partitions & XP_CASPER) { + // TODO: We may also want to use PARTITION_LINUX_HOME_GUID as fallback + // to automout as /home in case casper-rw fails. + name = L"casper-rw"; // Just in case + } else if (extra_partitions & XP_UEFI_NTFS) { + name = L"UEFI:NTFS"; + } else { + assert(FALSE); + } + DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = *guid; IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId)); - wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, (extra_partitions & XP_UEFI_NTFS)?L"UEFI:NTFS":L"EFI system partition"); + wcscpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, name); } else { - DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = (extra_partitions & XP_UEFI_NTFS)?0xef:RUFUS_EXTRA_PARTITION_TYPE; - if (extra_partitions & XP_COMPAT) + BYTE type = 0; + if (extra_partitions & XP_UEFI_NTFS) { + type = 0xef; + } else if (extra_partitions & XP_CASPER) { + type = 0x83; + } else if (extra_partitions & XP_COMPAT) { + type = RUFUS_EXTRA_PARTITION_TYPE; // Set the one track compatibility partition to be all hidden sectors DriveLayoutEx.PartitionEntry[pn].Mbr.HiddenSectors = SelectedDrive.SectorsPerTrack; + } else { + assert(FALSE); + } + DriveLayoutEx.PartitionEntry[pn].Mbr.PartitionType = type; } // We need to write the UEFI:NTFS partition before we refresh the disk diff --git a/src/drive.h b/src/drive.h index 47a81f43..098c2138 100644 --- a/src/drive.h +++ b/src/drive.h @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Drive access function calls - * Copyright © 2011-2018 Pete Batard + * Copyright © 2011-2019 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ #define XP_EFI 0x02 #define XP_UEFI_NTFS 0x04 #define XP_COMPAT 0x08 +#define XP_CASPER 0x10 #define FILE_FLOPPY_DISKETTE 0x00000004 @@ -254,6 +255,7 @@ typedef struct { } ClusterSize[FS_MAX]; } RUFUS_DRIVE_INFO; extern RUFUS_DRIVE_INFO SelectedDrive; +extern uint64_t persistence_size; BOOL SetAutoMount(BOOL enable); BOOL GetAutoMount(BOOL* enabled); diff --git a/src/ext2fs/com_err.h b/src/ext2fs/com_err.h index 1725f816..2ef67d11 100644 --- a/src/ext2fs/com_err.h +++ b/src/ext2fs/com_err.h @@ -19,8 +19,6 @@ #include #include -#include "rufus.h" - typedef long errcode_t; struct error_table { @@ -30,8 +28,10 @@ struct error_table { }; struct et_list; +/* For use with Rufus */ +extern void _uprintf(const char *format, ...); #define VA_ARGS(...) , ##__VA_ARGS__ -#define com_err(src, err, fmt, ...) uprintf("%s: [%d] " # fmt, src?src:"ext2fs", err VA_ARGS(__VA_ARGS__)) +#define com_err(src, err, fmt, ...) _uprintf("%s: [%08X] " # fmt, src?src:"ext2fs", err - EXT2_ET_BASE VA_ARGS(__VA_ARGS__)) extern char const *error_message (long); extern void (*com_err_hook) (const char *, long, const char *, va_list); diff --git a/src/ext2fs/ext2fs.h b/src/ext2fs/ext2fs.h index 621322f5..fa87e308 100644 --- a/src/ext2fs/ext2fs.h +++ b/src/ext2fs/ext2fs.h @@ -31,7 +31,7 @@ extern "C" { /* * Non-GNU C compilers won't necessarily understand inline */ -#if (!defined(__GNUC__) && !defined(__WATCOMC__)) +#if (!defined(__GNUC__) && !defined(__WATCOMC__) && !defined(_MSC_VER)) #define NO_INLINE_FUNCS #endif @@ -1737,6 +1737,8 @@ extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, unsigned int flags, FILE *f); +/* Rufus addtional */ +extern errcode_t ext2fs_print_progress(uint64_t cur, uint64_t max); /* inline functions */ #ifdef NO_INLINE_FUNCS @@ -1796,6 +1798,8 @@ extern const struct ext2_inode *ext2fs_const_inode(const struct ext2_inode_large #else #ifdef __GNUC__ #define _INLINE_ extern __inline__ +#elif defined(_MSC_VER) +#define _INLINE_ extern __inline #else /* For Watcom C */ #define _INLINE_ extern inline #endif /* __GNUC__ */ diff --git a/src/ext2fs/extent.c b/src/ext2fs/extent.c index e846b064..28170381 100644 --- a/src/ext2fs/extent.c +++ b/src/ext2fs/extent.c @@ -1733,6 +1733,8 @@ size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle) if (ul_log2(extents_per_block) == 0) return last_result; + // Nice work, Coverity: We've just validated that ul_log2(extents_per_block) is non-zero! + // coverity[divide_by_zero] last_result = 1 + ((ul_log2(EXT_MAX_EXTENT_LBLK) - ul_log2(iblock_extents)) / ul_log2(extents_per_block)); last_blocksize = handle->fs->blocksize; diff --git a/src/ext2fs/fallocate.c b/src/ext2fs/fallocate.c index 67389ce7..19737c19 100644 --- a/src/ext2fs/fallocate.c +++ b/src/ext2fs/fallocate.c @@ -692,6 +692,7 @@ static errcode_t extent_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, * _get() will error out. */ start_again: + // coverity[check_return] ext2fs_extent_goto(handle, start); err = ext2fs_extent_get(handle, EXT2_EXTENT_CURRENT, &left_extent); if (err == EXT2_ET_NO_CURRENT_NODE) { @@ -808,7 +809,7 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, { struct ext2_inode inode_buf; blk64_t blk, x; - errcode_t err; + errcode_t err = 0; if (((flags & EXT2_FALLOCATE_FORCE_INIT) && (flags & EXT2_FALLOCATE_FORCE_UNINIT)) || @@ -837,6 +838,10 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, /* XXX: Allocate a bunch of blocks the slow way */ for (blk = start; blk < start + len; blk++) { + /* For Rufus usage */ + err = ext2fs_print_progress(blk, start + len); + if (err) + return err; err = ext2fs_bmap2(fs, ino, inode, NULL, 0, blk, 0, &x); if (err) return err; diff --git a/src/ext2fs/hashmap.c b/src/ext2fs/hashmap.c index 3d8ee814..eca9edc6 100644 --- a/src/ext2fs/hashmap.c +++ b/src/ext2fs/hashmap.c @@ -20,6 +20,8 @@ struct ext2fs_hashmap *ext2fs_hashmap_create( { struct ext2fs_hashmap *h = calloc(sizeof(struct ext2fs_hashmap) + sizeof(struct ext2fs_hashmap_entry) * size, 1); + if (!h) + return h; h->size = size; h->free = free_fct; h->hash = hash_fct; @@ -33,6 +35,8 @@ void ext2fs_hashmap_add(struct ext2fs_hashmap *h, void *data, const void *key, uint32_t hash = h->hash(key, key_len) % h->size; struct ext2fs_hashmap_entry *e = malloc(sizeof(*e)); + if (!e) + return; e->data = data; e->key = key; e->key_len = key_len; diff --git a/src/ext2fs/mkjournal.c b/src/ext2fs/mkjournal.c index 2e2e20fd..4b83543f 100644 --- a/src/ext2fs/mkjournal.c +++ b/src/ext2fs/mkjournal.c @@ -156,7 +156,7 @@ errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num, { int j, count; static void *buf; - static int stride_length; + static int stride_length = 0; errcode_t retval; /* If fs is null, clean up the static buffer and return */ @@ -509,6 +509,7 @@ errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks, retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); #endif #endif + // coverity[dead_error_condition] if (retval) { retval = errno; goto errout; diff --git a/src/format.c b/src/format.c index a2f0faa4..2485aa17 100644 --- a/src/format.c +++ b/src/format.c @@ -601,15 +601,9 @@ static BOOL FormatFAT32(DWORD DriveIndex) die("Failed to allocate memory\n", ERROR_NOT_ENOUGH_MEMORY); } - format_percent = 0.0f; for (i=0; i<(SystemAreaSize+BurstSize-1); i+=BurstSize) { - if (GetTickCount64() > LastRefresh + MAX_REFRESH) { - LastRefresh = GetTickCount64(); - format_percent = (100.0f*i)/(1.0f*(SystemAreaSize+BurstSize)); - PrintInfo(0, MSG_217, format_percent); - UpdateProgress(OP_FORMAT, format_percent); - } - if (IS_ERROR(FormatStatus)) goto out; // For cancellation + UPDATE_PERCENT(MSG_217, (100.0f*i) / (1.0f*(SystemAreaSize + BurstSize))); + CHECK_FOR_USER_CANCEL; if (write_sectors(hLogicalVolume, BytesPerSect, i, BurstSize, pZeroSect) != (BytesPerSect*BurstSize)) { die("Error clearing reserved sectors\n", ERROR_WRITE_FAULT); } @@ -664,6 +658,139 @@ out: return r; } +errcode_t ext2fs_print_progress(uint64_t cur, uint64_t max) +{ + UPDATE_PERCENT(MSG_217, 25.0f + 75.0f * cur / (float)max); + return IS_ERROR(FormatStatus) ? EXT2_ET_CANCEL_REQUESTED : 0; +} + +const char* error_message(errcode_t error_code) +{ + static char error_string[256]; + + switch (error_code) { + case EXT2_ET_MAGIC_EXT2FS_FILSYS: + case EXT2_ET_MAGIC_BADBLOCKS_LIST: + case EXT2_ET_MAGIC_BADBLOCKS_ITERATE: + case EXT2_ET_MAGIC_INODE_SCAN: + case EXT2_ET_MAGIC_IO_CHANNEL: + case EXT2_ET_MAGIC_IO_MANAGER: + case EXT2_ET_MAGIC_BLOCK_BITMAP: + case EXT2_ET_MAGIC_INODE_BITMAP: + case EXT2_ET_MAGIC_GENERIC_BITMAP: + case EXT2_ET_MAGIC_ICOUNT: + case EXT2_ET_MAGIC_EXTENT_HANDLE: + case EXT2_ET_BAD_MAGIC: + return "Bad magic"; + case EXT2_ET_RO_FILSYS: + return "Read-only file system"; + case EXT2_ET_GDESC_BAD_BLOCK_MAP: + case EXT2_ET_GDESC_BAD_INODE_MAP: + case EXT2_ET_GDESC_BAD_INODE_TABLE: + return "Bad map or table"; + case EXT2_ET_UNEXPECTED_BLOCK_SIZE: + return "Unexpected block size"; + case EXT2_ET_DIR_CORRUPTED: + return "Corrupted entry"; + case EXT2_ET_GDESC_READ: + case EXT2_ET_GDESC_WRITE: + case EXT2_ET_INODE_BITMAP_WRITE: + case EXT2_ET_INODE_BITMAP_READ: + case EXT2_ET_BLOCK_BITMAP_WRITE: + case EXT2_ET_BLOCK_BITMAP_READ: + case EXT2_ET_INODE_TABLE_WRITE: + case EXT2_ET_INODE_TABLE_READ: + case EXT2_ET_NEXT_INODE_READ: + case EXT2_ET_SHORT_READ: + case EXT2_ET_SHORT_WRITE: + return "read/write error"; + case EXT2_ET_DIR_NO_SPACE: + return "no space left"; + case EXT2_ET_TOOSMALL: + return "Too small"; + case EXT2_ET_BAD_DEVICE_NAME: + return "Bad device name"; + case EXT2_ET_MISSING_INODE_TABLE: + return "Missing inode table"; + case EXT2_ET_CORRUPT_SUPERBLOCK: + return "Superblock is corrupted"; + case EXT2_ET_CALLBACK_NOTHANDLED: + return "Unhandled callback"; + case EXT2_ET_BAD_BLOCK_IN_INODE_TABLE: + return "Bad block in inode table"; + case EXT2_ET_UNSUPP_FEATURE: + case EXT2_ET_RO_UNSUPP_FEATURE: + case EXT2_ET_UNIMPLEMENTED: + return "Unsupported feature"; + case EXT2_ET_LLSEEK_FAILED: + return "Seek failed"; + case EXT2_ET_NO_MEMORY: + case EXT2_ET_BLOCK_ALLOC_FAIL: + case EXT2_ET_INODE_ALLOC_FAIL: + return "Out of memory"; + case EXT2_ET_INVALID_ARGUMENT: + return "Invalid argument"; + case EXT2_ET_NO_DIRECTORY: + return "No directory"; + case EXT2_ET_FILE_NOT_FOUND: + return "File not found"; + case EXT2_ET_FILE_RO: + return "File is read-only"; + case EXT2_ET_DIR_EXISTS: + return "Directory already exists"; + case EXT2_ET_CANCEL_REQUESTED: + return "Cancel requested"; + case EXT2_ET_FILE_TOO_BIG: + return "File too big"; + case EXT2_ET_JOURNAL_NOT_BLOCK: + case EXT2_ET_NO_JOURNAL_SB: + return "No journal superblock"; + case EXT2_ET_JOURNAL_TOO_SMALL: + return "Journal too small"; + case EXT2_ET_NO_JOURNAL: + return "No journal"; + case EXT2_ET_TOO_MANY_INODES: + return "Too many inodes"; + case EXT2_ET_NO_CURRENT_NODE: + return "No current node"; + case EXT2_ET_OP_NOT_SUPPORTED: + return "Operation not supported"; + case EXT2_ET_IO_CHANNEL_NO_SUPPORT_64: + return "I/O Channel does not support 64-bit operation"; + case EXT2_ET_BAD_DESC_SIZE: + return "Bad descriptor size"; + case EXT2_ET_INODE_CSUM_INVALID: + case EXT2_ET_INODE_BITMAP_CSUM_INVALID: + case EXT2_ET_EXTENT_CSUM_INVALID: + case EXT2_ET_DIR_CSUM_INVALID: + case EXT2_ET_EXT_ATTR_CSUM_INVALID: + case EXT2_ET_SB_CSUM_INVALID: + case EXT2_ET_BLOCK_BITMAP_CSUM_INVALID: + case EXT2_ET_MMP_CSUM_INVALID: + return "Invalid checksum"; + case EXT2_ET_UNKNOWN_CSUM: + return "Unknown checksum"; + case EXT2_ET_FILE_EXISTS: + return "File exists"; + case EXT2_ET_INODE_IS_GARBAGE: + return "Inode is garbage"; + case EXT2_ET_JOURNAL_FLAGS_WRONG: + return "Wrong journal flags"; + case EXT2_ET_FILESYSTEM_CORRUPTED: + return "File system is corrupted"; + case EXT2_ET_BAD_CRC: + return "Bad CRC"; + case EXT2_ET_CORRUPT_JOURNAL_SB: + return "Journal Superblock is corrupted"; + case EXT2_ET_INODE_CORRUPTED: + case EXT2_ET_EA_INODE_CORRUPTED: + return "Inode is corrupted"; + default: + static_sprintf(error_string, "Unknown ext2fs error 0x%08lX", error_code - EXT2_ET_BASE); + return error_string; + } +} + BOOL FormatExt2Fs(const char* label) { // Mostly taken from mke2fs.conf @@ -709,11 +836,12 @@ BOOL FormatExt2Fs(const char* label) goto out; PrintInfoDebug(0, MSG_222, "ext3"); + LastRefresh = 0; // Figure out the volume size and block size r = ext2fs_get_device_size2(path, KB, &size); if ((r != 0) || (size == 0)) { - uprintf("Could not read device size: %d", r); + uprintf("Could not read device size: %s", error_message(r)); goto out; } size *= KB; @@ -736,7 +864,7 @@ BOOL FormatExt2Fs(const char* label) features.s_inode_size = ext2fs_default[i].inode_size; features.s_inodes_count = ((ext2fs_blocks_count(&features) >> ext2fs_default[i].inode_ratio) > UINT32_MAX) ? UINT32_MAX : (uint32_t)(ext2fs_blocks_count(&features) >> ext2fs_default[i].inode_ratio); - uprintf("%d inodes, %lld blocks (block size = %d)", features.s_inodes_count, size, EXT2_BLOCK_SIZE(&features)); + uprintf("%d possible inodes out of %lld blocks (block size = %d)", features.s_inodes_count, size, EXT2_BLOCK_SIZE(&features)); uprintf("%lld blocks (%0.1f%%) reserved for the super user", ext2fs_r_blocks_count(&features), reserve_ratio * 100.0f); // Set features for ext3 @@ -747,13 +875,13 @@ BOOL FormatExt2Fs(const char* label) ext2fs_set_feature_filetype(&features); ext2fs_set_feature_sparse_super(&features); ext2fs_set_feature_large_file(&features); - features.s_backup_bgs[0] = 1; + features.s_backup_bgs[0] = ~0; features.s_default_mount_opts = EXT2_DEFM_XATTR_USER | EXT2_DEFM_ACL; // Now that we have set our base features, initialize a virtual superblock r = ext2fs_initialize(path, EXT2_FLAG_EXCLUSIVE | EXT2_FLAG_64BITS, &features, manager, &ext2fs); if (r != 0) { - uprintf("Could not initialize ext2fs features: %d", r); + uprintf("Could not initialize ext2fs features: %s", error_message(r)); goto out; } @@ -763,15 +891,15 @@ BOOL FormatExt2Fs(const char* label) r = io_channel_write_blk64(ext2fs->io, 0, 16, buf); safe_free(buf); if (r != 0) { - uprintf("Could not zero ext2fs superblock area: %d", r); + uprintf("Could not zero ext2fs superblock area: %s", error_message(r)); goto out; } // Finish setting up the file system - CoCreateGuid((GUID*)ext2fs->super->s_uuid); + IGNORE_RETVAL(CoCreateGuid((GUID*)ext2fs->super->s_uuid)); ext2fs_init_csum_seed(ext2fs); ext2fs->super->s_def_hash_version = EXT2_HASH_HALF_MD4; - CoCreateGuid((GUID*)ext2fs->super->s_hash_seed); + IGNORE_RETVAL(CoCreateGuid((GUID*)ext2fs->super->s_hash_seed)); ext2fs->super->s_max_mnt_count = -1; ext2fs->super->s_creator_os = EXT2_OS_WINDOWS; ext2fs->super->s_errors = EXT2_ERRORS_CONTINUE; @@ -779,37 +907,45 @@ BOOL FormatExt2Fs(const char* label) r = ext2fs_allocate_tables(ext2fs); if (r != 0) { - uprintf("Could not allocate ext2fs tables: %d", r); + uprintf("Could not allocate ext2fs tables: %s", error_message(r)); goto out; } r = ext2fs_convert_subcluster_bitmap(ext2fs, &ext2fs->block_map); if (r != 0) { - uprintf("Could set ext2fs cluster bitmap: %d", r); + uprintf("Could set ext2fs cluster bitmap: %s", error_message(r)); goto out; } - // Wipe inode table + // This should take about 10% + uprintf("Creating %d inodes...", ext2fs->group_desc_count); for (i = 0; i < (int)ext2fs->group_desc_count; i++) { + UPDATE_PERCENT(MSG_217, 25.0f * i / ((float)ext2fs->group_desc_count)) + CHECK_FOR_USER_CANCEL; cur = ext2fs_inode_table_loc(ext2fs, i); count = ext2fs_div_ceil((ext2fs->super->s_inodes_per_group - ext2fs_bg_itable_unused(ext2fs, i)) * EXT2_BLOCK_SIZE(ext2fs->super), EXT2_BLOCK_SIZE(ext2fs->super)); + uprintfs("+"); + if ((i + 1) % 80 == 0) + uprintfs("\r\n"); r = ext2fs_zero_blocks2(ext2fs, cur, count, &cur, &count); if (r != 0) { - uprintf("Could not zero ext2fs inode at %llu (%d blocks): %d\n", cur, count, r); + uprintf("Could not zero ext2fs inode at %llu (%d blocks): %s\n", cur, count, error_message(r)); goto out; } } + uprintfs("\r\n"); + UPDATE_PERCENT(MSG_217, 25.0f); // Create root and lost+found dirs r = ext2fs_mkdir(ext2fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0); if (r != 0) { - uprintf("Failed to create ext2fs root dir: %d", r); + uprintf("Failed to create ext2fs root dir: %s", error_message(r)); goto out; } ext2fs->umask = 077; r = ext2fs_mkdir(ext2fs, EXT2_ROOT_INO, 0, "lost+found"); if (r != 0) { - uprintf("Failed to create ext2fs 'lost+found' dir: %d", r); + uprintf("Failed to create ext2fs 'lost+found' dir: %s", error_message(r)); goto out; } @@ -820,27 +956,35 @@ BOOL FormatExt2Fs(const char* label) r = ext2fs_mark_inode_bitmap2(ext2fs->inode_map, EXT2_BAD_INO); if (r != 0) { - uprintf("Could not set ext2fs inode bitmaps: %d", r); + uprintf("Could not set ext2fs inode bitmaps: %s", error_message(r)); goto out; } ext2fs_inode_alloc_stats(ext2fs, EXT2_BAD_INO, 1); r = ext2fs_update_bb_inode(ext2fs, NULL); if (r != 0) { - uprintf("Could not set ext2fs inode stats: %d", r); + uprintf("Could not set ext2fs inode stats:%s", error_message(r)); goto out; } // Create the journal journal_size = ext2fs_default_journal_size(ext2fs_blocks_count(ext2fs->super)); + journal_size /= 2; // That journal init is really killing us! uprintf("Creating journal (%d blocks)", journal_size); + // Even with EXT2_MKJOURNAL_LAZYINIT, this call is absolutely dreadful in terms of speed... r = ext2fs_add_journal_inode(ext2fs, journal_size, EXT2_MKJOURNAL_NO_MNT_CHECK | EXT2_MKJOURNAL_LAZYINIT); + if (r != 0) { + uprintf("Could not create Journal: %s", error_message(r)); + goto out; + } // Finally we can call close() to get the file system gets created r = ext2fs_close(ext2fs); if (r != 0) { - uprintf("Could not create ext3 volume: %d", r); + uprintf("Could not create ext3 volume: %s", error_message(r)); goto out; } + UPDATE_PERCENT(MSG_217, 100.0f); + uprintf("Done"); ret = TRUE; out: @@ -1024,22 +1168,19 @@ static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSi uprintf("Erasing %d sectors", num_sectors_to_clear); for (i=0; i= WRITE_RETRIES) goto out; + uprintf("Retrying in %d seconds...", WRITE_TIMEOUT / 1000); + // Don't sit idly but use the downtime to check for conflicting processes... + Sleep(CheckDriveAccess(WRITE_TIMEOUT, FALSE)); } } } for (i = last_sector - MAX_SECTORS_TO_CLEAR; i < last_sector; i++) { for (j = 1; j <= WRITE_RETRIES; j++) { - if (IS_ERROR(FormatStatus)) - goto out; + CHECK_FOR_USER_CANCEL; if (write_sectors(hPhysicalDrive, SectorSize, i, 1, pBuf) != SectorSize) { if (j < WRITE_RETRIES) { uprintf("Retrying in %d seconds...", WRITE_TIMEOUT / 1000); @@ -1759,12 +1900,7 @@ static BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi) static void update_progress(const uint64_t processed_bytes) { - if (GetTickCount64() > LastRefresh + MAX_REFRESH) { - LastRefresh = GetTickCount64(); - format_percent = (100.0f*processed_bytes)/(1.0f*img_report.image_size); - PrintInfo(0, MSG_261, format_percent); - UpdateProgress(OP_FORMAT, format_percent); - } + UPDATE_PERCENT(MSG_261, (100.0f*processed_bytes) / (1.0f*img_report.image_size)); } /* Write an image file or zero a drive */ @@ -1824,13 +1960,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, HANDLE hSourceImage) // will be as fast, if not faster, than whatever async scheme you can come up with. rSize = BufSize; for (wb = 0, wSize = 0; wb < (uint64_t)SelectedDrive.DiskSize; wb += wSize) { - if (GetTickCount64() > LastRefresh + MAX_REFRESH) { - LastRefresh = GetTickCount64(); - format_percent = (100.0f*wb) / (1.0f*target_size); - PrintInfo(0, hSourceImage?MSG_261:fast_zeroing?MSG_306:MSG_286, format_percent); - UpdateProgress(OP_FORMAT, format_percent); - } - + UPDATE_PERCENT(hSourceImage?MSG_261:fast_zeroing?MSG_306:MSG_286, (100.0f*wb)/(1.0f*target_size)); if (hSourceImage != NULL) { s = ReadFile(hSourceImage, buffer, BufSize, &rSize, NULL); if (!s) { @@ -1976,6 +2106,8 @@ DWORD WINAPI FormatThread(void* param) extra_partitions = XP_UEFI_NTFS; else if (IsChecked(IDC_OLD_BIOS_FIXES)) extra_partitions = XP_COMPAT; + else if ((boot_type == BT_IMAGE) && !write_as_image && HAS_PERSISTENCE(img_report) && persistence_size) + extra_partitions = XP_CASPER; PrintInfoDebug(0, MSG_225); hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, FALSE, !lock_drive); @@ -2198,6 +2330,11 @@ DWORD WINAPI FormatThread(void* param) goto out; } + // Format Casper partition if it exists + if (extra_partitions & XP_CASPER) { + ret = FormatExt2Fs("casper-rw"); + } + // Thanks to Microsoft, we must fix the MBR AFTER the drive has been formatted if ((partition_type == PARTITION_STYLE_MBR) || ((boot_type != BT_NON_BOOTABLE) && (partition_type == PARTITION_STYLE_GPT))) { PrintInfoDebug(0, MSG_228); // "Writing master boot record..." @@ -2219,7 +2356,7 @@ DWORD WINAPI FormatThread(void* param) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_VOLUME_ID; goto out; } - uprintf("Found volume GUID %s, guid_volume"); + uprintf("Found volume GUID %s", guid_volume); if (!MountVolume(drive_name, guid_volume)) { uprintf("Could not remount %s as %C: %s\n", guid_volume, drive_name[0], WindowsErrorString()); @@ -2467,12 +2604,7 @@ DWORD WINAPI SaveImageThread(void* param) } if (rSize == 0) break; - if (GetTickCount64() > LastRefresh + MAX_REFRESH) { - LastRefresh = GetTickCount64(); - format_percent = (100.0f*wb)/(1.0f*img_save->DeviceSize); - PrintInfo(0, MSG_261, format_percent); - UpdateProgress(OP_FORMAT, format_percent); - } + UPDATE_PERCENT(MSG_261, (100.0f*wb)/(1.0f*img_save->DeviceSize)); for (i = 1; i <= WRITE_RETRIES; i++) { CHECK_FOR_USER_CANCEL; s = WriteFile(hDestImage, buffer, rSize, &wSize, NULL); diff --git a/src/format.h b/src/format.h index 29d30a28..663439f5 100644 --- a/src/format.h +++ b/src/format.h @@ -157,6 +157,10 @@ typedef struct { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|err; \ goto out; } while(0) +#define UPDATE_PERCENT(msg, percent) if (GetTickCount64() > LastRefresh + MAX_REFRESH) { \ + LastRefresh = GetTickCount64(); PrintInfo(0, msg, percent); \ + UpdateProgress(OP_FORMAT, percent); } + // For ext2/ext3/ext4 formatting typedef struct { uint64_t max_size; diff --git a/src/iso.c b/src/iso.c index 0841d0c4..772de32c 100644 --- a/src/iso.c +++ b/src/iso.c @@ -91,7 +91,6 @@ static const char* pe_file[] = { "ntdetect.com", "setupldr.bin", "txtsetup.sif" static const char* reactos_name = "setupldr.sys"; // TODO: freeldr.sys doesn't seem to work static const char* kolibri_name = "kolibri.img"; static const char* autorun_name = "autorun.inf"; -static const char* casper_name = "CASPER"; static const char* stupid_antivirus = " NOTE: This is usually caused by a poorly designed security solution. " "See https://goo.gl/QTobxX.\r\n This file will be skipped for now, but you should really " "look into using a *SMARTER* antivirus solution."; @@ -199,9 +198,6 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const if (safe_stricmp(psz_basename, kolibri_name) == 0) { img_report.has_kolibrios = TRUE; } - if (safe_stricmp(psz_basename, casper_name) == 0) { - img_report.has_casper = TRUE; - } if (safe_stricmp(psz_basename, bootmgr_efi_name) == 0) { img_report.has_efi |= 1; } diff --git a/src/rufus.c b/src/rufus.c index f62d5152..a661a0c7 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -109,7 +109,6 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa BOOL use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE; BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE; BOOL write_as_image = FALSE, installed_uefi_ntfs = FALSE, enable_fido = FALSE; -uint64_t persistence_size = 0; float fScale = 1.0f; int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = -1; int default_fs, fs_type, boot_type, partition_type, target_type; // file system, boot type, partition type, target type diff --git a/src/rufus.h b/src/rufus.h index de175ba9..bae4fc2f 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -28,8 +28,6 @@ #pragma once -/* Program options */ -#define RUFUS_LOGGING // print info to logging facility /* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */ //#define RUFUS_TEST @@ -152,9 +150,10 @@ #define safe_vsnprintf vsnprintf #endif -#ifdef RUFUS_LOGGING extern void _uprintf(const char *format, ...); +extern void _uprintfs(const char *str); #define uprintf(...) _uprintf(__VA_ARGS__) +#define uprintfs(s) _uprintfs(s) #define vuprintf(...) do { if (verbose) _uprintf(__VA_ARGS__); } while(0) #define vvuprintf(...) do { if (verbose > 1) _uprintf(__VA_ARGS__); } while(0) #define suprintf(...) do { if (!bSilent) _uprintf(__VA_ARGS__); } while(0) @@ -168,18 +167,6 @@ extern void _uprintf(const char *format, ...); #else #define duprintf(...) #endif -#else -#define uprintf(...) -#define vuprintf(...) -#define vvuprintf(...) -#define duprintf(...) -#define suprintf(...) -#define uuprintf(...) -#define duprintf(...) -#define ubprintf(...) -#define ubflush() -#define _uprintf NULL -#endif /* Custom Windows messages */ enum user_message_type { @@ -314,7 +301,7 @@ enum checksum_type { #define IS_EFI_BOOTABLE(r) (r.has_efi != 0) #define IS_BIOS_BOOTABLE(r) (HAS_BOOTMGR(r) || HAS_SYSLINUX(r) || HAS_WINPE(r) || HAS_GRUB(r) || HAS_REACTOS(r) || HAS_KOLIBRIOS(r)) #define HAS_WINTOGO(r) (HAS_BOOTMGR(r) && IS_EFI_BOOTABLE(r) && HAS_WININST(r)) -#define HAS_PERSISTENCE(r) (r.has_casper) +#define HAS_PERSISTENCE(r) ((HAS_SYSLINUX(r) || HAS_GRUB(r)) && !(HAS_WINDOWS(r) || HAS_REACTOS(r) || HAS_KOLIBRIOS(r))) #define IS_FAT(fs) ((fs_type == FS_FAT16) || (fs_type == FS_FAT32)) typedef struct { @@ -349,7 +336,6 @@ typedef struct { BOOLEAN uses_minint; BOOLEAN compression_type; BOOLEAN is_vhd; - BOOLEAN has_casper; uint16_t sl_version; // Syslinux/Isolinux version char sl_version_str[12]; char sl_version_ext[32]; diff --git a/src/rufus.rc b/src/rufus.rc index a3c5ddaa..fcc444cc 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.6.1523" +CAPTION "Rufus 3.6.1524" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -394,8 +394,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,6,1523,0 - PRODUCTVERSION 3,6,1523,0 + FILEVERSION 3,6,1524,0 + PRODUCTVERSION 3,6,1524,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -413,13 +413,13 @@ BEGIN VALUE "Comments", "https://akeo.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.6.1523" + VALUE "FileVersion", "3.6.1524" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus-3.6.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.6.1523" + VALUE "ProductVersion", "3.6.1524" END END BLOCK "VarFileInfo" diff --git a/src/stdio.c b/src/stdio.c index e0c2b4da..00652726 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -42,7 +42,6 @@ HWND hStatus; size_t ubuffer_pos = 0; char ubuffer[UBUFFER_SIZE]; // Buffer for ubpushf() messages we don't log right away -#ifdef RUFUS_LOGGING void _uprintf(const char *format, ...) { static char buf[4096]; @@ -78,7 +77,19 @@ void _uprintf(const char *format, ...) } free(wbuf); } -#endif + +void _uprintfs(const char* str) +{ + wchar_t* wstr; + wstr = utf8_to_wchar(str); + OutputDebugStringW(wstr); + if ((hLog != NULL) && (hLog != INVALID_HANDLE_VALUE)) { + Edit_SetSel(hLog, MAX_LOG_SIZE, MAX_LOG_SIZE); + Edit_ReplaceSel(hLog, wstr); + Edit_Scroll(hLog, Edit_GetLineCount(hLog), 0); + } + free(wstr); +} // Prints a bitstring of a number of any size, with or without leading zeroes. // See also the printbits() and printbitslz() helper macros in rufus.h