]> wimlib.net Git - wimlib/blobdiff - src/ntfs-3g_capture.c
Support for file exclusions via progress function
[wimlib] / src / ntfs-3g_capture.c
index 48bbc482410e73c0f8685f452dfcb7a1c8f309ab..5bc9563e862557f005bb79093aabfcf67753afe7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ntfs-3g_capture.c
  *
- * Capture a WIM image directly from a NTFS volume using libntfs-3g.  We capture
+ * Capture a WIM image directly from an NTFS volume using libntfs-3g.  We capture
  * everything we can, including security data and alternate data streams.
  */
 
@@ -341,7 +341,7 @@ insert_dos_name(struct dos_name_map *map, const ntfschar *dos_name,
        DEBUG("DOS name_len = %zu", name_nbytes);
        new_node = MALLOC(sizeof(struct dos_name_node));
        if (!new_node)
-               return -1;
+               return WIMLIB_ERR_NOMEM;
 
        /* DOS names are supposed to be 12 characters max (that's 24 bytes,
         * assuming 2-byte ntfs characters) */
@@ -357,19 +357,19 @@ insert_dos_name(struct dos_name_map *map, const ntfschar *dos_name,
        if (avl_tree_insert(&map->root, &new_node->index_node,
                            _avl_cmp_by_ntfs_ino))
        {
-               /* This should be impossible since a NTFS inode cannot
+               /* This should be impossible since an NTFS inode cannot
                 * have multiple DOS names, and we only should get each
                 * DOS name entry once from the ntfs_readdir() calls. */
                ERROR("NTFS inode %"PRIu64" has multiple DOS names",
                        le64_to_cpu(ntfs_ino));
                FREE(new_node);
-               return -1;
+               return WIMLIB_ERR_NOMEM;
        }
        DEBUG("Inserted DOS name for inode %"PRIu64, le64_to_cpu(ntfs_ino));
        return 0;
 }
 
-/* Returns a structure that contains the DOS name and its length for a NTFS
+/* Returns a structure that contains the DOS name and its length for an NTFS
  * inode, or NULL if the inode has no DOS name. */
 static struct dos_name_node *
 lookup_dos_name(const struct dos_name_map *map, u64 ntfs_ino)
@@ -394,7 +394,7 @@ set_dentry_dos_name(struct wim_dentry *dentry, const struct dos_name_map *map)
        if (dentry->is_win32_name) {
                node = lookup_dos_name(map, dentry->d_inode->i_ino);
                if (node) {
-                       dentry->short_name = utf16le_dupz(node->dos_node,
+                       dentry->short_name = utf16le_dupz((const utf16lechar *)node->dos_name,
                                                          node->name_nbytes);
                        if (!dentry->short_name)
                                return WIMLIB_ERR_NOMEM;
@@ -432,6 +432,7 @@ struct readdir_ctx {
        struct dos_name_map *dos_name_map;
        ntfs_volume *vol;
        struct add_image_params *params;
+       int ret;
 };
 
 static int
@@ -513,10 +514,11 @@ out_free_mbs_name:
        FREE(mbs_name);
 out:
        ctx->path[ctx->path_len] = '\0';
+       ctx->ret = ret;
        return ret;
 }
 
-/* Recursively build a WIM dentry tree corresponding to a NTFS volume.
+/* Recursively build a WIM dentry tree corresponding to an NTFS volume.
  * At the same time, update the WIM lookup table with lookup table entries for
  * the NTFS streams, and build an array of security descriptors.
  */
@@ -529,17 +531,16 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
                                 ntfs_volume *vol,
                                 struct add_image_params *params)
 {
-       le32 attributes;
+       u32 attributes;
        int ret;
        struct wim_dentry *root = NULL;
        struct wim_inode *inode = NULL;
 
-       if (should_exclude_path(path, path_len, params->config)) {
-               /* Exclude a file or directory tree based on the capture
-                * configuration file.  */
-               ret = 0;
+       ret = try_exclude(path, path_len, params);
+       if (ret < 0) /* Excluded? */
                goto out_progress;
-       }
+       if (ret > 0) /* Error? */
+               goto out;
 
        /* Get file attributes */
        ret = ntfs_get_ntfs_attrib(ni, (char*)&attributes, sizeof(attributes));
@@ -559,8 +560,7 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
                        goto out;
                }
                params->progress.scan.cur_path = path;
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
-               ret = 0;
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_UNSUPPORTED, NULL);
                goto out;
        }
 
@@ -578,14 +578,13 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
 
        if (inode->i_nlink > 1) {
                /* Shared inode; nothing more to do */
-               ret = 0;
                goto out_progress;
        }
 
        inode->i_creation_time    = le64_to_cpu(ni->creation_time);
        inode->i_last_write_time  = le64_to_cpu(ni->last_data_change_time);
        inode->i_last_access_time = le64_to_cpu(ni->last_access_time);
-       inode->i_attributes       = le32_to_cpu(attributes);
+       inode->i_attributes       = attributes;
        inode->i_resolved         = 1;
 
        /* Capture streams.  */
@@ -627,11 +626,18 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
                        .dos_name_map    = &dos_name_map,
                        .vol             = vol,
                        .params          = params,
+                       .ret             = 0,
                };
                ret = ntfs_readdir(ni, &pos, &ctx, wim_ntfs_capture_filldir);
                if (ret) {
-                       ERROR_WITH_ERRNO("Error reading directory \"%s\"", path);
-                       ret = WIMLIB_ERR_NTFS_3G;
+                       if (ctx.ret) {
+                               /* wimlib error  */
+                               ret = ctx.ret;
+                       } else {
+                               /* error from ntfs_readdir() itself  */
+                               ERROR_WITH_ERRNO("Error reading directory \"%s\"", path);
+                               ret = WIMLIB_ERR_NTFS_3G;
+                       }
                } else {
                        struct wim_dentry *child;
 
@@ -696,9 +702,9 @@ build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
 out_progress:
        params->progress.scan.cur_path = path;
        if (root == NULL)
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_EXCLUDED, NULL);
        else
-               do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
+               ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_OK, inode);
 out:
        if (ret == 0)
                *root_ret = root;
@@ -792,8 +798,6 @@ out:
                if (do_ntfs_umount(vol)) {
                        ERROR_WITH_ERRNO("Failed to unmount NTFS volume `%s'",
                                         device);
-                       if (ret == 0)
-                               ret = WIMLIB_ERR_NTFS_3G;
                }
        } else {
                /* We need to leave the NTFS volume mounted so that we can read