]> wimlib.net Git - wimlib/blobdiff - src/ntfs-3g_apply.c
w -> wim
[wimlib] / src / ntfs-3g_apply.c
index 0ec4702fc736f859b2b552641e5e8d3fc64c0ce8..a8292c7e2432c90da4b8d6c919e1a50fbf9c6dfa 100644 (file)
@@ -43,7 +43,7 @@
 #include <ntfs-3g/xattrs.h>
 
 #include "wimlib/apply.h"
-#include "wimlib/buffer_io.h"
+#include "wimlib/compiler.h"
 #include "wimlib/dentry.h"
 #include "wimlib/encoding.h"
 #include "wimlib/error.h"
@@ -291,7 +291,7 @@ apply_ntfs_hardlink(struct wim_dentry *from_dentry,
  * @ni:             The NTFS inode to apply the metadata to.
  * @dir_ni:  The NTFS inode for a directory containing @ni.
  * @dentry:  The WIM dentry whose inode contains the metadata to apply.
- * @w:       The WIMStruct for the WIM, through which the table of security
+ * @wim:       The WIMStruct for the WIM, through which the table of security
  *             descriptors can be accessed.
  *
  * Returns 0 on success, nonzero on failure.
@@ -300,12 +300,12 @@ static int
 apply_file_attributes_and_security_data(ntfs_inode *ni,
                                        ntfs_inode *dir_ni,
                                        struct wim_dentry *dentry,
-                                       const WIMStruct *w,
+                                       const WIMStruct *wim,
                                        int extract_flags)
 {
        int ret;
        struct SECURITY_CONTEXT ctx;
-       u32 attributes_le32;
+       le32 attributes;
        const struct wim_inode *inode;
 
        inode = dentry->d_inode;
@@ -313,13 +313,13 @@ apply_file_attributes_and_security_data(ntfs_inode *ni,
        DEBUG("Setting NTFS file attributes on `%s' to %#"PRIx32,
              dentry->_full_path, inode->i_attributes);
 
-       attributes_le32 = cpu_to_le32(inode->i_attributes);
+       attributes = cpu_to_le32(inode->i_attributes);
        memset(&ctx, 0, sizeof(ctx));
        ctx.vol = ni->vol;
        ret = ntfs_xattr_system_setxattr(&ctx, XATTR_NTFS_ATTRIB,
                                         ni, dir_ni,
-                                        (const char*)&attributes_le32,
-                                        sizeof(u32), 0);
+                                        (char*)&attributes,
+                                        sizeof(attributes), 0);
        if (ret) {
                ERROR("Failed to set NTFS file attributes on `%s'",
                      dentry->_full_path);
@@ -330,7 +330,7 @@ apply_file_attributes_and_security_data(ntfs_inode *ni,
                const char *desc;
                const struct wim_security_data *sd;
 
-               sd = wim_const_security_data(w);
+               sd = wim_const_security_data(wim);
                wimlib_assert(inode->i_security_id < sd->num_entries);
                desc = (const char *)sd->descriptors[inode->i_security_id];
                DEBUG("Applying security descriptor %d to `%s'",
@@ -357,48 +357,25 @@ static int
 apply_reparse_data(ntfs_inode *ni, struct wim_dentry *dentry,
                   union wimlib_progress_info *progress_info)
 {
-       struct wim_lookup_table_entry *lte;
        int ret;
-
-       lte = inode_unnamed_lte_resolved(dentry->d_inode);
+       u8 rpbuf[REPARSE_POINT_MAX_SIZE] _aligned_attribute(8);
+       u16 rpbuflen;
 
        DEBUG("Applying reparse data to `%s'", dentry->_full_path);
 
-       if (!lte) {
-               ERROR("Could not find reparse data for `%s'",
-                     dentry->_full_path);
-               return WIMLIB_ERR_INVALID_DENTRY;
-       }
-
-       /* "Reparse point data, including the tag and optional GUID, cannot
-        * exceed 16 kilobytes." - MSDN  */
-       if (wim_resource_size(lte) > REPARSE_POINT_MAX_SIZE - 8) {
-               ERROR("Reparse data of `%s' is too long (%"PRIu64" bytes)",
-                     dentry->_full_path, wim_resource_size(lte));
-               return WIMLIB_ERR_INVALID_DENTRY;
-       }
-
-       u8 reparse_data_buf[8 + wim_resource_size(lte)];
-       u8 *p = reparse_data_buf;
-       p = put_u32(p, dentry->d_inode->i_reparse_tag); /* ReparseTag */
-       DEBUG("ReparseTag = %#x", dentry->d_inode->i_reparse_tag);
-       p = put_u16(p, wim_resource_size(lte)); /* ReparseDataLength */
-       p = put_u16(p, 0); /* Reserved */
-
-       ret = read_full_resource_into_buf(lte, p);
+       ret = wim_inode_get_reparse_data(dentry->d_inode, rpbuf, &rpbuflen);
        if (ret)
                return ret;
 
-       ret = ntfs_set_ntfs_reparse_data(ni, (char*)reparse_data_buf,
-                                        wim_resource_size(lte) + 8, 0);
+       ret = ntfs_set_ntfs_reparse_data(ni, rpbuf, rpbuflen, 0);
        if (ret) {
                ERROR_WITH_ERRNO("Failed to set NTFS reparse data on `%s'",
                                 dentry->_full_path);
                return WIMLIB_ERR_NTFS_3G;
-       } else {
-               progress_info->extract.completed_bytes += wim_resource_size(lte);
        }
-       return ret;
+
+       progress_info->extract.completed_bytes += rpbuflen - 8;
+       return 0;
 }
 
 /*
@@ -469,7 +446,7 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
        }
 
        ret = apply_file_attributes_and_security_data(ni, dir_ni, dentry,
-                                                     args->w,
+                                                     args->wim,
                                                      args->extract_flags);
        if (ret)
                goto out_close_dir_ni;
@@ -481,7 +458,8 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
        }
 
        /* Set DOS (short) name if given */
-       if (dentry_has_short_name(dentry)) {
+       if (dentry_has_short_name(dentry) && !dentry->dos_name_invalid)
+       {
                char *short_name_mbs;
                size_t short_name_mbs_nbytes;
                ret = utf16le_to_tstr(dentry->short_name,
@@ -498,9 +476,9 @@ do_apply_dentry_ntfs(struct wim_dentry *dentry, ntfs_inode *dir_ni,
                                             short_name_mbs_nbytes, 0);
                FREE(short_name_mbs);
                if (ret) {
-                       ERROR_WITH_ERRNO("Could not set DOS (short) name for `%s'",
-                                        dentry->_full_path);
-                       ret = WIMLIB_ERR_NTFS_3G;
+                       WARNING_WITH_ERRNO("Could not set DOS (short) name for `%s'",
+                                          dentry->_full_path);
+                       ret = 0;
                }
                /* inodes have been closed by ntfs_set_ntfs_dos_name(). */
                goto out;
@@ -529,18 +507,22 @@ out:
 
 static int
 apply_root_dentry_ntfs(struct wim_dentry *dentry,
-                      ntfs_volume *vol, const WIMStruct *w,
+                      ntfs_volume *vol, const WIMStruct *wim,
                       int extract_flags)
 {
        ntfs_inode *ni;
        int ret = 0;
 
+       ret = calculate_dentry_full_path(dentry);
+       if (ret)
+               return ret;
+
        ni = ntfs_pathname_to_inode(vol, NULL, "/");
        if (!ni) {
                ERROR_WITH_ERRNO("Could not find root NTFS inode");
                return WIMLIB_ERR_NTFS_3G;
        }
-       ret = apply_file_attributes_and_security_data(ni, ni, dentry, w,
+       ret = apply_file_attributes_and_security_data(ni, ni, dentry, wim,
                                                      extract_flags);
        if (ntfs_inode_close(ni) != 0) {
                ERROR_WITH_ERRNO("Failed to close NTFS inode for root "
@@ -556,14 +538,14 @@ apply_dentry_ntfs(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
        ntfs_volume *vol = args->vol;
-       WIMStruct *w = args->w;
+       WIMStruct *wim = args->wim;
        struct wim_dentry *orig_dentry;
        struct wim_dentry *other;
        int ret;
 
        /* Treat the root dentry specially. */
        if (dentry_is_root(dentry))
-               return apply_root_dentry_ntfs(dentry, vol, w,
+               return apply_root_dentry_ntfs(dentry, vol, wim,
                                              args->extract_flags);
 
        /* NTFS filename namespaces need careful consideration.  A name for a
@@ -616,10 +598,10 @@ apply_dentry_ntfs(struct wim_dentry *dentry, void *arg)
 again:
        orig_dentry = NULL;
        if (!dentry->d_inode->i_dos_name_extracted &&
-           !dentry_has_short_name(dentry))
+           (!dentry_has_short_name(dentry) || dentry->dos_name_invalid))
        {
                inode_for_each_dentry(other, dentry->d_inode) {
-                       if (dentry_has_short_name(other)) {
+                       if (dentry_has_short_name(other) && !other->dos_name_invalid) {
                                orig_dentry = dentry;
                                dentry = other;
                                break;
@@ -627,6 +609,11 @@ again:
                }
        }
        dentry->d_inode->i_dos_name_extracted = 1;
+
+       ret = calculate_dentry_full_path(dentry);
+       if (ret)
+               return ret;
+
        ntfs_inode *dir_ni = dentry_open_parent_ni(dentry, vol);
        if (dir_ni) {
                ret = do_apply_dentry_ntfs(dentry, dir_ni, arg);
@@ -647,8 +634,7 @@ apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg)
 {
        struct apply_args *args = arg;
        ntfs_volume *vol = args->vol;
-       u8 *p;
-       u8 buf[24];
+       u64 ntfs_timestamps[3];
        ntfs_inode *ni;
        int ret;
 
@@ -661,11 +647,13 @@ apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg)
                return WIMLIB_ERR_NTFS_3G;
        }
 
-       p = buf;
-       p = put_u64(p, dentry->d_inode->i_creation_time);
-       p = put_u64(p, dentry->d_inode->i_last_write_time);
-       p = put_u64(p, dentry->d_inode->i_last_access_time);
-       ret = ntfs_inode_set_times(ni, (const char*)buf, 3 * sizeof(u64), 0);
+       /* Note: ntfs_inode_set_times() expects the times in native byte order,
+        * not little endian. */
+       ntfs_timestamps[0] = dentry->d_inode->i_creation_time;
+       ntfs_timestamps[1] = dentry->d_inode->i_last_write_time;
+       ntfs_timestamps[2] = dentry->d_inode->i_last_access_time;
+       ret = ntfs_inode_set_times(ni, (const char*)ntfs_timestamps,
+                                  sizeof(ntfs_timestamps), 0);
        if (ret != 0) {
                ERROR_WITH_ERRNO("Failed to set NTFS timestamps on `%s'",
                                 dentry->_full_path);