]> wimlib.net Git - wimlib/blobdiff - src/add_image.c
Update progress functions
[wimlib] / src / add_image.c
index 7f337c5d04e032e8b0309c73c918a3b169e9f0de..cd270390c3f7185a8b6f10e0dca9eecf633072ef 100644 (file)
@@ -3,7 +3,7 @@
  */
 
 /*
- * 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);
 }