X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fadd_image.c;h=ff97bc1c603a7ee1ec7a4b5bad82a13eccaf6062;hp=b50b05b55400c6c01fe6d0dac616118abd73ce4a;hb=ff556d243953bd6df1399466c452f327feae2ed9;hpb=df7f6ca9f3d34b5133667ad35f800b7afcabe434 diff --git a/src/add_image.c b/src/add_image.c index b50b05b5..ff97bc1c 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -146,6 +146,7 @@ unix_capture_directory(struct wim_dentry *dir_dentry, } /* Recurse on directory contents */ + ret = 0; for (;;) { errno = 0; entry = readdir(dir); @@ -256,11 +257,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 +300,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 +382,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; @@ -623,9 +619,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 +628,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.