/*
* This file provides the API functions wimlib_extract_image(),
- * wimlib_extract_image_from_pipe(), wimlib_extract_files(),
- * wimlib_extract_paths(), and wimlib_extract_pathlist(). Internally, all end
- * up calling do_wimlib_extract_paths() and extract_trees().
+ * wimlib_extract_image_from_pipe(), wimlib_extract_paths(), and
+ * wimlib_extract_pathlist(). Internally, all end up calling
+ * do_wimlib_extract_paths() and extract_trees().
*
* Although wimlib supports multiple extraction modes/backends (NTFS-3g, UNIX,
* Win32), this file does not itself have code to extract files or directories
#define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000
#define WIMLIB_EXTRACT_FLAG_FROM_PIPE 0x40000000
-#define WIMLIB_EXTRACT_FLAG_FILEMODE 0x20000000
-#define WIMLIB_EXTRACT_FLAG_IMAGEMODE 0x10000000
+#define WIMLIB_EXTRACT_FLAG_IMAGEMODE 0x20000000
/* Keep in sync with wimlib.h */
#define WIMLIB_EXTRACT_MASK_PUBLIC \
}
} else {
ret = ctx->ops->extract_unnamed_stream(
- file_spec, lte, ctx);
+ file_spec, lte, ctx,
+ dentry);
if (ret)
goto error;
}
if (ctx->supported_features.security_descriptors &&
inode->i_security_id != -1)
{
- const struct wim_security_data *sd;
+ struct wim_security_data *sd;
const u8 *desc;
size_t desc_size;
- sd = wim_const_security_data(ctx->wim);
+ sd = wim_get_current_security_data(ctx->wim);
desc = sd->descriptors[inode->i_security_id];
desc_size = sd->sizes[inode->i_security_id];
{
tchar *name;
int raw_fd;
+ int open_flags;
retry:
name = ttempnam(NULL, T("wimlib"));
return WIMLIB_ERR_NOMEM;
}
- raw_fd = topen(name, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600);
+ open_flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
+#ifdef __WIN32__
+ open_flags |= _O_SHORT_LIVED;
+#endif
+ raw_fd = topen(name, open_flags, 0600);
if (raw_fd < 0) {
if (errno == EEXIST) {
}
static int
-begin_extract_stream_to_tmpfile(struct wim_lookup_table_entry *lte,
- bool is_partial_res,
- void *_ctx)
+begin_extract_stream(struct wim_lookup_table_entry *lte,
+ u32 flags, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
int ret;
- if (!need_tmpfile_to_extract(lte, is_partial_res)) {
+ if (flags & BEGIN_STREAM_FLAG_WHOLE_STREAM) {
+ DEBUG("Whole stream (size=%"PRIu64") will be read into memory",
+ lte->size);
+ ctx->cur_stream = lte;
+ filedes_invalidate(&ctx->tmpfile_fd);
+ return 0;
+ }
+
+ if (!need_tmpfile_to_extract(lte,
+ (flags & BEGIN_STREAM_FLAG_PARTIAL_RESOURCE)))
+ {
DEBUG("Temporary file not needed "
"for stream (size=%"PRIu64")", lte->size);
ret = extract_stream_instances(lte, lte, ctx);
}
static int
-end_extract_stream_to_tmpfile(struct wim_lookup_table_entry *lte,
- int status, void *_ctx)
+extract_chunk(const void *chunk, size_t size, void *_ctx)
+{
+ struct apply_ctx *ctx = _ctx;
+ int ret;
+
+ if (filedes_valid(&ctx->tmpfile_fd)) {
+ ret = full_write(&ctx->tmpfile_fd, chunk, size);
+ if (ret)
+ ERROR_WITH_ERRNO("Error writing to file descriptor");
+ } else {
+ struct wim_lookup_table_entry lte_override;
+
+ memcpy(<e_override, ctx->cur_stream,
+ sizeof(struct wim_lookup_table_entry));
+
+ lte_override.resource_location = RESOURCE_IN_ATTACHED_BUFFER;
+ lte_override.size = size;
+ lte_override.attached_buffer = (void *)chunk;
+
+ ret = extract_stream_instances(ctx->cur_stream, <e_override, ctx);
+ }
+ return ret;
+}
+
+static int
+end_extract_stream(struct wim_lookup_table_entry *lte,
+ int status, void *_ctx)
{
struct apply_ctx *ctx = _ctx;
struct wim_lookup_table_entry lte_override;
int ret;
int errno_save = errno;
+ if (!filedes_valid(&ctx->tmpfile_fd))
+ return status;
+
ret = filedes_close(&ctx->tmpfile_fd);
if (status) {
extract_stream_list(struct apply_ctx *ctx)
{
struct read_stream_list_callbacks cbs = {
- .begin_stream = begin_extract_stream_to_tmpfile,
+ .begin_stream = begin_extract_stream,
.begin_stream_ctx = ctx,
- .consume_chunk = extract_chunk_to_fd,
- .consume_chunk_ctx = &ctx->tmpfile_fd,
- .end_stream = end_extract_stream_to_tmpfile,
+ .consume_chunk = extract_chunk,
+ .consume_chunk_ctx = ctx,
+ .end_stream = end_extract_stream,
.end_stream_ctx = ctx,
};
return read_stream_list(&ctx->stream_list,
pwm_flags = PWM_ALLOW_WIM_HDR;
if ((ctx->extract_flags & WIMLIB_EXTRACT_FLAG_RESUME))
pwm_flags |= PWM_SILENT_EOF;
- memcpy(ctx->progress.extract.guid, ctx->wim->hdr.guid, WIM_GID_LEN);
+ memcpy(ctx->progress.extract.guid, ctx->wim->hdr.guid, WIM_GUID_LEN);
ctx->progress.extract.part_number = ctx->wim->hdr.part_number;
ctx->progress.extract.total_parts = ctx->wim->hdr.total_parts;
if (ctx->progress_func)
if (part_number != ctx->progress.extract.part_number ||
total_parts != ctx->progress.extract.total_parts ||
memcmp(pwm_hdr.guid, ctx->progress.extract.guid,
- WIM_GID_LEN))
+ WIM_GUID_LEN))
{
ctx->progress.extract.part_number = part_number;
ctx->progress.extract.total_parts = total_parts;
memcpy(ctx->progress.extract.guid,
- pwm_hdr.guid, WIM_GID_LEN);
+ pwm_hdr.guid, WIM_GUID_LEN);
if (ctx->progress_func) {
ctx->progress_func(
WIMLIB_PROGRESS_MSG_EXTRACT_SPWM_PART_BEGIN,
}
if (file_name_valid(dentry->file_name, dentry->file_name_nbytes / 2, false)) {
-#if TCHAR_IS_UTF16LE
- dentry->extraction_name = dentry->file_name;
- dentry->extraction_name_nchars = dentry->file_name_nbytes / 2;
- return 0;
-#else
- return utf16le_to_tstr(dentry->file_name,
+ ret = utf16le_get_tstr(dentry->file_name,
dentry->file_name_nbytes,
- &dentry->extraction_name,
+ (const tchar **)&dentry->extraction_name,
&dentry->extraction_name_nchars);
-#endif
+ dentry->extraction_name_nchars /= sizeof(tchar);
+ return ret;
} else {
if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_REPLACE_INVALID_FILENAMES)
{
memcpy(utf16_name_copy, dentry->file_name, dentry->file_name_nbytes);
file_name_valid(utf16_name_copy, dentry->file_name_nbytes / 2, true);
- tchar *tchar_name;
+ const tchar *tchar_name;
size_t tchar_nchars;
- #if TCHAR_IS_UTF16LE
- tchar_name = utf16_name_copy;
- tchar_nchars = dentry->file_name_nbytes / 2;
- #else
- ret = utf16le_to_tstr(utf16_name_copy,
- dentry->file_name_nbytes,
- &tchar_name, &tchar_nchars);
+
+ ret = utf16le_get_tstr(utf16_name_copy,
+ dentry->file_name_nbytes,
+ &tchar_name, &tchar_nchars);
if (ret)
return ret;
- #endif
+
+ tchar_nchars /= sizeof(tchar);
+
size_t fixed_name_num_chars = tchar_nchars;
tchar fixed_name[tchar_nchars + 50];
fixed_name_num_chars += tsprintf(fixed_name + tchar_nchars,
T(" (invalid filename #%lu)"),
++ctx->invalid_sequence);
- #if !TCHAR_IS_UTF16LE
- FREE(tchar_name);
- #endif
+
+ utf16le_put_tstr(tchar_name);
+
dentry->extraction_name = memdup(fixed_name,
2 * fixed_name_num_chars + 2);
if (!dentry->extraction_name)
ctx.progress.extract.target = target;
}
- if (extract_flags & WIMLIB_EXTRACT_FLAG_FILEMODE) {
- /* Called from wimlib_extract_files(). There should be only 1
- * tree, and directory structure should not be preserved. */
- wimlib_assert(num_trees == 1);
- wimlib_assert(extract_flags &
- WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE);
- ret = calculate_dentry_full_path(trees[0]);
- if (ret)
- return ret;
- ctx.progress.extract.extract_root_wim_source_path = trees[0]->_full_path;
- ctx.target_dentry = trees[0];
- } else {
- ctx.progress.extract.extract_root_wim_source_path = T("");
- ctx.target_dentry = wim_root_dentry(wim);
- }
+ ctx.target_dentry = wim_get_current_root_dentry(wim);
/* Note: ctx.target_dentry represents the dentry that gets extracted to
* @target. There may be none, in which case it gets set to the image
* root and never matches any of the dentries actually being extracted.
goto out_destroy_stream_list;
}
ctx.realtarget_nchars = tstrlen(ctx.realtarget);
+ #ifdef __WIN32__
+ /* Strip trailing slashes. If we don't do this, we may create a
+ * path with multiple consecutive backslashes, which for some
+ * reason causes Windows to report that the file cannot be found.
+ */
+ while (ctx.realtarget_nchars >= 2
+ && ctx.realtarget[ctx.realtarget_nchars - 1] == L'\\'
+ && ctx.realtarget[ctx.realtarget_nchars - 2] != L':')
+ {
+ ctx.realtarget[--ctx.realtarget_nchars] = L'\0';
+ }
+ #endif
}
if (progress_func) {
#ifndef WITH_NTFS_3G
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
ERROR("wimlib was compiled without support for NTFS-3g, so\n"
- " it cannot apply a WIM image directly to a NTFS volume.");
+ " it cannot apply a WIM image directly to an NTFS volume.");
return WIMLIB_ERR_UNSUPPORTED;
}
#endif
return ret;
if ((extract_flags & (WIMLIB_EXTRACT_FLAG_NTFS |
- WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE |
- WIMLIB_EXTRACT_FLAG_FILEMODE)) ==
+ WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE)) ==
(WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE))
{
ret = mkdir_if_needed(target);
const tchar *target, int extract_flags,
wimlib_progress_func_t progress_func)
{
- const tchar *path = T("");
+ const tchar *path = WIMLIB_WIM_ROOT_PATH;
extract_flags |= WIMLIB_EXTRACT_FLAG_IMAGEMODE;
return do_wimlib_extract_paths(wim, image, target, &path, 1,
extract_flags, progress_func);
* Extraction API *
****************************************************************************/
-/* Note: new code should use wimlib_extract_paths() instead of
- * wimlib_extract_files() if possible. */
-WIMLIBAPI int
-wimlib_extract_files(WIMStruct *wim, int image,
- const struct wimlib_extract_command *cmds, size_t num_cmds,
- int default_extract_flags,
- wimlib_progress_func_t progress_func)
-{
- int all_flags = 0;
- int link_flags;
- int ret;
-
- if (num_cmds == 0)
- return 0;
-
- default_extract_flags |= WIMLIB_EXTRACT_FLAG_NO_PRESERVE_DIR_STRUCTURE;
-
- for (size_t i = 0; i < num_cmds; i++) {
- int cmd_flags = (cmds[i].extract_flags |
- default_extract_flags);
-
- if (cmd_flags & ~WIMLIB_EXTRACT_MASK_PUBLIC)
- return WIMLIB_ERR_INVALID_PARAM;
-
- int cmd_link_flags = (cmd_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK |
- WIMLIB_EXTRACT_FLAG_HARDLINK));
- if (i == 0) {
- link_flags = cmd_link_flags;
- } else {
- if (cmd_link_flags != link_flags) {
- ERROR("The same symlink or hardlink extraction mode "
- "must be set on all extraction commands!");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- }
- all_flags |= cmd_flags;
- }
- if (all_flags & WIMLIB_EXTRACT_FLAG_GLOB_PATHS) {
- ERROR("Glob paths not supported for wimlib_extract_files(). "
- "Use wimlib_extract_paths() instead.");
- return WIMLIB_ERR_INVALID_PARAM;
- }
-
- for (size_t i = 0; i < num_cmds; i++) {
- int extract_flags = (cmds[i].extract_flags |
- default_extract_flags);
- const tchar *target = cmds[i].fs_dest_path;
- const tchar *wim_source_path = cmds[i].wim_source_path;
-
- ret = do_wimlib_extract_paths(wim, image, target,
- &wim_source_path, 1,
- extract_flags | WIMLIB_EXTRACT_FLAG_FILEMODE,
- progress_func);
- if (ret)
- break;
- }
-
- clear_lte_extracted_file(wim, all_flags);
- return ret;
-}
-
WIMLIBAPI int
wimlib_extract_paths(WIMStruct *wim, int image, const tchar *target,
const tchar * const *paths, size_t num_paths,