mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-09 04:21:56 -04:00
[vhd] add libcdio integration to wimlib
* Allows working with WIMs without mounting the ISO by referencing something like "C:\Downloads\Windows.iso|sources/install.wim".
This commit is contained in:
parent
c288f2fe57
commit
96996ae1ee
8 changed files with 312 additions and 25 deletions
|
@ -264,7 +264,7 @@
|
|||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4018;4146;4267;4244;4334;4789;4996;6201;6239;6246;6255;6262;6297;6326;28252;28253</DisableSpecificWarnings>
|
||||
|
@ -286,7 +286,7 @@
|
|||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalOptions>/std:clatest</AdditionalOptions>
|
||||
|
@ -305,7 +305,7 @@
|
|||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalOptions>/std:clatest</AdditionalOptions>
|
||||
|
@ -321,7 +321,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4018;4146;4267;4244;4334;4789;4996;6201;6239;6246;6255;6262;6297;6326;28252;28253</DisableSpecificWarnings>
|
||||
|
@ -341,7 +341,7 @@
|
|||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalOptions>/std:clatest</AdditionalOptions>
|
||||
|
@ -358,7 +358,7 @@
|
|||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalOptions>/std:clatest</AdditionalOptions>
|
||||
|
@ -372,7 +372,7 @@
|
|||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4018;4146;4267;4244;4334;4789;4996;6201;6239;6246;6255;6262;6297;6326;28252;28253</DisableSpecificWarnings>
|
||||
|
@ -391,7 +391,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\src;..\src\wimlib;..\src\msvc-missing;..\src\libcdio;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<DisableSpecificWarnings>4018;4146;4267;4244;4334;4789;4996;6201;6239;6246;6255;6262;6297;6326;28252;28253</DisableSpecificWarnings>
|
||||
|
|
21
src/rufus.c
21
src/rufus.c
|
@ -3831,9 +3831,28 @@ extern int TestHashes(void);
|
|||
&& (msg.wParam == 'T')) {
|
||||
int r;
|
||||
WIMStruct* wim;
|
||||
r = wimlib_open_wim(L"C:\\tmp\\boot.wim", WIMLIB_OPEN_FLAG_CHECK_INTEGRITY, &wim);
|
||||
r = wimlib_open_wim(L"D:\\Incoming\\Win11_24H2_EnglishInternational_x64.iso|sources/boot.wim", WIMLIB_OPEN_FLAG_CHECK_INTEGRITY, &wim);
|
||||
// r = wimlib_open_wim(L"C:\\tmp\\test.iso|sources/boot.wim", WIMLIB_OPEN_FLAG_CHECK_INTEGRITY, &wim);
|
||||
// r = wimlib_open_wim(L"C:\\tmp\\boot.wim", WIMLIB_OPEN_FLAG_CHECK_INTEGRITY, &wim);
|
||||
if (r == 0) {
|
||||
int image;
|
||||
wchar_t* xml;
|
||||
size_t xml_size;
|
||||
wimlib_print_header(wim);
|
||||
if (wimlib_get_xml_data(wim, (void**) & xml, &xml_size) == 0) {
|
||||
xml[(xml_size / sizeof(wchar_t)) - 1] = L'\0';
|
||||
wuprintf(L"%s", xml);
|
||||
free(xml);
|
||||
}
|
||||
image = wimlib_resolve_image(wim, L"1");
|
||||
uprintf("image = %d", image);
|
||||
const wchar_t* fn = L"Windows/win.ini";
|
||||
r = wimlib_extract_paths(wim, image, L"C:\\tmp\\wim", &fn, 1, WIMLIB_EXTRACT_FLAG_NORPFIX |
|
||||
WIMLIB_EXTRACT_FLAG_GLOB_PATHS | WIMLIB_EXTRACT_FLAG_STRICT_GLOB | WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE);
|
||||
if (r == 0)
|
||||
uprintf("Successfully extracted '%S'", fn);
|
||||
else
|
||||
uprintf("Failed to extract '%S': %d", fn, r);
|
||||
wimlib_free(wim);
|
||||
} else {
|
||||
uprintf("Failed to open WIM: %d", r);
|
||||
|
|
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.8.2237"
|
||||
CAPTION "Rufus 4.8.2238"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -407,8 +407,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,8,2237,0
|
||||
PRODUCTVERSION 4,8,2237,0
|
||||
FILEVERSION 4,8,2238,0
|
||||
PRODUCTVERSION 4,8,2238,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -426,13 +426,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.8.2237"
|
||||
VALUE "FileVersion", "4.8.2238"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2025 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.8.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.8.2237"
|
||||
VALUE "ProductVersion", "4.8.2238"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -8,4 +8,4 @@ libwim_a_SOURCES = avl_tree.c blob_table.c compress.c compress_common.c compress
|
|||
sha1.c solid.c split.c tagged_items.c textfile.c threads.c timestamp.c update_image.c \
|
||||
util.c wim.c wimboot.c win32_apply.c win32_capture.c win32_common.c win32_replacements.c \
|
||||
win32_vss.c write.c xml.c xmlproc.c xml_windows.c xpress_compress.c xpress_decompress.c
|
||||
libwim_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -DHAVE_CONFIG_H -D_RUFUS -D__SSE2__ -D_POSIX -D_POSIX_THREAD_SAFE_FUNCTIONS -DUNICODE -D_UNICODE -D__MINGW_USE_VC2005_COMPAT -Wno-undef -Wno-strict-aliasing -Wno-shadow -Wno-incompatible-pointer-types -Wno-sequence-point
|
||||
libwim_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -I$(srcdir)/../libcdio -DHAVE_CONFIG_H -D_RUFUS -D__SSE2__ -D_POSIX -D_POSIX_THREAD_SAFE_FUNCTIONS -DUNICODE -D_UNICODE -D__MINGW_USE_VC2005_COMPAT -Wno-undef -Wno-strict-aliasing -Wno-shadow -Wno-incompatible-pointer-types -Wno-sequence-point
|
||||
|
|
|
@ -291,7 +291,7 @@ libwim_a_SOURCES = avl_tree.c blob_table.c compress.c compress_common.c compress
|
|||
util.c wim.c wimboot.c win32_apply.c win32_capture.c win32_common.c win32_replacements.c \
|
||||
win32_vss.c write.c xml.c xmlproc.c xml_windows.c xpress_compress.c xpress_decompress.c
|
||||
|
||||
libwim_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -DHAVE_CONFIG_H -D_RUFUS -D__SSE2__ -D_POSIX -D_POSIX_THREAD_SAFE_FUNCTIONS -DUNICODE -D_UNICODE -D__MINGW_USE_VC2005_COMPAT -Wno-undef -Wno-strict-aliasing -Wno-shadow -Wno-incompatible-pointer-types -Wno-sequence-point
|
||||
libwim_a_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/.. -I$(srcdir)/../libcdio -DHAVE_CONFIG_H -D_RUFUS -D__SSE2__ -D_POSIX -D_POSIX_THREAD_SAFE_FUNCTIONS -DUNICODE -D_UNICODE -D__MINGW_USE_VC2005_COMPAT -Wno-undef -Wno-strict-aliasing -Wno-shadow -Wno-incompatible-pointer-types -Wno-sequence-point
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2013 Eric Biggers
|
||||
* Copyright (C) 2025 Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
|
@ -38,6 +39,130 @@
|
|||
# define pwrite win32_pwrite
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LIBCDIO
|
||||
static int
|
||||
udf_pread(struct filedes* fd, void* buf, size_t count, off_t offset)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t partial_size;
|
||||
uint64_t file_length;
|
||||
char _buf[UDF_BLOCKSIZE];
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
if (!udf_setpos(fd->p_udf_file, (offset / UDF_BLOCKSIZE) * UDF_BLOCKSIZE)) {
|
||||
errno = ERANGE;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
fd->offset = (offset / UDF_BLOCKSIZE) * UDF_BLOCKSIZE;
|
||||
|
||||
file_length = udf_get_file_length(fd->p_udf_file);
|
||||
if (offset + count > file_length)
|
||||
count = file_length - offset;
|
||||
|
||||
if (offset % UDF_BLOCKSIZE) {
|
||||
partial_size = min(UDF_BLOCKSIZE - offset % UDF_BLOCKSIZE, count);
|
||||
ret = udf_read_block(fd->p_udf_file, _buf, 1);
|
||||
if (unlikely(ret <= 0)) {
|
||||
errno = EINVAL;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
memcpy(buf, &_buf[offset % UDF_BLOCKSIZE], partial_size);
|
||||
buf = _PTR(buf + partial_size);
|
||||
fd->offset += partial_size;
|
||||
count -= partial_size;
|
||||
}
|
||||
|
||||
while (count >= UDF_BLOCKSIZE) {
|
||||
ret = udf_read_block(fd->p_udf_file, buf, count / UDF_BLOCKSIZE);
|
||||
if (unlikely(ret <= 0)) {
|
||||
errno = EINVAL;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
buf = _PTR(buf + ret);
|
||||
fd->offset += ret;
|
||||
count -= ret;
|
||||
}
|
||||
|
||||
partial_size = count % UDF_BLOCKSIZE;
|
||||
if (partial_size) {
|
||||
ret = udf_read_block(fd->p_udf_file, _buf, 1);
|
||||
if (unlikely(ret <= 0)) {
|
||||
errno = EINVAL;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
memcpy(buf, _buf, partial_size);
|
||||
buf = _PTR(buf + partial_size);
|
||||
fd->offset += partial_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iso_pread(struct filedes* fd, void* buf, size_t count, off_t offset)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t partial_size;
|
||||
char _buf[ISO_BLOCKSIZE];
|
||||
lsn_t lsn_offset = fd->p_iso_file->lsn + offset / ISO_BLOCKSIZE;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
if (offset >= fd->p_iso_file->total_size) {
|
||||
errno = ERANGE;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
|
||||
if (offset + count > fd->p_iso_file->total_size)
|
||||
count = fd->p_iso_file->total_size - offset;
|
||||
|
||||
if (offset % ISO_BLOCKSIZE) {
|
||||
partial_size = min(ISO_BLOCKSIZE - offset % ISO_BLOCKSIZE, count);
|
||||
ret = iso9660_iso_seek_read(fd->p_iso, _buf, lsn_offset, 1);
|
||||
if (unlikely(ret <= 0)) {
|
||||
errno = EINVAL;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
lsn_offset += 1;
|
||||
memcpy(buf, &_buf[offset % ISO_BLOCKSIZE], partial_size);
|
||||
buf = _PTR(buf + partial_size);
|
||||
fd->offset += partial_size;
|
||||
count -= partial_size;
|
||||
}
|
||||
|
||||
while (count >= ISO_BLOCKSIZE) {
|
||||
ret = iso9660_iso_seek_read(fd->p_iso, _buf,
|
||||
lsn_offset % ISO_BLOCKSIZE, 1);
|
||||
ret = iso9660_iso_seek_read(fd->p_iso, buf, lsn_offset, count / ISO_BLOCKSIZE);
|
||||
if (unlikely(ret <= 0)) {
|
||||
errno = EINVAL;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
lsn_offset += ret / ISO_BLOCKSIZE;
|
||||
buf = _PTR(buf + ret);
|
||||
fd->offset += ret;
|
||||
count -= ret;
|
||||
}
|
||||
|
||||
partial_size = count % ISO_BLOCKSIZE;
|
||||
if (partial_size) {
|
||||
ret = iso9660_iso_seek_read(fd->p_iso, _buf, lsn_offset, 1);
|
||||
if (unlikely(ret <= 0)) {
|
||||
errno = EINVAL;
|
||||
return WIMLIB_ERR_READ;
|
||||
}
|
||||
memcpy(buf, _buf, partial_size);
|
||||
buf = _PTR(buf + partial_size);
|
||||
fd->offset += partial_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wrapper around read() that checks for errors and keeps retrying until all
|
||||
* requested bytes have been read or until end-of file has occurred.
|
||||
|
@ -50,6 +175,13 @@
|
|||
int
|
||||
full_read(struct filedes *fd, void *buf, size_t count)
|
||||
{
|
||||
#ifdef WITH_LIBCDIO
|
||||
if (fd->is_udf)
|
||||
return udf_pread(fd, buf, count, 0);
|
||||
else if (fd->is_iso)
|
||||
return iso_pread(fd, buf, count, 0);
|
||||
#endif
|
||||
|
||||
while (count) {
|
||||
ssize_t ret = read(fd->fd, buf, count);
|
||||
if (unlikely(ret <= 0)) {
|
||||
|
@ -117,6 +249,13 @@ full_pread(struct filedes *fd, void *buf, size_t count, off_t offset)
|
|||
if (fd->is_pipe)
|
||||
goto is_pipe;
|
||||
|
||||
#ifdef WITH_LIBCDIO
|
||||
if (fd->is_udf)
|
||||
return udf_pread(fd, buf, count, offset);
|
||||
else if (fd->is_iso)
|
||||
return iso_pread(fd, buf, count, offset);
|
||||
#endif
|
||||
|
||||
while (count) {
|
||||
ssize_t ret = pread(fd->fd, buf, count, offset);
|
||||
if (unlikely(ret <= 0)) {
|
||||
|
@ -195,6 +334,13 @@ full_pwrite(struct filedes *fd, const void *buf, size_t count, off_t offset)
|
|||
|
||||
off_t filedes_seek(struct filedes *fd, off_t offset)
|
||||
{
|
||||
#ifdef WITH_LIBCDIO
|
||||
/* No arbitrary seek for ISO files */
|
||||
if (fd->is_udf || fd->is_iso) {
|
||||
errno = ENFILE;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (fd->is_pipe) {
|
||||
errno = ESPIPE;
|
||||
return -1;
|
||||
|
@ -209,5 +355,10 @@ off_t filedes_seek(struct filedes *fd, off_t offset)
|
|||
|
||||
bool filedes_is_seekable(struct filedes *fd)
|
||||
{
|
||||
#ifdef WITH_LIBCDIO
|
||||
/* No arbitrary seek for ISO files */
|
||||
if (fd->is_udf || fd->is_iso)
|
||||
return false;
|
||||
#endif
|
||||
return !fd->is_pipe && lseek(fd->fd, 0, SEEK_CUR) != -1;
|
||||
}
|
||||
|
|
103
src/wimlib/wim.c
103
src/wimlib/wim.c
|
@ -4,6 +4,7 @@
|
|||
|
||||
/*
|
||||
* Copyright 2012-2023 Eric Biggers
|
||||
* Copyright 2025 Pete Batard <pete@akeo.ie>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Lesser General Public License as published by the Free
|
||||
|
@ -616,11 +617,77 @@ wimlib_register_progress_function(WIMStruct *wim,
|
|||
wim->progctx = progctx;
|
||||
}
|
||||
|
||||
#ifdef WITH_LIBCDIO
|
||||
static int
|
||||
open_iso_wim_file(const tchar* filename, struct filedes* fd_ret)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t n;
|
||||
char *iso_filename, *iso_path = NULL;
|
||||
udf_dirent_t *p_udf_root;
|
||||
|
||||
/* If the wim path contains a pipe separator, look it up inside an ISO */
|
||||
if (tstr_to_utf8(filename, (tstrlen(filename) + 1) * sizeof(tchar), &iso_path, &n))
|
||||
return WIMLIB_ERR_NOMEM;
|
||||
iso_filename = strchr(iso_path, '|');
|
||||
if (iso_filename == NULL) {
|
||||
ret = WIMLIB_ERR_NO_FILENAME;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*iso_filename++ = '\0';
|
||||
filedes_init(fd_ret, 0);
|
||||
|
||||
/* Try to open as UDF image */
|
||||
fd_ret->p_udf = udf_open(iso_path);
|
||||
if (!fd_ret->p_udf)
|
||||
goto try_iso;
|
||||
p_udf_root = udf_get_root(fd_ret->p_udf, true, 0);
|
||||
if (!p_udf_root) {
|
||||
ret = WIMLIB_ERR_OPEN;
|
||||
goto out;
|
||||
}
|
||||
fd_ret->p_udf_file = udf_fopen(p_udf_root, iso_filename);
|
||||
udf_dirent_free(p_udf_root);
|
||||
if (!fd_ret->p_udf_file) {
|
||||
ret = WIMLIB_ERR_OPEN;
|
||||
goto out;
|
||||
}
|
||||
fd_ret->is_udf = 1;
|
||||
goto out;
|
||||
|
||||
try_iso:
|
||||
/* Try to open as ISO9660 image */
|
||||
fd_ret->p_iso = iso9660_open_ext(iso_path, ISO_EXTENSION_ALL);
|
||||
if (!fd_ret->p_iso) {
|
||||
ret = WIMLIB_ERR_OPEN;
|
||||
goto out;
|
||||
}
|
||||
fd_ret->p_iso_file = iso9660_ifs_stat_translate(fd_ret->p_iso, iso_filename);
|
||||
if (!fd_ret->p_iso_file) {
|
||||
ret = WIMLIB_ERR_OPEN;
|
||||
goto out;
|
||||
}
|
||||
fd_ret->is_iso = 1;
|
||||
|
||||
out:
|
||||
FREE(iso_path);
|
||||
/* Because we use an union, make sure fd is cleared on error */
|
||||
if (ret)
|
||||
fd_ret->fd = 0;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
open_wim_file(const tchar *filename, struct filedes *fd_ret)
|
||||
{
|
||||
int raw_fd;
|
||||
|
||||
#ifdef WITH_LIBCDIO
|
||||
if (open_iso_wim_file(filename, fd_ret) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
raw_fd = topen(filename, O_RDONLY | O_BINARY);
|
||||
if (raw_fd < 0) {
|
||||
ERROR_WITH_ERRNO("Can't open \"%"TS"\" read-only", filename);
|
||||
|
@ -653,6 +720,16 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags)
|
|||
return ret;
|
||||
|
||||
/* The file size is needed for enforcing some limits later. */
|
||||
#ifdef WITH_LIBCDIO
|
||||
if ((wim->in_fd.is_udf | wim->in_fd.is_iso) &&
|
||||
(open_flags & WIMLIB_OPEN_FLAG_WRITE_ACCESS))
|
||||
return WIMLIB_ERR_WIM_IS_READONLY;
|
||||
if (wim->in_fd.is_udf)
|
||||
wim->file_size = udf_get_file_length(wim->in_fd.p_udf_file);
|
||||
else if (wim->in_fd.is_iso)
|
||||
wim->file_size = wim->in_fd.p_iso_file->total_size;
|
||||
else
|
||||
#endif
|
||||
if (fstat(wim->in_fd.fd, &stbuf) == 0)
|
||||
wim->file_size = stbuf.st_size;
|
||||
|
||||
|
@ -668,6 +745,12 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags)
|
|||
* Warning: in Windows native builds, realpath() calls the
|
||||
* replacement function in win32_replacements.c.
|
||||
*/
|
||||
#ifdef WITH_LIBCDIO
|
||||
/* No overwriting for libcdio, so simply duplicate */
|
||||
if (tstrchr(wimfile, T('|')))
|
||||
wim->filename = tstrdup(wimfile);
|
||||
else
|
||||
#endif
|
||||
wim->filename = realpath(wimfile, NULL);
|
||||
if (!wim->filename) {
|
||||
ERROR_WITH_ERRNO("Failed to get full path to file "
|
||||
|
@ -900,10 +983,22 @@ wim_decrement_refcnt(WIMStruct *wim)
|
|||
wimlib_assert(wim->refcnt > 0);
|
||||
if (--wim->refcnt != 0)
|
||||
return;
|
||||
if (filedes_valid(&wim->in_fd))
|
||||
filedes_close(&wim->in_fd);
|
||||
if (filedes_valid(&wim->out_fd))
|
||||
filedes_close(&wim->out_fd);
|
||||
#ifdef WITH_LIBCDIO
|
||||
if (wim->in_fd.is_udf) {
|
||||
udf_dirent_free(wim->in_fd.p_udf_file);
|
||||
udf_close(wim->in_fd.p_udf);
|
||||
} else if (wim->in_fd.is_iso) {
|
||||
iso9660_stat_free(wim->in_fd.p_iso_file);
|
||||
iso9660_close(wim->in_fd.p_iso);
|
||||
} else {
|
||||
#endif
|
||||
if (filedes_valid(&wim->in_fd))
|
||||
filedes_close(&wim->in_fd);
|
||||
if (filedes_valid(&wim->out_fd))
|
||||
filedes_close(&wim->out_fd);
|
||||
#ifdef WITH_LIBCDIO
|
||||
}
|
||||
#endif
|
||||
wimlib_free_decompressor(wim->decompressor);
|
||||
xml_free_info_struct(wim->xml_info);
|
||||
FREE(wim->filename);
|
||||
|
|
|
@ -6,12 +6,35 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef WITH_LIBCDIO
|
||||
# define DO_NOT_WANT_COMPATIBILITY
|
||||
# undef PRAGMA_BEGIN_PACKED
|
||||
# undef PRAGMA_END_PACKED
|
||||
# include <cdio/udf.h>
|
||||
# include <cdio/iso9660.h>
|
||||
#endif
|
||||
|
||||
/* Wrapper around a file descriptor that keeps track of offset (including in
|
||||
* pipes, which don't support lseek()) and a cached flag that tells whether the
|
||||
* file descriptor is a pipe or not. */
|
||||
* pipes, which don't support lseek()), allows the handling of files that are
|
||||
* contained within ISO images, and a cached flag that tells whether the file
|
||||
* descriptor is a pipe or not. */
|
||||
struct filedes {
|
||||
int fd;
|
||||
union {
|
||||
int fd;
|
||||
#ifdef WITH_LIBCDIO
|
||||
iso9660_t* p_iso;
|
||||
udf_t* p_udf;
|
||||
#endif
|
||||
};
|
||||
unsigned int is_pipe : 1;
|
||||
#ifdef WITH_LIBCDIO
|
||||
unsigned int is_iso : 1;
|
||||
unsigned int is_udf : 1;
|
||||
union {
|
||||
udf_dirent_t* p_udf_file;
|
||||
iso9660_stat_t* p_iso_file;
|
||||
};
|
||||
#endif
|
||||
off_t offset;
|
||||
};
|
||||
|
||||
|
@ -39,9 +62,8 @@ filedes_is_seekable(struct filedes *fd);
|
|||
|
||||
static inline void filedes_init(struct filedes *fd, int raw_fd)
|
||||
{
|
||||
memset(fd, 0, sizeof(*fd));
|
||||
fd->fd = raw_fd;
|
||||
fd->offset = 0;
|
||||
fd->is_pipe = 0;
|
||||
}
|
||||
|
||||
static inline void filedes_invalidate(struct filedes *fd)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue