]> wimlib.net Git - wimlib/blob - include/wimlib/xattr.h
mount_image.c: add fallback definitions of RENAME_* constants
[wimlib] / include / wimlib / xattr.h
1 #ifndef _WIMLIB_XATTR_H
2 #define _WIMLIB_XATTR_H
3
4 #include <string.h>
5
6 #include "wimlib/endianness.h"
7 #include "wimlib/tagged_items.h"
8 #include "wimlib/util.h"
9
10 #undef HAVE_LINUX_XATTR_SUPPORT
11 #if defined(HAVE_SYS_XATTR_H) && \
12         defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) && \
13         defined(HAVE_FSETXATTR) && defined(HAVE_LSETXATTR)
14 #  define HAVE_LINUX_XATTR_SUPPORT 1
15 #endif
16
17 #define WIM_XATTR_NAME_MAX 255
18 #define WIM_XATTR_SIZE_MAX 65535
19
20 /*
21  * On-disk format of each extended attribute (xattr, or EA) entry in a metadata
22  * item tagged with TAG_XATTRS.  This is the preferred xattr format, since it is
23  * also used by WIMGAPI and DISM starting in Windows 10 version 1607.
24  */
25 struct wim_xattr_entry {
26
27         /* length of xattr value in bytes */
28         le16 value_len;
29
30         /* length of xattr name in bytes, excluding the null terminator */
31         u8 name_len;
32
33         /* flags: 0 or 0x80 (FILE_NEED_EA) */
34         u8 flags;
35
36         /* followed by the xattr name *with* a null terminator */
37         char name[0];
38
39         /* followed by the xattr value */
40         /* u8 value[0]; */
41
42         /* no padding at end! */
43 } _packed_attribute;
44
45 static inline size_t
46 xattr_entry_size(const struct wim_xattr_entry *entry)
47 {
48         STATIC_ASSERT(sizeof(*entry) == 4);
49
50         return sizeof(*entry) + entry->name_len + 1 +
51                 le16_to_cpu(entry->value_len);
52 }
53
54 /* minimum is a 1-byte name (plus null terminator) and an empty value */
55 #define XATTR_ENTRY_MIN_SIZE (sizeof(struct wim_xattr_entry) + 2)
56
57 static inline struct wim_xattr_entry *
58 xattr_entry_next(const struct wim_xattr_entry *entry)
59 {
60         return (void *)entry + xattr_entry_size(entry);
61 }
62
63 static inline bool
64 valid_xattr_entry(const struct wim_xattr_entry *entry, size_t avail)
65 {
66         if (avail < sizeof(*entry))
67                 return false;
68
69         return entry->name_len > 0 && entry->name_len <= WIM_XATTR_NAME_MAX &&
70                 le16_to_cpu(entry->value_len) <= WIM_XATTR_SIZE_MAX &&
71                 avail >= xattr_entry_size(entry) &&
72                 memchr(entry->name, '\0', entry->name_len) == NULL &&
73                 entry->name[entry->name_len] == '\0';
74 }
75
76 /*
77  * On-disk format of each extended attribute entry in a metadata item tagged
78  * with TAG_WIMLIB_LINUX_XATTRS.  This is a deprecated format which wimlib
79  * v1.11-v1.12 used to store extended attributes on Linux (predating the Windows
80  * xattr support in both WIMGAPI and wimlib).  Now we use TAG_XATTRS for both
81  * Windows and Linux xattrs.
82  */
83 struct wimlib_xattr_entry_old {
84
85         /* length of xattr name in bytes, excluding a null terminator */
86         le16 name_len;
87
88         /* reserved, must be 0 */
89         le16 reserved;
90
91         /* length of xattr value in bytes */
92         le32 value_len;
93
94         /* followed by the xattr name *without* a null terminator */
95         char name[0];
96
97         /* followed by the xattr value */
98         /* u8 value[0]; */
99
100         /* then zero-padded to a 4-byte boundary */
101 } _aligned_attribute(4);
102
103 static inline size_t
104 old_xattr_entry_size(const struct wimlib_xattr_entry_old *entry)
105 {
106         STATIC_ASSERT(sizeof(*entry) == 8);
107
108         return ALIGN(sizeof(*entry) + le16_to_cpu(entry->name_len) +
109                      le32_to_cpu(entry->value_len), 4);
110 }
111
112 /* minimum is a 1-byte name and an empty value */
113 #define OLD_XATTR_ENTRY_MIN_SIZE \
114         (ALIGN(sizeof(struct wimlib_xattr_entry_old) + 1, 4))
115
116 static inline struct wimlib_xattr_entry_old *
117 old_xattr_entry_next(const struct wimlib_xattr_entry_old *entry)
118 {
119         return (void *)entry + old_xattr_entry_size(entry);
120 }
121
122 static inline bool
123 old_valid_xattr_entry(const struct wimlib_xattr_entry_old *entry, size_t avail)
124 {
125         u16 name_len;
126
127         if (avail < sizeof(*entry))
128                 return false;
129
130         name_len = le16_to_cpu(entry->name_len);
131         return name_len > 0 && name_len <= WIM_XATTR_NAME_MAX &&
132                 le32_to_cpu(entry->value_len) <= WIM_XATTR_SIZE_MAX &&
133                 avail >= old_xattr_entry_size(entry) &&
134                 memchr(entry->name, '\0', name_len) == NULL;
135 }
136
137 /* Is the xattr of the specified name security-related on Linux? */
138 static inline bool
139 is_linux_security_xattr(const char *name)
140 {
141 #define XATTR_SECURITY_PREFIX "security."
142 #define XATTR_SYSTEM_PREFIX "system."
143 #define XATTR_POSIX_ACL_ACCESS  "posix_acl_access"
144 #define XATTR_NAME_POSIX_ACL_ACCESS XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_ACCESS
145 #define XATTR_POSIX_ACL_DEFAULT  "posix_acl_default"
146 #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
147
148         return !strncmp(name, XATTR_SECURITY_PREFIX,
149                         sizeof(XATTR_SECURITY_PREFIX) - 1) ||
150                !strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
151                !strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT);
152 }
153
154 static inline const void *
155 inode_get_xattrs(const struct wim_inode *inode, u32 *len_ret)
156 {
157         return inode_get_tagged_item(inode, TAG_XATTRS,
158                                      XATTR_ENTRY_MIN_SIZE, len_ret);
159 }
160
161 static inline const void *
162 inode_get_xattrs_old(const struct wim_inode *inode, u32 *len_ret)
163 {
164         return inode_get_tagged_item(inode, TAG_WIMLIB_LINUX_XATTRS,
165                                      OLD_XATTR_ENTRY_MIN_SIZE, len_ret);
166 }
167
168 static inline const void *
169 inode_get_linux_xattrs(const struct wim_inode *inode, u32 *len_ret,
170                        bool *is_old_format_ret)
171 {
172         const void *entries;
173
174         entries = inode_get_xattrs(inode, len_ret);
175         if (entries) {
176                 *is_old_format_ret = false;
177                 return entries;
178         }
179         entries = inode_get_xattrs_old(inode, len_ret);
180         if (entries) {
181                 *is_old_format_ret = true;
182                 return entries;
183         }
184         return NULL;
185 }
186
187 static inline bool
188 inode_has_xattrs(const struct wim_inode *inode)
189 {
190         return inode_get_xattrs(inode, NULL) != NULL ||
191                inode_get_xattrs_old(inode, NULL) != NULL;
192 }
193
194 static inline bool
195 inode_set_xattrs(struct wim_inode *inode, const void *entries, u32 len)
196 {
197         return inode_set_tagged_item(inode, TAG_XATTRS, entries, len);
198 }
199
200 #endif /* _WIMLIB_XATTR_H  */