#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;
-#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;
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;
};
-extern int
-parse_reparse_data(const u8 * restrict rpbuf, u16 rpbuflen,
- struct reparse_data * restrict rpdata);
+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
-make_reparse_buffer(const struct reparse_data * restrict rpdata,
- u8 * restrict rpbuf,
- u16 * restrict rpbuflen_ret);
+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,
- u16 * restrict rpbuflen_ret,
- struct wim_lookup_table_entry *lte_override);
+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 wim_lookup_table_entry *lte);
+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
#endif /* _WIMLIB_REPARSE_H */