]> wimlib.net Git - wimlib/blobdiff - src/ntfs-3g_capture.c
Add new helper function for attaching newly scanned dentry tree
[wimlib] / src / ntfs-3g_capture.c
index 5a97cff04e560252fb13cbde6f7d0f8c5f92f53f..439d17a61aa98c7931b9b59646427f62aa72ac6d 100644 (file)
@@ -189,34 +189,33 @@ cmp_ntfs_locations(const struct ntfs_location *loc1,
        return cmp_u64(loc1->sort_key, loc2->sort_key);
 }
 
+/* Read rptag and rpreserved from the NTFS inode and save them in the WIM inode.
+ */
 static int
-read_reparse_tag(ntfs_inode *ni, struct ntfs_location *loc,
-                u32 *reparse_tag_ret)
+read_reparse_header(ntfs_inode *ni, struct wim_inode *inode)
 {
-       int ret;
-       le32 reparse_tag;
+       struct {
+               le32 rptag;
+               le16 rpdatalen;
+               le16 rpreserved;
+       } hdr;
+       s64 res;
        ntfs_attr *na;
 
-       na = open_ntfs_attr(ni, loc);
-       if (!na) {
-               ret = WIMLIB_ERR_NTFS_3G;
-               goto out;
-       }
+       na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
+       if (!na)
+               return WIMLIB_ERR_NTFS_3G;
+
+       res = ntfs_attr_pread(na, 0, sizeof(hdr), &hdr);
 
-       if (ntfs_attr_pread(na, 0, sizeof(reparse_tag),
-                           &reparse_tag) != sizeof(reparse_tag))
-       {
-               ERROR_WITH_ERRNO("Error reading reparse data");
-               ret = WIMLIB_ERR_NTFS_3G;
-               goto out_close_ntfs_attr;
-       }
-       *reparse_tag_ret = le32_to_cpu(reparse_tag);
-       ret = 0;
-out_close_ntfs_attr:
        ntfs_attr_close(na);
-out:
-       return ret;
 
+       if (res != sizeof(hdr))
+               return WIMLIB_ERR_NTFS_3G;
+
+       inode->i_reparse_tag = le32_to_cpu(hdr.rptag);
+       inode->i_rp_reserved = le16_to_cpu(hdr.rpreserved);
+       return 0;
 }
 
 static int
@@ -268,7 +267,7 @@ scan_ntfs_attr(struct wim_inode *inode,
               ATTR_TYPES type,
               const ATTR_RECORD *record)
 {
-       const u64 data_size = ntfs_get_attribute_value_length(record);
+       u64 data_size = ntfs_get_attribute_value_length(record);
        const u32 name_nchars = record->name_length;
        struct blob_descriptor *blob = NULL;
        utf16lechar *stream_name = NULL;
@@ -285,6 +284,23 @@ scan_ntfs_attr(struct wim_inode *inode,
                }
        }
 
+       if (unlikely(type == AT_REPARSE_POINT)) {
+               if (data_size < REPARSE_DATA_OFFSET) {
+                       ERROR("Reparse point attribute of \"%s\" "
+                             "is too short!", path);
+                       ret = WIMLIB_ERR_INVALID_REPARSE_DATA;
+                       goto out_cleanup;
+               }
+               data_size -= REPARSE_DATA_OFFSET;
+
+               ret = read_reparse_header(ni, inode);
+               if (ret) {
+                       ERROR_WITH_ERRNO("Error reading reparse point header "
+                                        "of \"%s\"", path);
+                       goto out_cleanup;
+               }
+       }
+
        /* If the stream is non-empty, set up a blob descriptor for it.  */
        if (data_size != 0) {
                blob = new_blob_descriptor();
@@ -317,21 +333,6 @@ scan_ntfs_attr(struct wim_inode *inode,
                ret = set_attr_sort_key(ni, blob->ntfs_loc);
                if (ret)
                        goto out_cleanup;
-
-               if (unlikely(type == AT_REPARSE_POINT)) {
-                       if (blob->size < REPARSE_DATA_OFFSET) {
-                               ERROR("Reparse data of \"%s\" "
-                                     "is invalid (only %"PRIu64" bytes)!",
-                                     path, data_size);
-                               ret = WIMLIB_ERR_INVALID_REPARSE_DATA;
-                               goto out_cleanup;
-                       }
-                       blob->size -= REPARSE_DATA_OFFSET;
-                       ret = read_reparse_tag(ni, blob->ntfs_loc,
-                                              &inode->i_reparse_tag);
-                       if (ret)
-                               goto out_cleanup;
-               }
        }
 
        strm = inode_add_stream(inode,
@@ -521,14 +522,14 @@ set_dentry_dos_name(struct wim_dentry *dentry, const struct dos_name_map *map)
 {
        const struct dos_name_node *node;
 
-       if (dentry->is_win32_name) {
+       if (dentry->d_is_win32_name) {
                node = lookup_dos_name(map, dentry->d_inode->i_ino);
                if (node) {
-                       dentry->short_name = utf16le_dupz(node->dos_name,
-                                                         node->name_nbytes);
-                       if (!dentry->short_name)
+                       dentry->d_short_name = utf16le_dupz(node->dos_name,
+                                                           node->name_nbytes);
+                       if (!dentry->d_short_name)
                                return WIMLIB_ERR_NOMEM;
-                       dentry->short_name_nbytes = node->name_nbytes;
+                       dentry->d_short_name_nbytes = node->name_nbytes;
                } else {
                        WARNING("NTFS inode %"PRIu64" has Win32 name with no "
                                "corresponding DOS name",
@@ -590,17 +591,13 @@ filldir(void *_ctx, const ntfschar *name, const int name_nchars,
                        goto out;
        }
 
-       /* Ignore . and .. entries  */
-       ret = 0;
-       if ((name_nchars == 1 && name[0] == cpu_to_le16('.')) ||
-           (name_nchars == 2 && name[0] == cpu_to_le16('.') &&
-                                name[1] == cpu_to_le16('.')))
-               goto out;
-
        ret = utf16le_to_tstr(name, name_nbytes, &mbs_name, &mbs_name_nbytes);
        if (ret)
                goto out;
 
+       if (should_ignore_filename(mbs_name, mbs_name_nbytes))
+               goto out_free_mbs_name;
+
        path_len = ctx->path_len;
        if (path_len != 1)
                ctx->path[path_len++] = '/';
@@ -610,8 +607,8 @@ filldir(void *_ctx, const ntfschar *name, const int name_nchars,
        ret = ntfs_3g_build_dentry_tree_recursive(&child, mref, ctx->path,
                                                  path_len, name_type,
                                                  ctx->volume, ctx->params);
-       if (child)
-               dentry_add_child(ctx->parent, child);
+       attach_scanned_tree(ctx->parent, child, ctx->params->blob_table);
+out_free_mbs_name:
        FREE(mbs_name);
 out:
        ctx->ret = ret;
@@ -675,10 +672,10 @@ ntfs_3g_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        struct wim_inode *inode = NULL;
        ntfs_inode *ni = NULL;
 
-       ret = try_exclude(path, path_len, params);
-       if (ret < 0) /* Excluded? */
+       ret = try_exclude(path, params);
+       if (unlikely(ret < 0)) /* Excluded? */
                goto out_progress;
-       if (ret > 0) /* Error? */
+       if (unlikely(ret > 0)) /* Error? */
                goto out;
 
        ni = ntfs_inode_open(volume->vol, mref);
@@ -717,7 +714,7 @@ ntfs_3g_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                goto out;
 
        if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name (rather than POSIX) */
-               root->is_win32_name = 1;
+               root->d_is_win32_name = 1;
 
        inode = root->d_inode;