mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[iso] add symlink support for target file systems that support it
* For now that means only NTFS. And we only do that for ISO-9660/Rock Ridge images.
This commit is contained in:
parent
0bd38abd4e
commit
e9d588a6e0
3 changed files with 87 additions and 45 deletions
112
src/iso.c
112
src/iso.c
|
@ -122,7 +122,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;
|
||||
static const int64_t old_c32_threshold[NB_OLD_C32] = OLD_C32_THRESHOLD;
|
||||
static uint8_t joliet_level = 0;
|
||||
static uint64_t total_blocks, nb_blocks;
|
||||
static uint64_t total_blocks, extra_blocks, nb_blocks;
|
||||
static BOOL scan_only = FALSE;
|
||||
static StrArray config_path, isolinux_path, modified_path;
|
||||
static char symlinked_syslinux[MAX_PATH];
|
||||
|
@ -311,20 +311,20 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const
|
|||
}
|
||||
|
||||
// Check for PE (XP) specific files in "/i386", "/amd64" or "/minint"
|
||||
for (i=0; i<ARRAYSIZE(pe_dirname); i++)
|
||||
for (i = 0; i < ARRAYSIZE(pe_dirname); i++)
|
||||
if (safe_stricmp(psz_dirname, pe_dirname[i]) == 0)
|
||||
for (j=0; j<ARRAYSIZE(pe_file); j++)
|
||||
if (safe_stricmp(psz_basename, pe_file[j]) == 0)
|
||||
img_report.winpe |= (1<<j)<<(ARRAYSIZE(pe_dirname)*i);
|
||||
|
||||
for (i=0; i<ARRAYSIZE(isolinux_bin); i++) {
|
||||
for (i = 0; i < ARRAYSIZE(isolinux_bin); i++) {
|
||||
if (safe_stricmp(psz_basename, isolinux_bin[i]) == 0) {
|
||||
// Maintain a list of all the isolinux.bin files found
|
||||
StrArrayAdd(&isolinux_path, psz_fullpath, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<NB_OLD_C32; i++) {
|
||||
for (i = 0; i < NB_OLD_C32; i++) {
|
||||
if (props->is_old_c32[i])
|
||||
img_report.has_old_c32[i] = TRUE;
|
||||
}
|
||||
|
@ -706,7 +706,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
HANDLE file_handle = NULL;
|
||||
DWORD buf_size, wr_size, err;
|
||||
EXTRACT_PROPS props;
|
||||
BOOL is_symlink, is_identical, free_p_statbuf = FALSE;
|
||||
BOOL is_symlink, is_identical, create_file, free_p_statbuf = FALSE;
|
||||
int length, r = 1;
|
||||
char psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL;
|
||||
char tmp[128], target_path[256];
|
||||
|
@ -798,7 +798,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
static_sprintf(target_path, "%s/%s", psz_path, p_statbuf->rr.psz_symlink);
|
||||
iso9660_stat_t *p_statbuf2 = iso9660_ifs_stat_translate(p_iso, target_path);
|
||||
if (p_statbuf2 != NULL) {
|
||||
total_blocks += (p_statbuf2->total_size + ISO_BLOCKSIZE - 1) / ISO_BLOCKSIZE;
|
||||
extra_blocks += (p_statbuf2->total_size + ISO_BLOCKSIZE - 1) / ISO_BLOCKSIZE;
|
||||
iso9660_stat_free(p_statbuf2);
|
||||
}
|
||||
}
|
||||
|
@ -821,8 +821,26 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
psz_sanpath = sanitize_filename(psz_fullpath, &is_identical);
|
||||
if (!is_identical)
|
||||
uprintf(" File name sanitized to '%s'", psz_sanpath);
|
||||
create_file = TRUE;
|
||||
if (is_symlink) {
|
||||
if (file_length == 0) {
|
||||
if (fs_type == FS_NTFS) {
|
||||
// Replicate symlinks if NTFS is being used
|
||||
static_sprintf(target_path, "%s/%s", psz_path, p_statbuf->rr.psz_symlink);
|
||||
iso9660_stat_t* p_statbuf2 = iso9660_ifs_stat_translate(p_iso, target_path);
|
||||
if (p_statbuf2 != NULL) {
|
||||
to_windows_path(psz_fullpath);
|
||||
to_windows_path(p_statbuf->rr.psz_symlink);
|
||||
uprintf("Symlinking: %s%s ➔ %s", psz_fullpath,
|
||||
(p_statbuf2->type == _STAT_DIR) ? "\\" : "", p_statbuf->rr.psz_symlink);
|
||||
if (!CreateSymbolicLinkU(psz_fullpath, p_statbuf->rr.psz_symlink,
|
||||
(p_statbuf2->type == _STAT_DIR) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0))
|
||||
uprintf(" Could not create symlink: %s", WindowsErrorString());
|
||||
to_unix_path(p_statbuf->rr.psz_symlink);
|
||||
to_unix_path(psz_fullpath);
|
||||
iso9660_stat_free(p_statbuf2);
|
||||
create_file = FALSE;
|
||||
}
|
||||
} else if (file_length == 0) {
|
||||
if ((safe_stricmp(p_statbuf->filename, "syslinux") == 0) &&
|
||||
// Special handling for ISOs that have a syslinux → isolinux symbolic link (e.g. Knoppix)
|
||||
(safe_stricmp(p_statbuf->rr.psz_symlink, "isolinux") == 0)) {
|
||||
|
@ -846,45 +864,58 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
|||
goto out;
|
||||
}
|
||||
} else {
|
||||
// TODO: Ideally, we'd want to create a text file that contains the target link
|
||||
print_extracted_file(psz_fullpath, file_length);
|
||||
print_extracted_file(psz_fullpath, safe_strlen(p_statbuf->rr.psz_symlink));
|
||||
uprintf(" Ignoring Rock Ridge symbolic link to '%s'", p_statbuf->rr.psz_symlink);
|
||||
}
|
||||
} else {
|
||||
uuprintf("Unexpected symlink length: %d", file_length);
|
||||
create_file = FALSE;
|
||||
}
|
||||
}
|
||||
file_handle = CreatePreallocatedFile(psz_sanpath, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, file_length);
|
||||
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
uprintf(" Unable to create file: %s", WindowsErrorString());
|
||||
if (((err == ERROR_ACCESS_DENIED) || (err == ERROR_INVALID_HANDLE)) &&
|
||||
(safe_strcmp(&psz_sanpath[3], autorun_name) == 0))
|
||||
uprintf(stupid_antivirus);
|
||||
else
|
||||
goto out;
|
||||
} else for (i = 0; file_length > 0; i++) {
|
||||
if (FormatStatus) goto out;
|
||||
memset(buf, 0, ISO_BLOCKSIZE);
|
||||
lsn = p_statbuf->lsn + (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;
|
||||
if (create_file) {
|
||||
file_handle = CreatePreallocatedFile(psz_sanpath, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, file_length);
|
||||
if (file_handle == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
uprintf(" Unable to create file: %s", WindowsErrorString());
|
||||
if (((err == ERROR_ACCESS_DENIED) || (err == ERROR_INVALID_HANDLE)) &&
|
||||
(safe_strcmp(&psz_sanpath[3], autorun_name) == 0))
|
||||
uprintf(stupid_antivirus);
|
||||
else
|
||||
goto out;
|
||||
} else if (is_symlink) {
|
||||
// Create a text file that contains the target link
|
||||
ISO_BLOCKING(r = WriteFileWithRetry(file_handle, p_statbuf->rr.psz_symlink,
|
||||
(DWORD)safe_strlen(p_statbuf->rr.psz_symlink), &wr_size, WRITE_RETRIES));
|
||||
if (!r) {
|
||||
uprintf(" Error writing file: %s", WindowsErrorString());
|
||||
goto out;
|
||||
}
|
||||
} else for (i = 0; file_length > 0; i++) {
|
||||
if (FormatStatus) goto out;
|
||||
memset(buf, 0, ISO_BLOCKSIZE);
|
||||
lsn = p_statbuf->lsn + (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(file_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;
|
||||
}
|
||||
file_length -= ISO_BLOCKSIZE;
|
||||
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
|
||||
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks +
|
||||
((fs_type != FS_NTFS) ? extra_blocks : 0));
|
||||
}
|
||||
buf_size = (DWORD)MIN(file_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;
|
||||
if (preserve_timestamps) {
|
||||
LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm));
|
||||
if (!SetFileTime(file_handle, ft, ft, ft))
|
||||
uprintf(" Could not set timestamp: %s", WindowsErrorString());
|
||||
}
|
||||
file_length -= ISO_BLOCKSIZE;
|
||||
if (nb_blocks++ % PROGRESS_THRESHOLD == 0)
|
||||
UpdateProgressWithInfo(OP_FILE_COPY, MSG_231, nb_blocks, total_blocks);
|
||||
}
|
||||
if (preserve_timestamps) {
|
||||
LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm));
|
||||
if (!SetFileTime(file_handle, ft, ft, ft))
|
||||
uprintf(" Could not set timestamp: %s", WindowsErrorString());
|
||||
}
|
||||
if (free_p_statbuf)
|
||||
iso9660_stat_free(p_statbuf);
|
||||
|
@ -1014,6 +1045,7 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
|
|||
uprintf("ISO analysis:");
|
||||
SendMessage(hMainDialog, UM_PROGRESS_INIT, PBS_MARQUEE, 0);
|
||||
total_blocks = 0;
|
||||
extra_blocks = 0;
|
||||
has_ldlinux_c32 = FALSE;
|
||||
// String array of all isolinux/syslinux locations
|
||||
StrArrayCreate(&config_path, 8);
|
||||
|
|
|
@ -1233,6 +1233,16 @@ static __inline BOOL MoveFileExU(const char* lpExistingFileName, const char* lpN
|
|||
return ret;
|
||||
}
|
||||
|
||||
static __inline BOOL CreateSymbolicLinkU(const char* lpSymlinkFileName, const char* lpTargetFileName, DWORD dwFlags)
|
||||
{
|
||||
wconvert(lpSymlinkFileName);
|
||||
wconvert(lpTargetFileName);
|
||||
BOOL ret = CreateSymbolicLinkW(wlpSymlinkFileName, wlpTargetFileName, dwFlags);
|
||||
wfree(lpTargetFileName);
|
||||
wfree(lpSymlinkFileName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The following expects PropertyBuffer to contain a single Unicode string
|
||||
static __inline BOOL SetupDiGetDeviceRegistryPropertyU(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData,
|
||||
DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize)
|
||||
|
|
10
src/rufus.rc
10
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.3.2086"
|
||||
CAPTION "Rufus 4.3.2087"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -392,8 +392,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,3,2086,0
|
||||
PRODUCTVERSION 4,3,2086,0
|
||||
FILEVERSION 4,3,2087,0
|
||||
PRODUCTVERSION 4,3,2087,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -411,13 +411,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.3.2086"
|
||||
VALUE "FileVersion", "4.3.2087"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.3.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.3.2086"
|
||||
VALUE "ProductVersion", "4.3.2087"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
Loading…
Reference in a new issue