#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
-#ifdef WITH_NTFS_3G
-# include "wimlib/ntfs_3g.h" /* for do_ntfs_umount() */
-#endif
#include "wimlib/paths.h"
#include "wimlib/progress.h"
-#include "wimlib/xml.h"
+#include "wimlib/xml_windows.h"
/* Saved specification of a "primitive" update operation that was performed. */
struct update_primitive {
/* Free orphaned dentry trees */
while (!list_empty(&j->orphans)) {
orphan = list_first_entry(&j->orphans,
- struct wim_dentry, tmp_list);
- list_del(&orphan->tmp_list);
+ struct wim_dentry, d_tmp_list);
+ list_del(&orphan->d_tmp_list);
free_dentry_tree(orphan, j->blob_table);
}
do_unlink(subject, parent, root_p);
/* @subject is now unlinked. Add it to orphans. */
- list_add(&subject->tmp_list, orphans);
- subject->is_orphan = 1;
+ list_add(&subject->d_tmp_list, orphans);
+ subject->d_is_orphan = 1;
}
/* Undo an unlink operation. */
do_link(subject, parent, root_p);
/* @subject is no longer unlinked. Delete it from orphans. */
- list_del(&subject->tmp_list);
- subject->is_orphan = 0;
+ list_del(&subject->d_tmp_list);
+ subject->d_is_orphan = 0;
}
/* Rollback a name change operation. */
break;
case CHANGE_FILE_NAME:
rollback_name_change(prim->name.old_name,
- &prim->name.subject->file_name,
- &prim->name.subject->file_name_nbytes);
+ &prim->name.subject->d_name,
+ &prim->name.subject->d_name_nbytes);
break;
case CHANGE_SHORT_NAME:
rollback_name_change(prim->name.old_name,
- &prim->name.subject->short_name,
- &prim->name.subject->short_name_nbytes);
+ &prim->name.subject->d_short_name,
+ &prim->name.subject->d_short_name_nbytes);
break;
}
}
do_link(subject, parent, j->root_p);
- if (subject->is_orphan) {
- list_del(&subject->tmp_list);
- subject->is_orphan = 0;
+ if (subject->d_is_orphan) {
+ list_del(&subject->d_tmp_list);
+ subject->d_is_orphan = 0;
}
return 0;
}
do_unlink(subject, parent, j->root_p);
- list_add(&subject->tmp_list, &j->orphans);
- subject->is_orphan = 1;
+ list_add(&subject->d_tmp_list, &j->orphans);
+ subject->d_is_orphan = 1;
return 0;
}
prim.type = CHANGE_FILE_NAME;
prim.name.subject = dentry;
- prim.name.old_name = dentry->file_name;
+ prim.name.old_name = dentry->d_name;
ret = record_update_primitive(j, prim);
if (ret) {
FREE(new_name);
return ret;
}
- dentry->file_name = new_name;
- dentry->file_name_nbytes = new_name_nbytes;
+ dentry->d_name = new_name;
+ dentry->d_name_nbytes = new_name_nbytes;
/* Clear the short name. */
prim.type = CHANGE_SHORT_NAME;
prim.name.subject = dentry;
- prim.name.old_name = dentry->short_name;
+ prim.name.old_name = dentry->d_short_name;
ret = record_update_primitive(j, prim);
if (ret)
return ret;
- dentry->short_name = NULL;
- dentry->short_name_nbytes = 0;
+ dentry->d_short_name = NULL;
+ dentry->d_short_name_nbytes = 0;
return 0;
}
existing_child =
get_dentry_child_with_utf16le_name(existing,
- new_child->file_name,
- new_child->file_name_nbytes,
+ new_child->d_name,
+ new_child->d_name_nbytes,
WIMLIB_CASE_PLATFORM_DEFAULT);
unlink_dentry(new_child);
if (existing_child) {
if (add_flags & WIMLIB_ADD_FLAG_VERBOSE) {
union wimlib_progress_info info;
- info.replace.path_in_wim = existing->_full_path;
+ info.replace.path_in_wim = existing->d_full_path;
ret = call_progress(progfunc,
WIMLIB_PROGRESS_MSG_REPLACE_FILE_IN_WIM,
&info, progctx);
if (ret)
goto out_free_branch;
- BUILD_BUG_ON(WIM_PATH_SEPARATOR != OS_PREFERRED_PATH_SEPARATOR);
+ STATIC_ASSERT(WIM_PATH_SEPARATOR == OS_PREFERRED_PATH_SEPARATOR);
ret = dentry_set_name(branch, path_basename(target_tstr));
if (ret)
goto out_free_target;
struct capture_params params;
struct capture_config config;
capture_tree_t capture_tree = platform_default_capture_tree;
-#ifdef WITH_NTFS_3G
- struct _ntfs_volume *ntfs_vol = NULL;
-#endif
- void *extra_arg = NULL;
struct wim_dentry *branch;
add_flags = add_cmd->add.add_flags;
wim_target_path = add_cmd->add.wim_target_path;
config_file = add_cmd->add.config_file;
- DEBUG("fs_source_path=\"%"TS"\", wim_target_path=\"%"TS"\", add_flags=%#x",
- fs_source_path, wim_target_path, add_flags);
-
memset(¶ms, 0, sizeof(params));
#ifdef WITH_NTFS_3G
- if (add_flags & WIMLIB_ADD_FLAG_NTFS) {
- capture_tree = build_dentry_tree_ntfs;
- extra_arg = &ntfs_vol;
- if (wim_get_current_image_metadata(wim)->ntfs_vol != NULL) {
- ERROR("NTFS volume already set");
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out;
- }
- }
+ if (add_flags & WIMLIB_ADD_FLAG_NTFS)
+ capture_tree = ntfs_3g_build_dentry_tree;
#endif
ret = get_capture_config(config_file, &config,
params.sd_set = sd_set;
params.config = &config;
params.add_flags = add_flags;
- params.extra_arg = extra_arg;
params.progfunc = wim->progfunc;
params.progctx = wim->progctx;
¶ms.progress, params.progctx);
if (ret) {
free_dentry_tree(branch, wim->blob_table);
- goto out_cleanup_after_capture;
+ goto out_destroy_config;
}
if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path) &&
ERROR("\"%"TS"\" is not a directory!", fs_source_path);
ret = WIMLIB_ERR_NOTDIR;
free_dentry_tree(branch, wim->blob_table);
- goto out_cleanup_after_capture;
+ goto out_destroy_config;
}
ret = attach_branch(branch, wim_target_path, j,
add_flags, params.progfunc, params.progctx);
if (ret)
- goto out_cleanup_after_capture;
+ goto out_destroy_config;
if (config_file && (add_flags & WIMLIB_ADD_FLAG_WIMBOOT) &&
WIMLIB_IS_WIM_ROOT_PATH(wim_target_path))
* /Windows/System32/WimBootCompress.ini in the WIM image. */
ret = platform_default_capture_tree(&branch, config_file, ¶ms);
if (ret)
- goto out_cleanup_after_capture;
+ goto out_destroy_config;
ret = attach_branch(branch, wimboot_cfgfile, j, 0, NULL, NULL);
if (ret)
- goto out_cleanup_after_capture;
+ goto out_destroy_config;
+ }
+
+ if (WIMLIB_IS_WIM_ROOT_PATH(wim_target_path)) {
+ ret = set_windows_specific_info(wim);
+ if (ret)
+ goto out_destroy_config;
}
-#ifdef WITH_NTFS_3G
- wim_get_current_image_metadata(wim)->ntfs_vol = ntfs_vol;
-#endif
ret = 0;
- goto out_destroy_config;
-out_cleanup_after_capture:
-#ifdef WITH_NTFS_3G
- if (ntfs_vol)
- do_ntfs_umount(ntfs_vol);
-#endif
out_destroy_config:
destroy_capture_config(&config);
out:
flags = delete_cmd->delete_.delete_flags;
wim_path = delete_cmd->delete_.wim_path;
- DEBUG("Deleting WIM path \"%"TS"\" (flags=%#x)", wim_path, flags);
-
tree = get_dentry(wim, wim_path, WIMLIB_CASE_PLATFORM_DEFAULT);
if (!tree) {
/* Path to delete does not exist in the WIM. */
static int
free_dentry_full_path(struct wim_dentry *dentry, void *_ignore)
{
- FREE(dentry->_full_path);
- dentry->_full_path = NULL;
+ FREE(dentry->d_full_path);
+ dentry->d_full_path = NULL;
return 0;
}
unlink_dentry(src);
dentry_add_child(parent_of_dst, src);
}
- if (src->_full_path)
+ if (src->d_full_path)
for_dentry_in_tree(src, free_dentry_full_path, NULL);
return 0;
}
return ret;
}
-static inline const tchar *
-update_op_to_str(int op)
-{
- switch (op) {
- case WIMLIB_UPDATE_OP_ADD:
- return T("add");
- case WIMLIB_UPDATE_OP_DELETE:
- return T("delete");
- case WIMLIB_UPDATE_OP_RENAME:
- return T("rename");
- default:
- wimlib_assert(0);
- return NULL;
- }
-}
-
static bool
have_command_type(const struct wimlib_update_command *cmds, size_t num_cmds,
enum wimlib_update_op op)
inode_table = alloca(sizeof(struct wim_inode_table));
sd_set = alloca(sizeof(struct wim_sd_set));
- ret = init_inode_table(inode_table, 9001);
+ ret = init_inode_table(inode_table, 64);
if (ret)
goto out;
info.update.total_commands = num_cmds;
ret = 0;
for (size_t i = 0; i < num_cmds; i++) {
- DEBUG("Executing update command %zu of %zu (op=%"TS")",
- i + 1, num_cmds, update_op_to_str(cmds[i].op));
info.update.command = &cmds[i];
if (update_flags & WIMLIB_UPDATE_FLAG_SEND_PROGRESS) {
ret = call_progress(wim->progfunc,
WIMLIB_ADD_FLAG_WINCONFIG |
WIMLIB_ADD_FLAG_WIMBOOT |
WIMLIB_ADD_FLAG_NO_REPLACE |
- WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION))
+ WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION |
+ WIMLIB_ADD_FLAG_SNAPSHOT |
+ WIMLIB_ADD_FLAG_FILE_PATHS_UNNEEDED))
return WIMLIB_ERR_INVALID_PARAM;
bool is_entire_image = WIMLIB_IS_WIM_ROOT_PATH(cmd->add.wim_target_path);
#ifndef WITH_NTFS_3G
if (add_flags & WIMLIB_ADD_FLAG_NTFS) {
- ERROR("wimlib was compiled without support for NTFS-3g, so\n"
- " we cannot capture a WIM image directly "
- "from an NTFS volume");
+ ERROR("NTFS-3g capture mode is unsupported because wimlib "
+ "was compiled --without-ntfs-3g");
return WIMLIB_ERR_UNSUPPORTED;
}
#endif
#ifdef __WIN32__
- /* Check for flags not supported on Windows */
+ /* Check for flags not supported on Windows. */
if (add_flags & WIMLIB_ADD_FLAG_UNIX_DATA) {
ERROR("Capturing UNIX-specific data is not supported on Windows");
return WIMLIB_ERR_UNSUPPORTED;
ERROR("Dereferencing symbolic links is not supported on Windows");
return WIMLIB_ERR_UNSUPPORTED;
}
+#else
+ /* Check for flags only supported on Windows. */
+
+ /* Currently, SNAPSHOT means Windows VSS. In the future, it perhaps
+ * could be implemented for other types of snapshots, such as btrfs. */
+ if (add_flags & WIMLIB_ADD_FLAG_SNAPSHOT) {
+ ERROR("Snapshot mode is only supported on Windows, where it uses VSS.");
+ return WIMLIB_ERR_UNSUPPORTED;
+ }
#endif
/* VERBOSE implies EXCLUDE_VERBOSE */
}
if (!is_entire_image) {
- if (add_flags & WIMLIB_ADD_FLAG_NTFS) {
- ERROR("Cannot add directly from an NTFS volume "
- "when not capturing a full image!");
- return WIMLIB_ERR_INVALID_PARAM;
- }
-
if (add_flags & WIMLIB_ADD_FLAG_RPFIX) {
ERROR("Cannot do reparse point fixups when "
"not capturing a full image!");
int update_flags)
{
int ret;
+ struct wim_image_metadata *imd;
struct wimlib_update_command *cmds_copy;
if (update_flags & ~WIMLIB_UPDATE_FLAG_SEND_PROGRESS)
return WIMLIB_ERR_INVALID_PARAM;
- DEBUG("Updating image %d with %zu commands", image, num_cmds);
-
/* Load the metadata for the image to modify (if not loaded already) */
ret = select_wim_image(wim, image);
if (ret)
- goto out;
+ return ret;
- DEBUG("Preparing %zu update commands", num_cmds);
+ imd = wim->image_metadata[image - 1];
+
+ /* Don't allow updating an image currently being shared by multiple
+ * WIMStructs (as a result of an export) */
+ if (imd->refcnt > 1)
+ return WIMLIB_ERR_IMAGE_HAS_MULTIPLE_REFERENCES;
/* Make a copy of the update commands, in the process doing certain
* canonicalizations on paths (e.g. translating backslashes to forward
* commands. */
ret = copy_update_commands(cmds, num_cmds, &cmds_copy);
if (ret)
- goto out;
+ return ret;
/* Perform additional checks on the update commands before we execute
* them. */
goto out_free_cmds_copy;
/* Actually execute the update commands. */
- DEBUG("Executing %zu update commands", num_cmds);
ret = execute_update_commands(wim, cmds_copy, num_cmds, update_flags);
if (ret)
goto out_free_cmds_copy;
- wim->image_metadata[image - 1]->modified = 1;
-
- /* Statistics about the WIM image, such as the numbers of files and
- * directories, may have changed. Call xml_update_image_info() to
- * recalculate these statistics. */
- xml_update_image_info(wim, image);
+ mark_image_dirty(imd);
for (size_t i = 0; i < num_cmds; i++)
if (cmds_copy[i].op == WIMLIB_UPDATE_OP_ADD &&
wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX;
out_free_cmds_copy:
free_update_commands(cmds_copy, num_cmds);
-out:
return ret;
}