]> wimlib.net Git - wimlib/blobdiff - src/ntfs-3g_capture.c
NTFS-3g capture: sort attributes by starting LCN
[wimlib] / src / ntfs-3g_capture.c
index dd6cae76df4756125935955ebf4808e3c5b55181..c0bd9076afeb472801d555a2e53dff3f8d70fcf4 100644 (file)
@@ -65,8 +65,8 @@ open_ntfs_attr(ntfs_inode *ni, const struct ntfs_location *loc)
                            loc->attr_name,
                            loc->attr_name_nchars);
        if (!na) {
-               ERROR_WITH_ERRNO("Failed to open attribute of \"%"TS"\" in "
-                                "NTFS volume", loc->path);
+               ERROR_WITH_ERRNO("Failed to open attribute of NTFS inode %"PRIu64,
+                                loc->mft_no);
        }
        return na;
 }
@@ -84,9 +84,10 @@ read_ntfs_attribute_prefix(const struct blob_descriptor *blob, u64 size,
        int ret;
        u8 buf[BUFFER_SIZE];
 
-       ni = ntfs_pathname_to_inode(vol, NULL, loc->path);
+       ni = ntfs_inode_open(vol, loc->mft_no);
        if (!ni) {
-               ERROR_WITH_ERRNO("Can't find NTFS inode for \"%"TS"\"", loc->path);
+               ERROR_WITH_ERRNO("Failed to open NTFS inode %"PRIu64,
+                                loc->mft_no);
                ret = WIMLIB_ERR_NTFS_3G;
                goto out;
        }
@@ -102,7 +103,8 @@ read_ntfs_attribute_prefix(const struct blob_descriptor *blob, u64 size,
        while (bytes_remaining) {
                s64 to_read = min(bytes_remaining, sizeof(buf));
                if (ntfs_attr_pread(na, pos, to_read, buf) != to_read) {
-                       ERROR_WITH_ERRNO("Error reading \"%"TS"\"", loc->path);
+                       ERROR_WITH_ERRNO("Error reading data from NTFS inode "
+                                        "%"PRIu64, loc->mft_no);
                        ret = WIMLIB_ERR_NTFS_3G;
                        goto out_close_ntfs_attr;
                }
@@ -166,6 +168,30 @@ attr_type_to_wimlib_stream_type(ATTR_TYPES type)
        }
 }
 
+/* When sorting blobs located in NTFS volumes for sequential reading, we sort
+ * first by starting LCN of the attribute if available, otherwise no sort order
+ * is defined.  This usually results in better sequential access to the volume.
+ */
+static int
+set_attr_sort_key(ntfs_inode *ni, struct ntfs_location *loc)
+{
+       ntfs_attr *na;
+       runlist_element *rl;
+
+       na = open_ntfs_attr(ni, loc);
+       if (!na)
+               return WIMLIB_ERR_NTFS_3G;
+
+       rl = ntfs_attr_find_vcn(na, 0);
+       if (rl && rl->lcn != LCN_HOLE)
+               loc->sort_key = rl->lcn;
+       else
+               loc->sort_key = 0;
+
+       ntfs_attr_close(na);
+       return 0;
+}
+
 /* Save information about an NTFS attribute (stream) to a WIM inode.  */
 static int
 scan_ntfs_attr(struct wim_inode *inode,
@@ -212,11 +238,7 @@ scan_ntfs_attr(struct wim_inode *inode,
                blob->size = data_size;
                blob->ntfs_loc->ntfs_vol = vol;
                blob->ntfs_loc->attr_type = type;
-               blob->ntfs_loc->path = memdup(path, path_len + 1);
-               if (unlikely(!blob->ntfs_loc->path)) {
-                       ret = WIMLIB_ERR_NOMEM;
-                       goto out_cleanup;
-               }
+               blob->ntfs_loc->mft_no = ni->mft_no;
 
                if (unlikely(name_nchars)) {
                        blob->ntfs_loc->attr_name = utf16le_dup(stream_name);
@@ -227,6 +249,10 @@ scan_ntfs_attr(struct wim_inode *inode,
                        blob->ntfs_loc->attr_name_nchars = name_nchars;
                }
 
+               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\" "