ntfs-3g_apply.c: Use wim_inode_get_reparse_data()
authorEric Biggers <ebiggers3@gmail.com>
Fri, 17 May 2013 19:03:59 +0000 (14:03 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Fri, 17 May 2013 19:03:59 +0000 (14:03 -0500)
include/wimlib/reparse.h
src/ntfs-3g_apply.c
src/reparse.c
src/win32_apply.c

index dd07949..ff422a1 100644 (file)
@@ -62,7 +62,8 @@ make_reparse_buffer(const struct reparse_data * restrict rpdata,
 
 extern int
 wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
-                          u8 * restrict rpbuf);
+                          u8 * restrict rpbuf,
+                          u16 * restrict rpbuflen_ret);
 
 #ifndef __WIN32__
 ssize_t
index 0ec4702..dde9a1d 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"
@@ -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;
 }
 
 /*
@@ -647,8 +624,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 +637,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);
index 9ec264d..446b6f9 100644 (file)
 #include <errno.h>
 #include <stdlib.h>
 
+struct reparse_buffer_disk {
+       le32 rptag;
+       le16 rpdatalen;
+       le16 rpreserved;
+       le16 substitute_name_offset;
+       le16 substitute_name_nbytes;
+       le16 print_name_offset;
+       le16 print_name_nbytes;
+       union {
+               struct {
+                       le32 rpflags;
+                       u8 data[REPARSE_POINT_MAX_SIZE - 20];
+               } _packed_attribute symlink;
+               struct {
+                       u8 data[REPARSE_POINT_MAX_SIZE - 16];
+               } _packed_attribute junction;
+       };
+} _packed_attribute;
+
 static const utf16lechar volume_junction_prefix[11] = {
        cpu_to_le16('\\'),
        cpu_to_le16('\\'),
@@ -125,25 +144,6 @@ parse_substitute_name(const utf16lechar *substitute_name,
        }
 }
 
-struct reparse_buffer_disk {
-       le32 rptag;
-       le16 rpdatalen;
-       le16 rpreserved;
-       le16 substitute_name_offset;
-       le16 substitute_name_nbytes;
-       le16 print_name_offset;
-       le16 print_name_nbytes;
-       union {
-               struct {
-                       le32 rpflags;
-                       u8 data[REPARSE_POINT_MAX_SIZE - 20];
-               } _packed_attribute symlink;
-               struct {
-                       u8 data[REPARSE_POINT_MAX_SIZE - 16];
-               } _packed_attribute junction;
-       };
-} _packed_attribute;
-
 /*
  * Read the data from a symbolic link, junction, or mount point reparse point
  * buffer into a `struct reparse_data'.
@@ -267,11 +267,13 @@ make_reparse_buffer(const struct reparse_data * restrict rpdata,
  */
 int
 wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
-                          u8 * restrict rpbuf)
+                          u8 * restrict rpbuf,
+                          u16 * restrict rpbuflen_ret)
 {
        struct wim_lookup_table_entry *lte;
        int ret;
        struct reparse_buffer_disk *rpbuf_disk;
+       u16 rpdatalen;
 
        wimlib_assert(inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT);
 
@@ -280,10 +282,12 @@ wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
                ERROR("Reparse point has no reparse data!");
                return WIMLIB_ERR_INVALID_REPARSE_DATA;
        }
+
        if (wim_resource_size(lte) > REPARSE_POINT_MAX_SIZE - 8) {
                ERROR("Reparse data is too long!");
                return WIMLIB_ERR_INVALID_REPARSE_DATA;
        }
+       rpdatalen = wim_resource_size(lte);
 
        /* Read the data from the WIM file */
        ret = read_full_resource_into_buf(lte, rpbuf + 8);
@@ -297,11 +301,13 @@ wim_inode_get_reparse_data(const struct wim_inode * restrict inode,
        rpbuf_disk->rptag = cpu_to_le32(inode->i_reparse_tag);
 
        /* ReparseDataLength */
-       rpbuf_disk->rpdatalen = cpu_to_le16(wim_resource_size(lte));
+       rpbuf_disk->rpdatalen = cpu_to_le16(rpdatalen);
 
        /* ReparseReserved
         * XXX this could be one of the unknown fields in the WIM dentry. */
        rpbuf_disk->rpreserved = cpu_to_le16(0);
+
+       *rpbuflen_ret = rpdatalen + 8;
        return 0;
 }
 
@@ -321,19 +327,18 @@ wim_inode_readlink(const struct wim_inode * restrict inode,
 {
        int ret;
        struct reparse_buffer_disk rpbuf_disk _aligned_attribute(8);
-       u16 rpdatalen;
        struct reparse_data rpdata;
        char *link_target;
        char *translated_target;
        size_t link_target_len;
+       u16 rpbuflen;
 
        wimlib_assert(inode_is_symlink(inode));
 
-       if (wim_inode_get_reparse_data(inode, (u8*)&rpbuf_disk))
+       if (wim_inode_get_reparse_data(inode, (u8*)&rpbuf_disk, &rpbuflen))
                return -EIO;
 
-       if (parse_reparse_data((const u8*)&rpbuf_disk,
-                              le16_to_cpu(rpbuf_disk.rpdatalen) + 8, &rpdata))
+       if (parse_reparse_data((const u8*)&rpbuf_disk, rpbuflen, &rpdata))
                return -EIO;
 
        ret = utf16le_to_tstr(rpdata.substitute_name,
@@ -354,7 +359,8 @@ wim_inode_readlink(const struct wim_inode * restrict inode,
        case SUBST_NAME_IS_UNKNOWN:
                ERROR("Can't understand reparse point "
                      "substitute name \"%s\"", link_target);
-               return -EIO;
+               ret = -EIO;
+               goto out_free_link_target;
        default:
                translated_target += ret;
                link_target_len -= ret;
@@ -373,6 +379,7 @@ out_have_link:
                ret = link_target_len;
        }
        memcpy(buf, translated_target, link_target_len);
+out_free_link_target:
        FREE(link_target);
        return ret;
 }
index 272a1dd..c91315c 100644 (file)
@@ -153,10 +153,11 @@ win32_set_reparse_data(HANDLE h,
        int ret;
        u8 rpbuf[REPARSE_POINT_MAX_SIZE];
        DWORD bytesReturned;
+       u16 rpbuflen;
 
        DEBUG("Setting reparse data on \"%ls\"", path);
 
-       ret = wim_inode_get_reparse_data(inode, rpbuf);
+       ret = wim_inode_get_reparse_data(inode, rpbuf, &rpbuflen);
        if (ret)
                return ret;
 
@@ -194,7 +195,7 @@ win32_set_reparse_data(HANDLE h,
         *  "Not used with this operation; set to NULL."
         */
        if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, rpbuf,
-                            8 + le16_to_cpu(*(u16*)(rpbuf + 4)),
+                            rpbuflen,
                             NULL, 0,
                             &bytesReturned /* lpBytesReturned */,
                             NULL /* lpOverlapped */))