Add basic infrastructure for storing xattr items
[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_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_XATTR_SUPPORT 1
15 #endif
16
17 /*
18  * On-disk format of an entry in an extended attributes tagged item (wimlib
19  * extension).  An xattr item consists of a series of variable-length xattr
20  * name/value pairs, each of which begins with this header.
21  *
22  * Currently this is only used for Linux-style xattrs, but in the future we may
23  * use this for Windows-style xattrs too.
24  */
25 struct wimlib_xattr_entry {
26
27         /* length of xattr name in bytes */
28         le16 name_len;
29
30         /* reserved, must be 0 */
31         le16 reserved;
32
33         /* length of xattr value in bytes */
34         le32 value_len;
35
36         /* followed by the xattr name with no terminating null */
37         char name[0];
38
39         /* followed by the xattr value with no terminating null */
40         /* u8 value[0]; */
41
42         /* then zero-padded to a 4-byte boundary */
43 } _aligned_attribute(4);
44
45 static inline size_t
46 xattr_entry_size(const struct wimlib_xattr_entry *entry)
47 {
48         return ALIGN(sizeof(*entry) + le16_to_cpu(entry->name_len) +
49                      le32_to_cpu(entry->value_len), 4);
50 }
51
52 static inline struct wimlib_xattr_entry *
53 xattr_entry_next(const struct wimlib_xattr_entry *entry)
54 {
55         return (void *)entry + xattr_entry_size(entry);
56 }
57
58 /* Currently we use the Linux limits when validating xattr names and values */
59 #define XATTR_NAME_MAX 255
60 #define XATTR_SIZE_MAX 65536
61
62 static inline bool
63 valid_xattr_entry(const struct wimlib_xattr_entry *entry, size_t avail)
64 {
65         if (avail < sizeof(*entry))
66                 return false;
67
68         if (entry->name_len == 0 ||
69             le16_to_cpu(entry->name_len) > XATTR_NAME_MAX)
70                 return false;
71
72         if (entry->reserved != 0)
73                 return false;
74
75         if (le32_to_cpu(entry->value_len) > XATTR_SIZE_MAX)
76                 return false;
77
78         if (avail < xattr_entry_size(entry))
79                 return false;
80
81         if (memchr(entry->name, '\0', le16_to_cpu(entry->name_len)))
82                 return false;
83
84         return true;
85 }
86
87 /* Is the xattr of the specified name security-related? */
88 static inline bool
89 is_security_xattr(const char *name)
90 {
91 #define XATTR_SECURITY_PREFIX "security."
92 #define XATTR_SYSTEM_PREFIX "system."
93 #define XATTR_POSIX_ACL_ACCESS  "posix_acl_access"
94 #define XATTR_NAME_POSIX_ACL_ACCESS XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_ACCESS
95 #define XATTR_POSIX_ACL_DEFAULT  "posix_acl_default"
96 #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
97
98         return !strncmp(name, XATTR_SECURITY_PREFIX,
99                         sizeof(XATTR_SECURITY_PREFIX) - 1) ||
100                !strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
101                !strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT);
102 }
103
104 static inline const void *
105 inode_get_linux_xattrs(const struct wim_inode *inode, u32 *len_ret)
106 {
107         return inode_get_tagged_item(inode, TAG_WIMLIB_LINUX_XATTRS, 0,
108                                      len_ret);
109 }
110
111 static inline bool
112 inode_has_linux_xattrs(const struct wim_inode *inode)
113 {
114         return inode_get_linux_xattrs(inode, NULL) != NULL;
115 }
116
117 static inline bool
118 inode_set_linux_xattrs(struct wim_inode *inode, const void *entries, u32 len)
119 {
120         return inode_set_tagged_data(inode, TAG_WIMLIB_LINUX_XATTRS,
121                                      entries, len);
122 }
123
124 #endif /* _WIMLIB_XATTR_H  */