-static int
-check_sorted_sources(struct wimlib_capture_source *sources, size_t num_sources,
- int add_image_flags)
-{
- if (add_image_flags & WIMLIB_ADD_IMAGE_FLAG_NTFS) {
- if (num_sources != 1) {
- ERROR("Must specify exactly 1 capture source "
- "(the NTFS volume) in NTFS mode!");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- if (sources[0].wim_target_path[0] != '\0') {
- ERROR("In NTFS capture mode the target path inside "
- "the image must be the root directory!");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- } else if (num_sources != 0) {
- /* This code is disabled because the current code
- * unconditionally attempts to do overlays. So, duplicate
- * target paths are OK. */
- #if 0
- if (num_sources > 1 && sources[0].wim_target_path[0] == '\0') {
- ERROR("Cannot specify root target when using multiple "
- "capture sources!");
- return WIMLIB_ERR_INVALID_PARAM;
- }
- for (size_t i = 0; i < num_sources - 1; i++) {
- size_t len = strlen(sources[i].wim_target_path);
- size_t j = i + 1;
- const char *target1 = sources[i].wim_target_path;
- do {
- const char *target2 = sources[j].wim_target_path;
- DEBUG("target1=%s, target2=%s",
- target1,target2);
- if (strncmp(target1, target2, len) ||
- target2[len] > '/')
- break;
- if (target2[len] == '/') {
- ERROR("Invalid target `%s': is a prefix of `%s'",
- target1, target2);
- return WIMLIB_ERR_INVALID_PARAM;
- }
- if (target2[len] == '\0') {
- ERROR("Invalid target `%s': is a duplicate of `%s'",
- target1, target2);
- return WIMLIB_ERR_INVALID_PARAM;
- }
- } while (++j != num_sources);
- }
- #endif
- }
- return 0;
-
-}
-
-/* Creates a new directory to place in the WIM image. This is to create parent
- * directories that are not part of any target as needed. */
-static struct wim_dentry *
-new_filler_directory(const mbchar *name)
-{
- struct wim_dentry *dentry;
- DEBUG("Creating filler directory \"%s\"", name);
- dentry = new_dentry_with_inode(name);
- if (dentry) {
- /* Leave the inode number as 0 for now. The final inode number
- * will be assigned later by assign_inode_numbers(). */
- dentry->d_inode->i_resolved = 1;
- dentry->d_inode->i_attributes = FILE_ATTRIBUTE_DIRECTORY;
- }
- return dentry;
-}
-
-/* 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. */
-static int
-do_overlay(struct wim_dentry *target, struct wim_dentry *branch)
-{
- struct rb_root *rb_root;
-
- DEBUG("Doing overlay \"%W\" => \"%W\"",
- branch->file_name, target->file_name);
-
- if (!dentry_is_directory(target)) {
- ERROR("Cannot overlay directory \"%W\" over non-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);
- /* 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 \"%W\" already exists "
- "as a child of \"%W\"",
- child->file_name, target->file_name);
- return WIMLIB_ERR_INVALID_OVERLAY;
- }
- }
- free_dentry(branch);
- return 0;
-
-}
-
-/* Attach or overlay a branch onto the WIM image.
- *
- * @root_p:
- * Pointer to the root of the WIM image, or pointer to NULL if it has not
- * been created yet.
- * @branch
- * Branch to add.
- * @target_path:
- * Path in the WIM image to add the branch, with leading and trailing
- * slashes stripped.
- */
-static int
-attach_branch(struct wim_dentry **root_p, struct wim_dentry *branch,
- mbchar *target_path)
-{
- char *slash;
- struct wim_dentry *dentry, *parent, *target;
-
- DEBUG("Attaching branch \"%W\" => \"%s\"",
- branch->file_name, target_path);
-
- if (*target_path == '\0') {
- /* Target: root directory */
- if (*root_p) {
- /* Overlay on existing root */
- return do_overlay(*root_p, branch);
- } else {
- /* Set as root */
- *root_p = branch;
- return 0;
- }
- }
-
- /* Adding a non-root branch. Create root if it hasn't been created
- * already. */
- if (!*root_p) {
- *root_p = new_filler_directory("");
- if (!*root_p)
- return WIMLIB_ERR_NOMEM;
- }
-
- /* Walk the path to the branch, creating filler directories as needed.
- * */
- parent = *root_p;
- while ((slash = strchr(target_path, '/'))) {
- *slash = '\0';
- dentry = get_dentry_child_with_name(parent, target_path);
- if (!dentry) {
- dentry = new_filler_directory(target_path);
- if (!dentry)
- return WIMLIB_ERR_NOMEM;
- dentry_add_child(parent, dentry);