]> wimlib.net Git - wimlib/blobdiff - src/unix_capture.c
Refactor some of the dentry, inode, and lookup table code
[wimlib] / src / unix_capture.c
index a080e8cb074cd1ac419c312ab991ef68ab7c51b9..dd79b658e0238cc9f15ed3d039ef1285e2dc9015 100644 (file)
@@ -45,7 +45,7 @@ static int
 unix_capture_regular_file(const char *path,
                          u64 size,
                          struct wim_inode *inode,
-                         struct wim_lookup_table *lookup_table)
+                         struct list_head *unhashed_streams)
 {
        inode->i_attributes = FILE_ATTRIBUTE_NORMAL;
 
@@ -64,8 +64,8 @@ unix_capture_regular_file(const char *path,
                }
                lte->file_on_disk = file_on_disk;
                lte->resource_location = RESOURCE_IN_FILE_ON_DISK;
-               lte->resource_entry.original_size = size;
-               lookup_table_insert_unhashed(lookup_table, lte, inode, 0);
+               lte->size = size;
+               add_unhashed_stream(lte, inode, 0, unhashed_streams);
                inode->i_lte = lte;
        }
        return 0;
@@ -128,6 +128,7 @@ unix_capture_directory(struct wim_dentry *dir_dentry,
                if (child)
                        dentry_add_child(dir_dentry, child);
        }
+       path[path_len] = '\0';
        closedir(dir);
        return ret;
 }
@@ -162,14 +163,17 @@ unix_capture_symlink(struct wim_dentry **root_p,
                        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"
-                                       "          (Use --norpfix to capture "
-                                       "absolute symlinks as-is)",
-                                       path, deref_name_buf);
+                       if (dest == NULL) {
+                               /* RPFIX (reparse point fixup) mode:  Ignore
+                                * absolute symbolic link that points out of the
+                                * tree to be captured.  */
                                free_dentry(*root_p);
                                *root_p = NULL;
+                               params->progress.scan.cur_path = path;
+                               params->progress.scan.symlink_target = deref_name_buf;
+                               do_capture_progress(params,
+                                                   WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
+                                                   NULL);
                                return 0;
                        }
                        inode->i_not_rpfixed = 0;
@@ -201,54 +205,40 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                 struct add_image_params *params)
 {
        struct wim_dentry *root = NULL;
-       int ret = 0;
-       struct wim_inode *inode;
+       int ret;
+       struct wim_inode *inode = NULL;
+       struct stat stbuf;
 
        if (exclude_path(path, path_len, params->config, true)) {
-               if ((params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE)
-                   && params->progress_func)
-               {
-                       union wimlib_progress_info info;
-                       info.scan.cur_path = path;
-                       info.scan.status = WIMLIB_SCAN_DENTRY_EXCLUDED;
-                       params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info);
-               }
-               goto out;
-       }
-
-       if ((params->add_flags & WIMLIB_ADD_FLAG_VERBOSE)
-           && params->progress_func)
-       {
-               union wimlib_progress_info info;
-               info.scan.cur_path = path;
-               info.scan.status = WIMLIB_SCAN_DENTRY_OK;
-               params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info);
+               ret = 0;
+               goto out_progress;
        }
 
-       struct stat stbuf;
-       int (*stat_fn)(const char *restrict, struct stat *restrict);
        if ((params->add_flags & WIMLIB_ADD_FLAG_DEREFERENCE) ||
            (params->add_flags & WIMLIB_ADD_FLAG_ROOT))
-               stat_fn = stat;
+               ret = stat(path, &stbuf);
        else
-               stat_fn = lstat;
+               ret = lstat(path, &stbuf);
 
-       ret = (*stat_fn)(path, &stbuf);
        if (ret) {
-               ERROR_WITH_ERRNO("Failed to stat `%s'", path);
+               ERROR_WITH_ERRNO("Failed to stat \"%s\"", path);
                ret = WIMLIB_ERR_STAT;
                goto out;
        }
-       if (!S_ISREG(stbuf.st_mode) && !S_ISDIR(stbuf.st_mode)
-           && !S_ISLNK(stbuf.st_mode)) {
-               if ((params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE)
-                   && params->progress_func)
+
+       if (!S_ISREG(stbuf.st_mode) &&
+           !S_ISDIR(stbuf.st_mode) &&
+           !S_ISLNK(stbuf.st_mode))
+       {
+               if (params->add_flags & WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE)
                {
-                       union wimlib_progress_info info;
-                       info.scan.cur_path = path;
-                       info.scan.status = WIMLIB_SCAN_DENTRY_UNSUPPORTED;
-                       params->progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info);
+                       ERROR("Can't archive unsupported file \"%s\"", path);
+                       ret = WIMLIB_ERR_UNSUPPORTED_FILE;
+                       goto out;
                }
+               params->progress.scan.cur_path = path;
+               do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
+               ret = 0;
                goto out;
        }
 
@@ -260,8 +250,11 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret,
 
        inode = root->d_inode;
 
-       if (inode->i_nlink > 1) /* Already captured this inode? */
-               goto out;
+       if (inode->i_nlink > 1) {
+               /* Already captured this inode? */
+               ret = 0;
+               goto out_progress;
+       }
 
 #ifdef HAVE_STAT_NANOSECOND_PRECISION
        inode->i_creation_time = timespec_to_wim_timestamp(stbuf.st_mtim);
@@ -285,23 +278,36 @@ unix_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        params->add_flags &= ~WIMLIB_ADD_FLAG_ROOT;
        if (S_ISREG(stbuf.st_mode))
                ret = unix_capture_regular_file(path, stbuf.st_size,
-                                               inode, params->lookup_table);
+                                               inode, params->unhashed_streams);
        else if (S_ISDIR(stbuf.st_mode))
                ret = unix_capture_directory(root, path, path_len, params);
-       else
+       else {
                ret = unix_capture_symlink(&root, path, inode, params);
-out:
-       if (ret == 0)
-               *root_ret = root;
+               if (root == NULL)
+                       goto out;
+       }
+
+       if (ret)
+               goto out;
+
+out_progress:
+       params->progress.scan.cur_path = path;
+       if (root == NULL)
+               do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
        else
+               do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
+out:
+       if (ret)
                free_dentry_tree(root, params->lookup_table);
+       else
+               *root_ret = root;
        return ret;
 }
 
 /*
  * unix_build_dentry_tree():
- *     Builds a tree of WIM dentries from an on-disk directory tree (UNIX
- *     version; no NTFS-specific data is captured).
+ *     Builds a tree of WIM dentries from an on-disk directory tree (UNIX
+ *     version; no NTFS-specific data is captured).
  *
  * @root_ret:   Place to return a pointer to the root of the dentry tree.  Only
  *             modified if successful.  Set to NULL if the file or directory was
@@ -352,7 +358,7 @@ unix_build_dentry_tree(struct wim_dentry **root_ret,
        if (path_len >= path_bufsz)
                return WIMLIB_ERR_INVALID_PARAM;
 
-       path_buf = MALLOC(path_bufsz);
+       path_buf = MALLOC(path_bufsz);
        if (!path_buf)
                return WIMLIB_ERR_NOMEM;
        memcpy(path_buf, root_disk_path, path_len + 1);