NTFS apply ADS fixes
authorEric Biggers <ebiggers3@gmail.com>
Wed, 29 Aug 2012 22:18:17 +0000 (17:18 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Wed, 29 Aug 2012 22:18:17 +0000 (17:18 -0500)
src/ntfs-apply.c
src/ntfs-capture.c
src/resource.c

index e8e86c1..d465e57 100644 (file)
@@ -1,9 +1,8 @@
 /*
  * ntfs-apply.c
  *
- * Apply a WIM image to a NTFS volume, restoring everything we can, including
- * security data and alternate data streams.  There should be no loss of
- * information.
+ * Apply a WIM image to a NTFS volume.  We restore everything we can, including
+ * security data and alternate data streams.
  */
 
 /*
@@ -119,19 +118,38 @@ static int write_ntfs_data_streams(ntfs_inode *ni, const struct dentry *dentry,
                ntfs_attr *na;
 
                lte = dentry_stream_lte(dentry, stream_idx, w->lookup_table);
-               na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
-               if (!na) {
-                       ERROR_WITH_ERRNO("Failed to open a data stream of "
-                                        "extracted file `%s'",
-                                        dentry->full_path_utf8);
-                       ret = WIMLIB_ERR_NTFS_3G;
-                       break;
+
+               if (stream_name_len) {
+                       /* Create an empty named stream. */
+                       ret = ntfs_attr_add(ni, AT_DATA, stream_name,
+                                           stream_name_len, NULL, 0);
+                       if (ret != 0) {
+                               ERROR_WITH_ERRNO("Failed to create name data "
+                                                "stream for extracted file "
+                                                "`%s'",
+                                                dentry->full_path_utf8);
+                               ret = WIMLIB_ERR_NTFS_3G;
+                               break;
+
+                       }
                }
-               if (lte)
+               /* If there's no lookup table entry, it's an empty stream.
+                * Otherwise, we must open the attribute and extract the data.
+                * */
+               if (lte) {
+                       na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
+                       if (!na) {
+                               ERROR_WITH_ERRNO("Failed to open a data stream of "
+                                                "extracted file `%s'",
+                                                dentry->full_path_utf8);
+                               ret = WIMLIB_ERR_NTFS_3G;
+                               break;
+                       }
                        ret = extract_wim_resource_to_ntfs_attr(lte, na);
-               ntfs_attr_close(na);
-               if (ret != 0)
-                       break;
+                       if (ret != 0)
+                               break;
+                       ntfs_attr_close(na);
+               }
                if (stream_idx == dentry->num_ads)
                        break;
                stream_name = (ntfschar*)dentry->ads_entries[stream_idx].stream_name;
@@ -669,10 +687,18 @@ static int do_wim_apply_image_ntfs(WIMStruct *w, const char *device, int extract
 
        if (ret != 0)
                goto out;
-       DEBUG("Setting NTFS timestamps");
+       if (extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE)
+               printf("Setting timestamps of extracted files on NTFS "
+                      "volume `%s'\n", device);
        ret = for_dentry_in_tree_depth(wim_root_dentry(w),
                                       wim_apply_dentry_timestamps,
                                       &args);
+       if (ret == 0 && (extract_flags & WIMLIB_EXTRACT_FLAG_VERBOSE))
+               printf("Finished applying image %d of %s to NTFS "
+                      "volume `%s'\n",
+                      w->current_image,
+                      w->filename ? w->filename : "WIM",
+                      device);
 out:
        DEBUG("Unmounting NTFS volume `%s'", device);
        if (ntfs_umount(vol, FALSE) != 0) {
index f16850e..1fe9ee1 100644 (file)
@@ -2,8 +2,7 @@
  * ntfs-capture.c
  *
  * Capture a WIM image from a NTFS volume.  We capture everything we can,
- * including security data and alternate data streams.  There should be no loss
- * of information.
+ * including security data and alternate data streams.
  */
 
 /*
@@ -272,6 +271,7 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                size_t stream_name_utf16_len;
                u32 reparse_tag;
                u64 data_size = ntfs_get_attribute_value_length(actx->attr);
+               u64 name_length = actx->attr->name_length;
 
                if (data_size == 0) { 
                        if (errno != 0) {
@@ -308,14 +308,16 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                                if (!ntfs_loc->path_utf8)
                                        goto out_free_ntfs_loc;
                                memcpy(ntfs_loc->path_utf8, path, path_len + 1);
-                               ntfs_loc->stream_name_utf16 = MALLOC(actx->attr->name_length * 2);
-                               if (!ntfs_loc->stream_name_utf16)
-                                       goto out_free_ntfs_loc;
-                               memcpy(ntfs_loc->stream_name_utf16,
-                                      attr_record_name(actx->attr),
-                                      actx->attr->name_length * 2);
+                               if (name_length) {
+                                       ntfs_loc->stream_name_utf16 = MALLOC(name_length * 2);
+                                       if (!ntfs_loc->stream_name_utf16)
+                                               goto out_free_ntfs_loc;
+                                       memcpy(ntfs_loc->stream_name_utf16,
+                                              attr_record_name(actx->attr),
+                                              actx->attr->name_length * 2);
+                                       ntfs_loc->stream_name_utf16_num_chars = name_length;
+                               }
 
-                               ntfs_loc->stream_name_utf16_num_chars = actx->attr->name_length;
                                lte = new_lookup_table_entry();
                                if (!lte)
                                        goto out_free_ntfs_loc;
@@ -333,13 +335,13 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                                }
                                ntfs_loc = NULL;
                                DEBUG("Add resource for `%s' (size = %zu)",
-                                       dentry->file_name_utf8,
-                                       lte->resource_entry.original_size);
+                                     dentry->file_name_utf8,
+                                     lte->resource_entry.original_size);
                                copy_hash(lte->hash, attr_hash);
                                lookup_table_insert(lookup_table, lte);
                        }
                }
-               if (actx->attr->name_length == 0) {
+               if (name_length == 0) {
                        /* Unnamed data stream.  Put the reference to it in the
                         * dentry. */
                        if (dentry->lte) {
@@ -355,7 +357,7 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                        struct ads_entry *new_ads_entry;
                        size_t stream_name_utf8_len;
                        stream_name_utf8 = utf16_to_utf8((const char*)attr_record_name(actx->attr),
-                                                        actx->attr->name_length,
+                                                        name_length * 2,
                                                         &stream_name_utf8_len);
                        if (!stream_name_utf8)
                                goto out_free_lte;
@@ -363,6 +365,8 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                        FREE(stream_name_utf8);
                        if (!new_ads_entry)
                                goto out_free_lte;
+
+                       wimlib_assert(new_ads_entry->stream_name_len == name_length * 2);
                                
                        new_ads_entry->lte = lte;
                }
index fd75a62..59c1d9c 100644 (file)
@@ -748,6 +748,8 @@ static int write_wim_resource(struct lookup_table_entry *lte,
        ntfs_inode *ni = NULL;
 #endif
 
+       wimlib_assert(lte);
+
        /* Original size of the resource */
        original_size = wim_resource_size(lte);