NTFS capture (IN PROGRESS)
authorEric Biggers <ebiggers3@gmail.com>
Sun, 26 Aug 2012 02:12:08 +0000 (21:12 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 26 Aug 2012 02:12:08 +0000 (21:12 -0500)
src/lookup_table.h
src/modify.c
src/ntfs-capture.c
src/wimlib_internal.h

index 0490291..c15bf40 100644 (file)
@@ -26,6 +26,14 @@ struct lookup_table {
 
 struct wimlib_fd;
 
+typedef struct _ntfs_attr ntfs_attr;
+typedef struct _ntfs_volume ntfs_volume;
+struct ntfs_location {
+       ntfs_volume *vol;
+       const char *path;
+       const char *ads_name;
+};
+
 /* 
  * An entry in the lookup table in the WIM file. 
  *
@@ -56,6 +64,7 @@ struct lookup_table_entry {
                RESOURCE_IN_FILE_ON_DISK,
                RESOURCE_IN_STAGING_FILE,
                RESOURCE_IN_ATTACHED_BUFFER,
+               RESOURCE_IN_NTFS_VOLUME,
        } resource_location;
 
        /* Number of times this lookup table entry is referenced by dentries. */
@@ -84,10 +93,12 @@ struct lookup_table_entry {
                char *file_on_disk;
                char *staging_file_name;
                u8 *attached_buffer;
+               struct ntfs_location *ntfs_location;
        };
        union {
                struct lookup_table_entry *next_lte_in_swm;
                FILE *file_on_disk_fp;
+               ntfs_attr *attr;
        };
 #ifdef WITH_FUSE
        /* File descriptors table for this data stream */
index cef29ab..ed6b07f 100644 (file)
@@ -73,8 +73,10 @@ void destroy_image_metadata(struct image_metadata *imd,struct lookup_table *lt)
  *             the regular files in the tree into the WIM as file resources.
  */
 static int build_dentry_tree(struct dentry *root, const char *root_disk_path,
-                            struct lookup_table* lookup_table,
-                            int add_flags)
+                            struct lookup_table *lookup_table,
+                            struct wim_security_data *sd,
+                            int add_flags,
+                            void *extra_arg)
 {
        DEBUG("%s", root_disk_path);
        struct stat root_stbuf;
@@ -140,7 +142,7 @@ static int build_dentry_tree(struct dentry *root, const char *root_disk_path,
                        if (!child)
                                return WIMLIB_ERR_NOMEM;
                        ret = build_dentry_tree(child, name, lookup_table,
-                                               add_flags);
+                                               sd, add_flags, extra_arg);
                        link_dentry(child, root);
                        if (ret != 0)
                                break;
@@ -263,12 +265,12 @@ static int add_lte_to_dest_wim(struct dentry *dentry, void *arg)
  * @w:           The WIMStruct for the WIM file.
  * @root_dentry:  The root of the directory tree for the image.
  */
-static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry)
+static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry,
+                              struct wim_security_data *sd)
 {
        struct lookup_table_entry *metadata_lte;
        struct image_metadata *imd;
        struct image_metadata *new_imd;
-       struct wim_security_data *sd;
        struct link_group_table *lgt;
 
        DEBUG("Reallocating image metadata array for image_count = %u",
@@ -286,11 +288,6 @@ static int add_new_dentry_tree(WIMStruct *w, struct dentry *root_dentry)
        metadata_lte = new_lookup_table_entry();
        if (!metadata_lte)
                goto out_free_imd;
-       sd = CALLOC(1, sizeof(struct wim_security_data));
-       if (!sd)
-               goto out_free_metadata_lte;
-       sd->refcnt = 1;
-       sd->total_length = 8;
 
        lgt = new_link_group_table(9001);
        if (!lgt)
@@ -338,6 +335,7 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
        int ret;
        struct dentry *root;
        struct wim_pair wims;
+       struct wim_security_data *sd;
 
        if (src_image == WIM_ALL_IMAGES) {
                if (src_wim->hdr.image_count > 1) {
@@ -411,21 +409,16 @@ WIMLIBAPI int wimlib_export_image(WIMStruct *src_wim,
         * wimlib_export_image() is documented as leaving dest_wim is an
         * indeterminate state.  */
        root = wim_root_dentry(src_wim);
+       sd = wim_security_data(src_wim);
        for_dentry_in_tree(root, increment_dentry_refcnt, NULL);
        wims.src_wim = src_wim;
        wims.dest_wim = dest_wim;
        ret = for_dentry_in_tree(root, add_lte_to_dest_wim, &wims);
        if (ret != 0)
                return ret;
-       ret = add_new_dentry_tree(dest_wim, root);
+       ret = add_new_dentry_tree(dest_wim, root, sd);
        if (ret != 0)
                return ret;
-       /* Bring over old security data */
-       struct wim_security_data *sd = wim_security_data(src_wim);
-       struct image_metadata *new_imd = wim_get_current_image_metadata(dest_wim);
-       wimlib_assert(sd);
-       free_security_data(new_imd->security_data);
-       new_imd->security_data = sd;
        sd->refcnt++;
 
        if (flags & WIMLIB_EXPORT_FLAG_BOOT) {
@@ -499,10 +492,13 @@ int do_add_image(WIMStruct *w, const char *dir, const char *name,
                 const char *description, const char *flags_element,
                 int flags,
                 int (*capture_tree)(struct dentry *, const char *,
-                                    struct lookup_table *, int))
+                                    struct lookup_table *, 
+                                    struct wim_security_data *, int, void *),
+                void *extra_arg)
 {
        struct dentry *root_dentry;
        struct image_metadata *imd;
+       struct wim_security_data *sd;
        int ret;
 
        DEBUG("Adding dentry tree from dir `%s'.", dir);
@@ -528,23 +524,31 @@ int do_add_image(WIMStruct *w, const char *dir, const char *name,
        if (!root_dentry)
                return WIMLIB_ERR_NOMEM;
 
+
+       sd = CALLOC(1, sizeof(struct wim_security_data));
+       if (!sd)
+               goto out_free_dentry_tree;
+       sd->total_length = 8;
+       sd->refcnt = 1;
+
        DEBUG("Building dentry tree.");
-       ret = (*capture_tree)(root_dentry, dir, w->lookup_table,
-                             flags | WIMLIB_ADD_IMAGE_FLAG_ROOT);
+       ret = (*capture_tree)(root_dentry, dir, w->lookup_table, sd,
+                             flags | WIMLIB_ADD_IMAGE_FLAG_ROOT,
+                             extra_arg);
 
        if (ret != 0) {
                ERROR("Failed to build dentry tree for `%s'", dir);
-               goto out_free_dentry_tree;
+               goto out_free_sd;
        }
 
        DEBUG("Calculating full paths of dentries.");
        ret = for_dentry_in_tree(root_dentry, calculate_dentry_full_path, NULL);
        if (ret != 0)
-               goto out_free_dentry_tree;
+               goto out_free_sd;
 
-       ret = add_new_dentry_tree(w, root_dentry);
+       ret = add_new_dentry_tree(w, root_dentry, sd);
        if (ret != 0)
-               goto out_free_dentry_tree;
+               goto out_free_sd;
 
        DEBUG("Inserting dentries into hard link group table");
        ret = for_dentry_in_tree(root_dentry, link_group_table_insert, 
@@ -567,6 +571,8 @@ out_destroy_imd:
                               w->lookup_table);
        w->hdr.image_count--;
        return ret;
+out_free_sd:
+       free_security_data(sd);
 out_free_dentry_tree:
        free_dentry_tree(root_dentry, w->lookup_table);
        return ret;
@@ -580,5 +586,5 @@ WIMLIBAPI int wimlib_add_image(WIMStruct *w, const char *dir,
                               const char *flags_element, int flags)
 {
        return do_add_image(w, dir, name, description, flags_element, flags,
-                           build_dentry_tree);
+                           build_dentry_tree, NULL);
 }
index 2ca4afa..8eec3ed 100644 (file)
@@ -182,20 +182,57 @@ out_revert:
 }
 #endif
 
+static int ntfs_attr_sha1sum(ntfs_inode *ni, ATTR_RECORD *ar,
+                            u8 md[SHA1_HASH_SIZE])
+{
+       s64 pos = 0;
+       s64 bytes_remaining;
+       char buf[4096];
+       ntfs_attr *na;
+       SHA_CTX ctx;
+
+       na = ntfs_attr_open(ni, ar->type,
+                           (ntfschar*)((u8*)ar + le16_to_cpu(ar->name_offset)),
+                           ar->name_length);
+       if (!na) {
+               ERROR_WITH_ERRNO("Failed to open NTFS attribute");
+               return WIMLIB_ERR_NTFS_3G;
+       }
+
+       bytes_remaining = na->data_size;
+       sha1_init(&ctx);
+
+       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 NTFS attribute");
+                       return WIMLIB_ERR_NTFS_3G;
+               }
+               sha1_update(&ctx, buf, to_read);
+               pos += to_read;
+               bytes_remaining -= to_read;
+       }
+       sha1_final(md, &ctx);
+       ntfs_attr_close(na);
+       return 0;
+}
+
 static int __build_dentry_tree_ntfs(struct dentry *dentry, ntfs_inode *ni,
+                                   char path[], size_t path_len,
                                    struct lookup_table *lookup_table,
                                    struct sd_tree *tree)
 {
        u32 attributes = ntfs_inode_get_attributes(ni);
        int mrec_flags = ni->mrec->flags;
        u32 sd_size;
-       int ret;
+       int ret = 0;
 
        dentry->creation_time    = le64_to_cpu(ni->creation_time);
        dentry->last_write_time  = le64_to_cpu(ni->last_data_change_time);
        dentry->last_access_time = le64_to_cpu(ni->last_access_time);
        dentry->security_id      = le32_to_cpu(ni->security_id);
        dentry->attributes       = le32_to_cpu(attributes);
+       dentry->resolved = true;
 
        if (mrec_flags & MFT_RECORD_IS_DIRECTORY) {
                if (attributes & FILE_ATTR_REPARSE_POINT) {
@@ -208,6 +245,45 @@ static int __build_dentry_tree_ntfs(struct dentry *dentry, ntfs_inode *ni,
                        /* Symbolic link or other reparse point */
                } else {
                        /* Normal file */
+                       ntfs_attr_search_ctx *actx;
+                       u8 attr_hash[SHA1_HASH_SIZE];
+                       struct lookup_table_entry *lte;
+
+                       actx = ntfs_attr_get_search_ctx(ni, NULL);
+                       if (!actx) {
+                               ERROR_WITH_ERRNO("Cannot get attribute search "
+                                                "context");
+                               return WIMLIB_ERR_NTFS_3G;
+                       }
+                       while (!ntfs_attr_lookup(AT_DATA, NULL, 0,
+                                                CASE_SENSITIVE, 0, NULL, 0, actx))
+                       {
+                               ret = ntfs_attr_sha1sum(ni, actx->attr, attr_hash);
+                               if (ret != 0)
+                                       return ret;
+                               lte = __lookup_resource(lookup_table, attr_hash);
+                               if (lte) {
+                                       lte->refcnt++;
+                               } else {
+                                       /*char *file_on_disk = STRDUP(root_disk_path);*/
+                                       /*if (!file_on_disk) {*/
+                                               /*ERROR("Failed to allocate memory for file path");*/
+                                               /*return WIMLIB_ERR_NOMEM;*/
+                                       /*}*/
+                                       /*lte = new_lookup_table_entry();*/
+                                       /*if (!lte) {*/
+                                               /*FREE(file_on_disk);*/
+                                               /*return WIMLIB_ERR_NOMEM;*/
+                                       /*}*/
+                                       /*lte->file_on_disk = file_on_disk;*/
+                                       /*lte->resource_location = RESOURCE_IN_FILE_ON_DISK;*/
+                                       /*lte->resource_entry.original_size = root_stbuf.st_size;*/
+                                       /*lte->resource_entry.size = root_stbuf.st_size;*/
+                                       /*copy_hash(lte->hash, hash);*/
+                                       /*lookup_table_insert(lookup_table, lte);*/
+                               }
+                               dentry->lte = lte;
+                       }
                }
        }
        ret = ntfs_inode_get_security(ni,
@@ -224,24 +300,23 @@ static int __build_dentry_tree_ntfs(struct dentry *dentry, ntfs_inode *ni,
                                      SACL_SECURITY_INFORMATION,
                                      sd, sd_size, &sd_size);
        dentry->security_id = tree_add_sd(tree, sd, sd_size);
-
        return 0;
 }
 
 static int build_dentry_tree_ntfs(struct dentry *root_dentry,
                                  const char *device,
                                  struct lookup_table *lookup_table,
-                                 int flags)
+                                 struct wim_security_data *sd,
+                                 int flags,
+                                 void *extra_arg)
 {
        ntfs_volume *vol;
        ntfs_inode *root_ni;
        int ret = 0;
        struct sd_tree tree;
-       tree.sd = CALLOC(1, sizeof(struct wim_security_data));
-       if (!tree.sd)
-               return WIMLIB_ERR_NOMEM;
-       tree.sd->total_length = 8;
+       tree.sd = sd;
        tree.root = NULL;
+       ntfs_volume **ntfs_vol_p = extra_arg;
        
        vol = ntfs_mount(device, MS_RDONLY);
        if (!vol) {
@@ -256,7 +331,11 @@ static int build_dentry_tree_ntfs(struct dentry *root_dentry,
                ret = WIMLIB_ERR_NTFS_3G;
                goto out;
        }
-       ret = __build_dentry_tree_ntfs(root_dentry, root_ni, lookup_table, &tree);
+       char path[4096];
+       path[0] = '/';
+       path[1] = '\0';
+       ret = __build_dentry_tree_ntfs(root_dentry, root_ni, path, 1,
+                                      lookup_table, &tree);
 
 out:
        if (ntfs_umount(vol, FALSE) != 0) {
@@ -279,7 +358,8 @@ WIMLIBAPI int wimlib_add_image_from_ntfs_volume(WIMStruct *w,
                return WIMLIB_ERR_INVALID_PARAM;
        }
        return do_add_image(w, device, name, description, flags_element, flags,
-                           build_dentry_tree_ntfs);
+                           build_dentry_tree_ntfs,
+                           &w->ntfs_vol);
 }
 
 #else /* WITH_NTFS_3G */
index 4f39062..1a2654c 100644 (file)
@@ -181,6 +181,7 @@ struct wim_header {
  * a LZ77-based algorithm. */
 #define WIM_HDR_FLAG_COMPRESS_LZX       0x00040000
 
+typedef struct _ntfs_volume ntfs_volume;
 
 /* Structure for security data.  Each image in the WIM file has its own security
  * data. */
@@ -265,6 +266,7 @@ typedef struct WIMStruct {
                int add_flags;
                int write_flags;
                bool write_metadata;
+               ntfs_volume *ntfs_vol;
        };
 
        /* The currently selected image, indexed starting at 1.  If not 0,
@@ -338,7 +340,9 @@ extern int do_add_image(WIMStruct *w, const char *dir, const char *name,
                        const char *description, const char *flags_element,
                        int flags,
                        int (*capture_tree)(struct dentry *, const char *,
-                                    struct lookup_table *, int));
+                                    struct lookup_table *, 
+                                    struct wim_security_data *, int, void *),
+                       void *extra_arg);
 
 /* resource.c */
 extern const u8 *get_resource_entry(const u8 *p, struct resource_entry *entry);