X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=include%2Fwimlib%2Freparse.h;h=dce19a22130087ec1cc9475a88b060aab513dbdb;hp=dd07949faac9151929c6e5c288b03b25ac23ba6e;hb=5e3d0c732c29487e19c36110cdc4fb8d5ffe46ad;hpb=5b81e7556e33e4af42dc1e07eb36f830ca0c4db3 diff --git a/include/wimlib/reparse.h b/include/wimlib/reparse.h index dd07949f..dce19a22 100644 --- a/include/wimlib/reparse.h +++ b/include/wimlib/reparse.h @@ -1,81 +1,112 @@ #ifndef _WIMLIB_REPARSE_H #define _WIMLIB_REPARSE_H +#include "wimlib/inode.h" /* for reparse tag definitions */ #include "wimlib/types.h" -struct wim_inode; -struct wim_lookup_table; +struct blob_descriptor; +struct blob_table; + +/* Windows enforces this limit on the size of a reparse point buffer. */ +#define REPARSE_POINT_MAX_SIZE 16384 + +/* + * 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; + le16 rpreserved; + union { + u8 rpdata[REPARSE_POINT_MAX_SIZE - 8]; + + struct { + le16 substitute_name_offset; + le16 substitute_name_nbytes; + le16 print_name_offset; + le16 print_name_nbytes; + + 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; + }; +}; -#define REPARSE_POINT_MAX_SIZE (16 * 1024) +#define REPARSE_DATA_OFFSET ((unsigned)offsetof(struct reparse_buffer_disk, rpdata)) -/* 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; +#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); +} - /* 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; }; -enum { - SUBST_NAME_IS_RELATIVE_LINK = -1, - SUBST_NAME_IS_VOLUME_JUNCTION = -2, - SUBST_NAME_IS_UNKNOWN = -3, -}; -extern int -parse_substitute_name(const utf16lechar *substitute_name, - u16 substitute_name_nbytes, - u32 rptag); +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 int -parse_reparse_data(const u8 * restrict rpbuf, u16 rpbuflen, - struct reparse_data * restrict rpdata); +extern void +complete_reparse_point(struct reparse_buffer_disk *rpbuf, + const struct wim_inode *inode, u16 blob_size); extern int -make_reparse_buffer(const struct reparse_data * restrict rpdata, - u8 * restrict rpbuf); +parse_link_reparse_point(const struct reparse_buffer_disk *rpbuf, u16 rpbuflen, + struct link_reparse_point *link); extern int -wim_inode_get_reparse_data(const struct wim_inode * restrict inode, - u8 * restrict rpbuf); +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); +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, - struct wim_lookup_table *lookup_table); + struct blob_table *blob_table); #endif -extern tchar * -capture_fixup_absolute_symlink(tchar *dest, - u64 capture_root_ino, u64 capture_root_dev); - #endif /* _WIMLIB_REPARSE_H */