*/
/*
- * Copyright (C) 2012, 2013 Eric Biggers
+ * Copyright (C) 2012, 2013, 2014 Eric Biggers
*
* This file is part of wimlib, a library for working with WIM files.
*
#endif
#include "wimlib.h"
-#include "wimlib/capture.h"
#include "wimlib/error.h"
#include "wimlib/lookup_table.h"
#include "wimlib/metadata.h"
+#include "wimlib/security.h"
#include "wimlib/xml.h"
-/*
- * Adds the dentry tree and security data for a new image to the image metadata
- * array of the WIMStruct.
- */
+/* Creates and appends a 'struct wim_image_metadata' for an empty image.
+ *
+ * The resulting image will be the last in the WIM, so its index will be
+ * the new value of wim->hdr.image_count. */
static int
-add_new_dentry_tree(WIMStruct *wim, struct wim_dentry *root_dentry,
- struct wim_security_data *sd)
+add_empty_image_metadata(WIMStruct *wim)
{
- struct wim_image_metadata *new_imd;
- struct wim_lookup_table_entry *metadata_lte;
int ret;
+ struct wim_lookup_table_entry *metadata_lte;
+ struct wim_security_data *sd;
+ struct wim_image_metadata *imd;
+ /* Create lookup table entry for this metadata resource (for now really
+ * just a dummy entry). */
+ ret = WIMLIB_ERR_NOMEM;
metadata_lte = new_lookup_table_entry();
if (!metadata_lte)
- return WIMLIB_ERR_NOMEM;
+ goto out;
- metadata_lte->resource_entry.flags = WIM_RESHDR_FLAG_METADATA;
+ metadata_lte->flags = WIM_RESHDR_FLAG_METADATA;
metadata_lte->unhashed = 1;
- new_imd = new_image_metadata();
- if (!new_imd) {
- free_lookup_table_entry(metadata_lte);
- return WIMLIB_ERR_NOMEM;
- }
+ /* Create empty security data (no security descriptors). */
+ sd = new_wim_security_data();
+ if (!sd)
+ goto out_free_metadata_lte;
+
+ imd = new_image_metadata();
+ if (!imd)
+ goto out_free_security_data;
- new_imd->root_dentry = root_dentry;
- new_imd->metadata_lte = metadata_lte;
- new_imd->security_data = sd;
- new_imd->modified = 1;
+ /* A NULL root_dentry indicates a completely empty image, without even a
+ * root directory. */
+ imd->root_dentry = NULL;
+ imd->metadata_lte = metadata_lte;
+ imd->security_data = sd;
+ imd->modified = 1;
- ret = append_image_metadata(wim, new_imd);
+ /* Append as next image index. */
+ ret = append_image_metadata(wim, imd);
if (ret)
- put_image_metadata(new_imd, NULL);
+ put_image_metadata(imd, NULL);
+ goto out;
+
+out_free_security_data:
+ free_wim_security_data(sd);
+out_free_metadata_lte:
+ free_lookup_table_entry(metadata_lte);
+out:
return ret;
}
-/* Append an empty image to the WIMStruct. */
+/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_add_empty_image(WIMStruct *wim, const tchar *name, int *new_idx_ret)
{
int ret;
- struct wim_security_data *sd;
-
- DEBUG("Adding empty image \"%"TS"\"", name);
- if (name == NULL || name[0] == T('\0')) {
- ERROR("Must specify a non-empty string for the image name");
- ret = WIMLIB_ERR_INVALID_PARAM;
- goto out;
- }
+ ret = can_modify_wim(wim);
+ if (ret)
+ return ret;
- if (wim->hdr.total_parts != 1) {
- ERROR("Cannot add an image to a split WIM");
- ret = WIMLIB_ERR_SPLIT_UNSUPPORTED;
- goto out;
- }
+ if (!name)
+ name = T("");
if (wimlib_image_name_in_use(wim, name)) {
ERROR("There is already an image named \"%"TS"\" in the WIM!",
name);
- ret = WIMLIB_ERR_IMAGE_NAME_COLLISION;
- goto out;
- }
-
- sd = new_wim_security_data();
- if (!sd) {
- ret = WIMLIB_ERR_NOMEM;
- goto out;
+ return WIMLIB_ERR_IMAGE_NAME_COLLISION;
}
- ret = add_new_dentry_tree(wim, NULL, sd);
+ ret = add_empty_image_metadata(wim);
if (ret)
- goto out_free_security_data;
+ return ret;
ret = xml_add_image(wim, name);
- if (ret)
- goto out_put_image_metadata;
+ if (ret) {
+ put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
+ NULL);
+ return ret;
+ }
if (new_idx_ret)
*new_idx_ret = wim->hdr.image_count;
- DEBUG("Successfully added new image (index %d)",
- wim->hdr.image_count);
- goto out;
-out_put_image_metadata:
- put_image_metadata(wim->image_metadata[--wim->hdr.image_count],
- wim->lookup_table);
- goto out;
-out_free_security_data:
- free_security_data(sd);
-out:
- return ret;
+ return 0;
}
+/* Translate the 'struct wimlib_capture_source's passed to
+ * wimlib_add_image_multisource() into 'struct wimlib_update_command's for
+ * wimlib_update_image(). */
static struct wimlib_update_command *
capture_sources_to_add_cmds(const struct wimlib_capture_source *sources,
size_t num_sources,
int add_flags,
- const struct wimlib_capture_config *config)
+ const tchar *config_file)
{
struct wimlib_update_command *add_cmds;
- DEBUG("Translating %zu capture sources to `struct wimlib_update_command's",
- num_sources);
add_cmds = CALLOC(num_sources, sizeof(add_cmds[0]));
- if (add_cmds) {
- for (size_t i = 0; i < num_sources; i++) {
- DEBUG("Source %zu of %zu: fs_source_path=\"%"TS"\", "
- "wim_target_path=\"%"TS"\"",
- i + 1, num_sources,
- sources[i].fs_source_path,
- sources[i].wim_target_path);
- add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
- add_cmds[i].add.add_flags = add_flags;
- add_cmds[i].add.config = (struct wimlib_capture_config*)config;
- add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
- add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
- }
+ if (!add_cmds)
+ return NULL;
+
+ /* WIMLIB_ADD_FLAG_BOOT is handled by wimlib_add_image_multisource(),
+ * not wimlib_update_image(), so mask it out.
+ *
+ * However, WIMLIB_ADD_FLAG_WIMBOOT is handled by both. */
+ add_flags &= ~WIMLIB_ADD_FLAG_BOOT;
+
+ for (size_t i = 0; i < num_sources; i++) {
+ add_cmds[i].op = WIMLIB_UPDATE_OP_ADD;
+ add_cmds[i].add.fs_source_path = sources[i].fs_source_path;
+ add_cmds[i].add.wim_target_path = sources[i].wim_target_path;
+ add_cmds[i].add.add_flags = add_flags;
+ add_cmds[i].add.config_file = (tchar *)config_file;
}
return add_cmds;
}
-/* Adds an image to the WIMStruct from multiple on-disk directory trees, or a
- * NTFS volume. */
+/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_add_image_multisource(WIMStruct *wim,
const struct wimlib_capture_source *sources,
size_t num_sources,
const tchar *name,
- const struct wimlib_capture_config *config,
- int add_flags,
- wimlib_progress_func_t progress_func)
+ const tchar *config_file,
+ int add_flags)
{
int ret;
struct wimlib_update_command *add_cmds;
- DEBUG("Adding image \"%"TS"\" from %zu sources (add_flags=%#x)",
- name, num_sources, add_flags);
+ /* Make sure no reserved fields are set. */
+ for (size_t i = 0; i < num_sources; i++)
+ if (sources[i].reserved != 0)
+ return WIMLIB_ERR_INVALID_PARAM;
- /* Add the new image (initially empty) */
+ /* Add the new image (initially empty). */
ret = wimlib_add_empty_image(wim, name, NULL);
if (ret)
- goto out;
+ return ret;
- /* Translate the "capture sources" into generic update commands. */
+ /* Translate the "capture sources" into generic update commands. */
+ ret = WIMLIB_ERR_NOMEM;
add_cmds = capture_sources_to_add_cmds(sources, num_sources,
- add_flags, config);
- if (!add_cmds) {
- ret = WIMLIB_ERR_NOMEM;
+ add_flags, config_file);
+ if (!add_cmds)
goto out_delete_image;
- }
- /* Delegate the work to wimlib_update_image(). */
+ /* Delegate the work to wimlib_update_image(). */
ret = wimlib_update_image(wim, wim->hdr.image_count, add_cmds,
- num_sources, 0, progress_func);
+ num_sources, 0);
FREE(add_cmds);
if (ret)
goto out_delete_image;
- /* Success; set boot index if requested. */
+ /* If requested, set this image as the WIM's bootable image. */
if (add_flags & WIMLIB_ADD_FLAG_BOOT)
wim->hdr.boot_idx = wim->hdr.image_count;
- ret = 0;
- goto out;
+
+ /* If requested, mark new image as WIMBoot-compatible. */
+ if (add_flags & WIMLIB_ADD_FLAG_WIMBOOT)
+ wim_info_set_wimboot(wim->wim_info, wim->hdr.image_count, true);
+
+ return 0;
+
out_delete_image:
- /* Roll back the image we added */
- put_image_metadata(wim->image_metadata[wim->hdr.image_count - 1],
- wim->lookup_table);
+ /* Unsuccessful; rollback the WIM to its original state. */
+
+ /* wimlib_update_image() is now all-or-nothing, so no dentries remain
+ * and there's no need to pass the lookup table here. */
+ put_image_metadata(wim->image_metadata[wim->hdr.image_count - 1], NULL);
+
xml_delete_image(&wim->wim_info, wim->hdr.image_count);
wim->hdr.image_count--;
-out:
return ret;
}
-/* Adds an image to the WIMStruct from an on-disk directory tree or NTFS volume. */
+/* API function documented in wimlib.h */
WIMLIBAPI int
wimlib_add_image(WIMStruct *wim,
const tchar *source,
const tchar *name,
- const struct wimlib_capture_config *config,
- int add_flags,
- wimlib_progress_func_t progress_func)
+ const tchar *config_file,
+ int add_flags)
{
- /* Delegate the work to the more general wimlib_add_image_multisource().
- * */
+ /* Use the more general wimlib_add_image_multisource(). */
const struct wimlib_capture_source capture_src = {
- .fs_source_path = (tchar*)source,
- .wim_target_path = T(""),
+ .fs_source_path = (tchar *)source,
+ .wim_target_path = WIMLIB_WIM_ROOT_PATH,
.reserved = 0,
};
return wimlib_add_image_multisource(wim, &capture_src, 1, name,
- config, add_flags,
- progress_func);
+ config_file, add_flags);
}