X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fadd_image.c;h=89721052d3a6156effd77fa1f07d873409312e3c;hp=e45bc1c1449b9efd72f51a7aa3cae7db4131b060;hb=cbeb81145e2532bfcf3f5e58c6be000615f54953;hpb=aee5df8a6702da0782d64333eb8b3d1fb52c880b diff --git a/src/add_image.c b/src/add_image.c index e45bc1c1..89721052 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); @@ -179,53 +180,6 @@ unix_capture_directory(struct wim_dentry *dir_dentry, return ret; } -static char * -fixup_symlink(char *dest, ino_t capture_root_ino, dev_t capture_root_dev) -{ - char *p = dest; - struct stat stbuf; - - for (;;) { - char save; - int ret; - - while (*p == '/') - p++; - - save = *p; - *p = '\0'; - if (stat(dest, &stbuf)) { - WARNING_WITH_ERRNO("Failed to stat \"%s\": %m", dest); - *p = save; - /* Treat as a link pointing outside the capture root (it - * most likely is). */ - return NULL; - } - *p = save; - - if (stbuf.st_ino == capture_root_ino && - stbuf.st_dev == capture_root_dev) - { - /* Link points inside capture root. Return abbreviated - * path. */ - if (*p == '\0') - *(p - 1) = '/'; - while (p - 1 >= dest && *(p - 1) == '/') - p--; - return p; - } - - if (*p == '\0') { - /* Link points outside capture root. */ - return NULL; - } - - do { - p++; - } while (*p != '/' && *p != '\0'); - } -} - static int unix_capture_symlink(struct wim_dentry **root_p, const char *path, @@ -269,6 +223,7 @@ unix_capture_symlink(struct wim_dentry **root_p, *root_p = NULL; return 0; } + inode->i_not_rpfixed = 0; } ret = inode_set_symlink(inode, dest, params->lookup_table, NULL); @@ -302,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) { @@ -434,7 +384,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; @@ -669,9 +621,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) { @@ -680,30 +630,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. @@ -911,8 +867,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");