Misc fixes
authorEric Biggers <ebiggers3@gmail.com>
Sun, 26 Aug 2012 23:46:47 +0000 (18:46 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 26 Aug 2012 23:46:47 +0000 (18:46 -0500)
- Remove code pertaining to root permissions.  We don't need to be root to do a
  NTFS apply anymore.
- Improve comments on fields of `struct dentry'.
- Another fix to hard-link creation in the NTFS apply.  We close the directory
  inode before opening the target inode and re-opening the directory inode, so
  that we can make sure the directory inode will not be opened twice at the same
  time.

src/dentry.h
src/lookup_table.h
src/ntfs-apply.c
src/ntfs-capture.c
src/util.c
src/wimlib.h

index e030acf03b27c3b9487b1d6217cf87ec6bf5ca04..d634abcdc61173519f8f58fe016fe837bd500e7d 100644 (file)
@@ -114,24 +114,33 @@ struct dentry {
        /* Pointer to a child of this directory entry. */
        struct dentry *children;
 
-       /* Size of directory entry, in bytes.  Typical size is around 104 to 120
-        * bytes. */
-       /* It is possible for the length field to be 0.  This situation, which
+       /* Size of directory entry on disk, in bytes.  Typical size is around
+        * 104 to 120 bytes.
+        *
+        * It is possible for the length field to be 0.  This situation, which
         * is undocumented, indicates the end of a list of sibling nodes in a
         * directory.  It also means the real length is 8, because the dentry
-        * included only the length field, but that takes up 8 bytes. */
+        * included only the length field, but that takes up 8 bytes.
+        *
+        * The length here includes the base directory entry on disk as well as
+        * the long and short filenames.  It does NOT include any alternate
+        * stream entries that may follow the directory entry, even though the
+        * size of those needs to be considered.
+        */
        u64 length;
 
        /* The file attributes associated with this file. */
        u32 attributes;
 
-       /* The index of the node in the security table that contains this file's
-        * security information.  If -1, no security information exists for this
-        * file.  */
+       /* The index of the security descriptor in the WIM image's table of
+        * security descriptors that contains this file's security information.
+        * If -1, no security information exists for this file.  */
        int32_t security_id;
 
-       /* The offset, from the start of the metadata section, of this directory
-        * entry's child files.  0 if the directory entry has no children. */
+       /* The offset, from the start of the WIM metadata resource for this
+        * image, of this directory entry's child files.  0 if the directory
+        * entry has no children (as in the case of regular files or reparse
+        * points). */
        u64 subdir_offset;
 
        /* Timestamps for the dentry.  The timestamps are the number of
@@ -142,15 +151,15 @@ struct dentry {
        u64 last_write_time;
 
        /* true if the dentry's lookup table entry has been resolved (i.e. the
-        * @lte field is invalid, but the @hash field is not valid) */
+        * @lte field is valid, but the @hash field is not valid) */
        bool resolved;
 
        /* A hash of the file's contents, or a pointer to the lookup table entry
         * for this dentry if the lookup table entries have been resolved.
         *
         * More specifically, this is for the un-named default file stream, as
-        * opposed to the alternate file streams, which may have their own
-        * lookup table entries.  */
+        * opposed to the alternate (named) file streams, which may have their
+        * own lookup table entries.  */
        union {
                u8 hash[SHA1_HASH_SIZE];
                struct lookup_table_entry *lte;
@@ -210,7 +219,11 @@ struct dentry {
        };
 
        /* If the file is part of a hard link set, all the directory entries in
-        * the set will share the same value for this field. */
+        * the set will share the same value for this field. 
+        *
+        * Unfortunately, in some WIMs it is NOT the case that all dentries that
+        * share this field are actually in the same hard link set, although the
+        * WIMs that wimlib writes maintain this restriction. */
        u64 hard_link;
 
        enum {
index 79fdf116d392a826a9d144c657160171819332f5..6a07aaa97d51db024ebdb8f00a80ae2df841bd36 100644 (file)
@@ -33,6 +33,7 @@ struct ntfs_location {
        char *stream_name_utf16;
        u16 stream_name_utf16_num_chars;
        ntfs_volume **ntfs_vol_p;
+       bool is_reparse_point;
 };
 
 /* 
index c4e09fe5e32712151c6092e5101bc1fdd082fb91..4118a30af74dac5fc5e3f626c39d03aa86ae5a69 100644 (file)
@@ -141,6 +141,15 @@ static int write_ntfs_data_streams(ntfs_inode *ni, const struct dentry *dentry,
        return ret;
 }
 
+static bool in_same_dir(const char *path1, const char *path2)
+{
+       const char *p1 = strrchr(path1, '/');
+       const char *p2 = strrchr(path2, '/');
+       if (p1 - path1 != p2 - path2)
+               return false;
+       return memcmp(path1, path2,  p1 - path1) == 0;
+}
+
 /*
  * Makes a NTFS hard link
  *
@@ -156,21 +165,52 @@ static int wim_apply_hardlink_ntfs(const struct dentry *from_dentry,
                                   ntfs_inode **to_ni_ret)
 {
        int ret;
+       char *p;
+       char orig;
+       const char *dir_name;
+
        ntfs_inode *to_ni;
+       ntfs_volume *vol;
 
        wimlib_assert(dentry_is_regular_file(from_dentry)
                        && dentry_is_regular_file(to_dentry));
 
+       if (ntfs_inode_close(dir_ni) != 0) {
+               ERROR_WITH_ERRNO("Error closing directory");
+               return WIMLIB_ERR_NTFS_3G;
+       }
+
+       vol = dir_ni->vol;
+
        DEBUG("Extracting NTFS hard link `%s' => `%s'",
              from_dentry->full_path_utf8, to_dentry->extracted_file);
 
-       to_ni = ntfs_pathname_to_inode(dir_ni->vol, NULL,
+       to_ni = ntfs_pathname_to_inode(vol, NULL,
                                       to_dentry->extracted_file);
        if (!to_ni) {
                ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
                                 to_dentry->extracted_file);
                return WIMLIB_ERR_NTFS_3G;
        }
+       p = from_dentry->full_path_utf8 + from_dentry->full_path_utf8_len;
+       do {
+               p--;
+       } while (*p != '/');
+
+       orig = *p;
+       *p = '\0';
+       dir_name = from_dentry->full_path_utf8;
+
+       dir_ni = ntfs_pathname_to_inode(vol, NULL,
+                                       from_dentry->full_path_utf8);
+       if (!dir_ni) {
+               ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
+                                from_dentry->full_path_utf8);
+               *p = orig;
+               return WIMLIB_ERR_NTFS_3G;
+       }
+       *p = orig;
+
        ret = ntfs_link(to_ni, dir_ni,
                        (ntfschar*)from_dentry->file_name,
                        from_dentry->file_name_len / 2);
@@ -687,16 +727,6 @@ WIMLIBAPI int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image,
        if (ret != 0)
                return ret;
 
-#if 0
-       if (getuid() != 0) {
-               ERROR("We are not root, but NTFS-3g requires root privileges to set arbitrary");
-               ERROR("security data on the NTFS filesystem.  Please run this program as root");
-               ERROR("if you want to extract a WIM image while preserving NTFS-specific");
-               ERROR("information.");
-
-               return WIMLIB_ERR_NOT_ROOT;
-       }
-#endif
        return do_wim_apply_image_ntfs(w, device, flags);
 }
 
index 08868419b82dbf34b6c79cb60a6d49e331ea33fb..56e1c53995c37dbac6bffabcc4068cfdaeaddba1 100644 (file)
@@ -127,8 +127,8 @@ static int sd_set_add_sd(struct sd_set *sd_set, const u8 *descriptor,
        u64 *sizes;
        u8 *descr_copy;
        struct wim_security_data *sd;
-       sha1_buffer(descriptor, size, hash);
 
+       sha1_buffer(descriptor, size, hash);
        security_id = lookup_sd(hash, sd_set->root);
        if (security_id >= 0)
                return security_id;
@@ -268,7 +268,6 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                } else {
                        struct ntfs_location *ntfs_loc;
 
-
                        ntfs_loc = CALLOC(1, sizeof(*ntfs_loc));
                        if (!ntfs_loc)
                                goto out_put_actx;
@@ -285,6 +284,7 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                               actx->attr->name_length * 2);
 
                        ntfs_loc->stream_name_utf16_num_chars = actx->attr->name_length;
+                       ntfs_loc->is_reparse_point = (type == AT_REPARSE_POINT);
                        lte = new_lookup_table_entry();
                        if (!lte)
                                goto out_free_ntfs_loc;
@@ -296,7 +296,12 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                        lookup_table_insert(lookup_table, lte);
                }
                if (actx->attr->name_length == 0) {
-                       wimlib_assert(!dentry->lte);
+                       if (dentry->lte) {
+                               ERROR("Found two un-named data streams for "
+                                     "`%s'", path);
+                               ret = WIMLIB_ERR_NTFS_3G;
+                               goto out_free_lte;
+                       }
                        dentry->lte = lte;
                } else {
                        struct ads_entry *new_ads_entry;
@@ -305,8 +310,8 @@ static int capture_ntfs_streams(struct dentry *dentry, ntfs_inode *ni,
                                                         &stream_name_utf16_len);
                        if (!stream_name_utf8)
                                goto out_free_lte;
-                       FREE(stream_name_utf8);
                        new_ads_entry = dentry_add_ads(dentry, stream_name_utf8);
+                       FREE(stream_name_utf8);
                        if (!new_ads_entry)
                                goto out_free_lte;
                                
index 1e134f7ad29f7ae75ec44799e9f6b1f22f9c0a91..b2d26256a5c60d82f78747aa12db9ee3e456dfb0 100644 (file)
@@ -165,8 +165,6 @@ static const char *error_strings[] = {
                        "identify a WIM file",
        [WIMLIB_ERR_NO_FILENAME] 
                = "The WIM is not identified with a filename",
-       [WIMLIB_ERR_NOT_ROOT]
-               = "Root privileges are required for this operation",
        [WIMLIB_ERR_NTFS_3G]
                = "NTFS-3g encountered an error (check errno)",
        [WIMLIB_ERR_OPEN] 
index 928f2401b9bca5b06d03eaacedc5b57c163265a1..6d9eef48dc42a824d08470d605b381fad82a6eae 100644 (file)
@@ -322,7 +322,6 @@ enum wimlib_error_code {
        WIMLIB_ERR_NOMEM,
        WIMLIB_ERR_NOTDIR,
        WIMLIB_ERR_NOT_A_WIM_FILE,
-       WIMLIB_ERR_NOT_ROOT,
        WIMLIB_ERR_NO_FILENAME,
        WIMLIB_ERR_NTFS_3G,
        WIMLIB_ERR_OPEN,