From: Eric Biggers Date: Fri, 17 May 2013 19:03:59 +0000 (-0500) Subject: ntfs-3g_apply.c: Use wim_inode_get_reparse_data() X-Git-Tag: v1.4.0~23 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=f2f293a1759c81e7bd5deb904c3909368f3feaa5 ntfs-3g_apply.c: Use wim_inode_get_reparse_data() --- diff --git a/include/wimlib/reparse.h b/include/wimlib/reparse.h index dd07949f..ff422a1d 100644 --- a/include/wimlib/reparse.h +++ b/include/wimlib/reparse.h @@ -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 diff --git a/src/ntfs-3g_apply.c b/src/ntfs-3g_apply.c index 0ec4702f..dde9a1db 100644 --- a/src/ntfs-3g_apply.c +++ b/src/ntfs-3g_apply.c @@ -43,7 +43,7 @@ #include #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); diff --git a/src/reparse.c b/src/reparse.c index 9ec264d5..446b6f9f 100644 --- a/src/reparse.c +++ b/src/reparse.c @@ -45,6 +45,25 @@ #include #include +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; } diff --git a/src/win32_apply.c b/src/win32_apply.c index 272a1dda..c91315cf 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -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 */))