#ifndef _WIMLIB_REPARSE_H #define _WIMLIB_REPARSE_H #include "wimlib/inode.h" /* for reparse tag definitions */ #include "wimlib/types.h" 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_DATA_OFFSET (offsetof(struct reparse_buffer_disk, rpdata)) #define REPARSE_DATA_MAX_SIZE (REPARSE_POINT_MAX_SIZE - REPARSE_DATA_OFFSET) static inline void check_reparse_buffer_disk(void) { BUILD_BUG_ON(offsetof(struct reparse_buffer_disk, rpdata) != 8); BUILD_BUG_ON(offsetof(struct reparse_buffer_disk, link.junction.data) != 16); BUILD_BUG_ON(offsetof(struct reparse_buffer_disk, link.symlink.data) != 20); BUILD_BUG_ON(sizeof(struct reparse_buffer_disk) != REPARSE_POINT_MAX_SIZE); } /* 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 { u32 rptag; u16 rpreserved; /* Flags, valid for symbolic links only */ u32 symlink_flags; /* Pointers to the substitute name and print name of the link, * potentially not null terminated */ utf16lechar *substitute_name; utf16lechar *print_name; /* 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_link_reparse_point(const struct reparse_buffer_disk *rpbuf, u16 rpbuflen, struct link_reparse_point *link); extern int make_link_reparse_point(const struct link_reparse_point *link, struct reparse_buffer_disk *rpbuf, u16 *rpbuflen_ret); #ifndef __WIN32__ 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 blob_table *blob_table); #endif #endif /* _WIMLIB_REPARSE_H */