X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=include%2Fwimlib%2Freparse.h;h=dce19a22130087ec1cc9475a88b060aab513dbdb;hp=43adbd5c87406913f300131b1c03feadebf0fbfa;hb=37d9c3935130128901f6eee8d7531d8ae4b1bca6;hpb=3de1ec66f778edda19865482d685bc6f4e17faf7 diff --git a/include/wimlib/reparse.h b/include/wimlib/reparse.h index 43adbd5c..dce19a22 100644 --- a/include/wimlib/reparse.h +++ b/include/wimlib/reparse.h @@ -1,17 +1,22 @@ #ifndef _WIMLIB_REPARSE_H #define _WIMLIB_REPARSE_H -#include - +#include "wimlib/inode.h" /* for reparse tag definitions */ #include "wimlib/types.h" -struct wim_inode; -struct blob_table; struct blob_descriptor; +struct blob_table; -#define REPARSE_POINT_MAX_SIZE (16 * 1024) +/* Windows enforces this limit on the size of a reparse point buffer. */ +#define REPARSE_POINT_MAX_SIZE 16384 -/* On-disk format of reparse point buffer */ +/* + * On-disk format of a reparse point buffer. See: + * https://msdn.microsoft.com/en-us/library/dd541671.aspx + * + * Note: we are not using _packed_attribute for this structure, so only cast to + * this if properly aligned! + */ struct reparse_buffer_disk { le32 rptag; le16 rpdatalen; @@ -24,72 +29,80 @@ struct reparse_buffer_disk { le16 substitute_name_nbytes; le16 print_name_offset; le16 print_name_nbytes; - le32 rpflags; - u8 data[REPARSE_POINT_MAX_SIZE - 20]; - } _packed_attribute symlink; - struct { - le16 substitute_name_offset; - le16 substitute_name_nbytes; - le16 print_name_offset; - le16 print_name_nbytes; - u8 data[REPARSE_POINT_MAX_SIZE - 16]; - } _packed_attribute junction; + union { + struct { + u8 data[REPARSE_POINT_MAX_SIZE - 16]; + } junction; + + struct { + le32 flags; + #define SYMBOLIC_LINK_RELATIVE 0x00000001 + u8 data[REPARSE_POINT_MAX_SIZE - 20]; + } symlink; + }; + } link; }; -} _packed_attribute; +}; -#define REPARSE_DATA_OFFSET (offsetof(struct reparse_buffer_disk, rpdata)) +#define REPARSE_DATA_OFFSET ((unsigned)offsetof(struct reparse_buffer_disk, rpdata)) #define REPARSE_DATA_MAX_SIZE (REPARSE_POINT_MAX_SIZE - REPARSE_DATA_OFFSET) +static _unused_attribute void +check_reparse_buffer_disk(void) +{ + STATIC_ASSERT(offsetof(struct reparse_buffer_disk, rpdata) == 8); + STATIC_ASSERT(offsetof(struct reparse_buffer_disk, link.junction.data) == 16); + STATIC_ASSERT(offsetof(struct reparse_buffer_disk, link.symlink.data) == 20); + STATIC_ASSERT(sizeof(struct reparse_buffer_disk) == REPARSE_POINT_MAX_SIZE); +} -/* Structured format for symbolic link, junction point, or mount point reparse - * data. */ -struct reparse_data { - /* Reparse point tag (see WIM_IO_REPARSE_TAG_* values) */ - u32 rptag; - - /* Length of reparse data, not including the 8-byte header (ReparseTag, - * ReparseDataLength, ReparseReserved) */ - u16 rpdatalen; +/* Wrapper around a symbolic link or junction reparse point + * (WIM_IO_REPARSE_TAG_SYMLINK or WIM_IO_REPARSE_TAG_MOUNT_POINT) */ +struct link_reparse_point { - /* ReparseReserved */ + u32 rptag; u16 rpreserved; - /* Flags (only for WIM_IO_REPARSE_TAG_SYMLINK reparse points). - * SYMBOLIC_LINK_RELATIVE means this is a relative symbolic link; - * otherwise should be set to 0. */ -#define SYMBOLIC_LINK_RELATIVE 0x00000001 - u32 rpflags; + /* Flags, valid for symbolic links only */ + u32 symlink_flags; - /* Pointer to the substitute name of the link (UTF-16LE). */ + /* Pointers to the substitute name and print name of the link, + * potentially not null terminated */ utf16lechar *substitute_name; - - /* Pointer to the print name of the link (UTF-16LE). */ utf16lechar *print_name; - /* Number of bytes of the substitute name, not including null terminator - * if present */ - u16 substitute_name_nbytes; - - /* Number of bytes of the print name, not including null terminator if - * present */ - u16 print_name_nbytes; + /* Lengths of the substitute and print names in bytes, not including + * their null terminators if present */ + size_t substitute_name_nbytes; + size_t print_name_nbytes; }; +static inline bool +link_is_relative_symlink(const struct link_reparse_point *link) +{ + return link->rptag == WIM_IO_REPARSE_TAG_SYMLINK && + (link->symlink_flags & SYMBOLIC_LINK_RELATIVE); +} + +extern void +complete_reparse_point(struct reparse_buffer_disk *rpbuf, + const struct wim_inode *inode, u16 blob_size); + extern int -parse_reparse_data(const u8 * restrict rpbuf, u16 rpbuflen, - struct reparse_data * restrict rpdata); +parse_link_reparse_point(const struct reparse_buffer_disk *rpbuf, u16 rpbuflen, + struct link_reparse_point *link); extern int -make_reparse_buffer(const struct reparse_data * restrict rpdata, - u8 * restrict rpbuf, - u16 * restrict rpbuflen_ret); +make_link_reparse_point(const struct link_reparse_point *link, + struct reparse_buffer_disk *rpbuf, u16 *rpbuflen_ret); #ifndef __WIN32__ -ssize_t -wim_inode_readlink(const struct wim_inode * restrict inode, char * restrict buf, - size_t buf_len, struct blob_descriptor *blob); +extern int +wim_inode_readlink(const struct wim_inode *inode, char *buf, size_t bufsize, + const struct blob_descriptor *blob, + const char *altroot, size_t altroot_len); extern int wim_inode_set_symlink(struct wim_inode *inode, const char *target,