]> wimlib.net Git - wimlib/blobdiff - src/add_image.c
Get imagex extract --to-stdout working
[wimlib] / src / add_image.c
index 8e97a8ec1e95c3b7e623dba8e5b174880fb913a9..c39ded67c3903ec1ba1b8458a504fd0ae07665eb 100644 (file)
@@ -146,6 +146,7 @@ unix_capture_directory(struct wim_dentry *dir_dentry,
        }
 
        /* Recurse on directory contents */
+       ret = 0;
        for (;;) {
                errno = 0;
                entry = readdir(dir);
@@ -209,9 +210,9 @@ unix_capture_symlink(struct wim_dentry **root_p,
                if ((params->add_image_flags & WIMLIB_ADD_IMAGE_FLAG_RPFIX) &&
                     dest[0] == '/')
                {
-                       dest = fixup_symlink(dest,
-                                            params->capture_root_ino,
-                                            params->capture_root_dev);
+                       dest = capture_fixup_absolute_symlink(dest,
+                                                             params->capture_root_ino,
+                                                             params->capture_root_dev);
                        if (!dest) {
                                WARNING("Ignoring out of tree absolute symlink "
                                        "\"%s\" -> \"%s\"\n"
@@ -224,8 +225,7 @@ unix_capture_symlink(struct wim_dentry **root_p,
                        }
                        inode->i_not_rpfixed = 0;
                }
-               ret = inode_set_symlink(inode, dest,
-                                       params->lookup_table, NULL);
+               ret = wim_inode_set_symlink(inode, dest, params->lookup_table);
                if (ret == 0) {
                        /* Unfortunately, Windows seems to have the concept of
                         * "file" symbolic links as being different from
@@ -256,11 +256,6 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        struct wim_inode *inode;
 
        if (exclude_path(path, path_len, params->config, true)) {
-               if (params->add_image_flags & WIMLIB_ADD_IMAGE_FLAG_ROOT) {
-                       ERROR("Cannot exclude the root directory from capture");
-                       ret = WIMLIB_ERR_INVALID_CAPTURE_CONFIG;
-                       goto out;
-               }
                if ((params->add_image_flags & WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE)
                    && params->progress_func)
                {
@@ -304,9 +299,7 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret,
 
        ret = inode_table_new_dentry(params->inode_table,
                                     path_basename_with_len(path, path_len),
-                                    stbuf.st_ino,
-                                    stbuf.st_dev,
-                                    &root);
+                                    stbuf.st_ino, stbuf.st_dev, false, &root);
        if (ret)
                goto out;
 
@@ -388,7 +381,9 @@ unix_build_dentry_tree(struct wim_dentry **root_ret,
                        return WIMLIB_ERR_STAT;
                }
 
-               if (!S_ISDIR(root_stbuf.st_mode)) {
+               if ((params->add_image_flags & WIMLIB_ADD_IMAGE_FLAG_ROOT) &&
+                   !S_ISDIR(root_stbuf.st_mode))
+               {
                        ERROR("Root of capture \"%s\" is not a directory",
                              root_disk_path);
                        return WIMLIB_ERR_NOTDIR;
@@ -483,29 +478,6 @@ exclude_path(const tchar *path, size_t path_len,
 
 }
 
-/* Strip leading and trailing forward slashes from a string.  Modifies it in
- * place and returns the stripped string. */
-static const tchar *
-canonicalize_target_path(tchar *target_path)
-{
-       tchar *p;
-       if (target_path == NULL)
-               return T("");
-       for (;;) {
-               if (*target_path == T('\0'))
-                       return target_path;
-               else if (*target_path == T('/'))
-                       target_path++;
-               else
-                       break;
-       }
-
-       p = tstrchr(target_path, T('\0')) - 1;
-       while (*p == T('/'))
-               *p-- = T('\0');
-       return target_path;
-}
-
 /* Strip leading and trailing slashes from the target paths, and translate all
  * backslashes in the source and target paths into forward slashes. */
 static void
@@ -520,12 +492,8 @@ canonicalize_sources_and_targets(struct wimlib_capture_source *sources,
                /* The Windows API can handle forward slashes.  Just get rid of
                 * backslashes to avoid confusing other parts of the library
                 * code. */
-               zap_backslashes(sources->fs_source_path);
-               if (sources->wim_target_path)
-                       zap_backslashes(sources->wim_target_path);
-
-               sources->wim_target_path =
-                       (tchar*)canonicalize_target_path(sources->wim_target_path);
+               sources->fs_source_path = canonicalize_fs_path(sources->fs_source_path);
+               sources->wim_target_path = canonicalize_wim_path(sources->wim_target_path);
                DEBUG("Canonical target: \"%"TS"\"", sources->wim_target_path);
                sources++;
        }
@@ -623,9 +591,7 @@ new_filler_directory(const tchar *name, struct wim_dentry **dentry_ret)
        return ret;
 }
 
-/* Transfers the children of @branch to @target.  It is an error if @target is
- * not a directory or if both @branch and @target contain a child dentry with
- * the same name. */
+/* Overlays @branch onto @target, both of which must be directories. */
 static int
 do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
 {
@@ -634,30 +600,36 @@ do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
        DEBUG("Doing overlay \"%"WS"\" => \"%"WS"\"",
              branch->file_name, target->file_name);
 
-       if (!dentry_is_directory(target)) {
-               ERROR("Cannot overlay directory \"%"WS"\" "
-                     "over non-directory", branch->file_name);
+       if (!dentry_is_directory(branch) || !dentry_is_directory(target)) {
+               ERROR("Cannot overlay \"%"WS"\" onto existing dentry: "
+                     "is not directory-on-directory!", branch->file_name);
                return WIMLIB_ERR_INVALID_OVERLAY;
        }
 
        rb_root = &branch->d_inode->i_children;
        while (rb_root->rb_node) { /* While @branch has children... */
                struct wim_dentry *child = rbnode_dentry(rb_root->rb_node);
+               struct wim_dentry *existing;
+
                /* Move @child to the directory @target */
                unlink_dentry(child);
-               if (!dentry_add_child(target, child)) {
-                       /* Revert the change to avoid leaking the directory tree
-                        * rooted at @child */
-                       dentry_add_child(branch, child);
-                       ERROR("Overlay error: file \"%"WS"\" already exists "
-                             "as a child of \"%"WS"\"",
-                             child->file_name, target->file_name);
-                       return WIMLIB_ERR_INVALID_OVERLAY;
+               existing = dentry_add_child(target, child);
+
+               /* File or directory with same name already exists */
+               if (existing) {
+                       int ret;
+                       ret = do_overlay(existing, child);
+                       if (ret) {
+                               /* Overlay failed.  Revert the change to avoid
+                                * leaking the directory tree rooted at @child.
+                                * */
+                               dentry_add_child(branch, child);
+                               return ret;
+                       }
                }
        }
        free_dentry(branch);
        return 0;
-
 }
 
 /* Attach or overlay a branch onto the WIM image.
@@ -865,8 +837,13 @@ wimlib_add_image_multisource(WIMStruct *w,
 
        if ((add_image_flags & (WIMLIB_ADD_IMAGE_FLAG_RPFIX |
                                WIMLIB_ADD_IMAGE_FLAG_NORPFIX)) == 0)
-               if (w->hdr.flags & WIM_HDR_FLAG_RP_FIX)
+       {
+               /* Do reparse-point fixups by default if the header flag is set
+                * from previous images, or if this is the first image being
+                * added. */
+               if ((w->hdr.flags & WIM_HDR_FLAG_RP_FIX) || w->hdr.image_count == 0)
                        add_image_flags |= WIMLIB_ADD_IMAGE_FLAG_RPFIX;
+       }
 
        if (!name || !*name) {
                ERROR("Must specify a non-empty string for the image name");