2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2016 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Major refactoring of XATTR code written by:
22 * Radosław Korzeniewski, MMXVI
23 * radoslaw@korzeniewski.net, radekk@inteos.pl
24 * Inteos Sp. z o.o. http://www.inteos.pl/
30 #include "bxattr_osx.h"
32 #if defined(HAVE_DARWIN_OS)
34 /* check if XATTR support is enabled */
35 #if defined(HAVE_XATTR)
38 * Define the supported XATTR streams for this OS
40 static const int os_xattr_streams[] = {
41 STREAM_XACL_DARWIN_XATTR,
45 static const char *os_xattr_skiplist[] = {
46 "com.apple.system.extendedsecurity",
47 "com.apple.ResourceFork",
51 static const char *os_xattr_acl_skiplist[] = {
52 "com.apple.system.Security",
57 * OS specific constructor
59 BXATTR_OSX::BXATTR_OSX()
61 set_xattr_streams(os_xattr_streams);
62 set_xattr_skiplists(os_xattr_skiplist, os_xattr_acl_skiplist);
66 * Perform OS specific extended attribute backup
68 * in/out - check API at bxattr.h
70 bRC_BXATTR BXATTR_OSX::os_backup_xattr (JCR *jcr, FF_PKT *ff_pkt){
71 return generic_backup_xattr(jcr, ff_pkt);
75 * Perform OS specific XATTR restore. Runtime is called only when stream is supported by OS.
77 * in/out - check API at bxattr.h
79 bRC_BXATTR BXATTR_OSX::os_restore_xattr (JCR *jcr, int stream, char *content, uint32_t length){
80 return generic_restore_xattr(jcr, stream);
84 * Return a list of xattr names in newly allocated pool memory and a length of the allocated buffer.
85 * It allocates a memory with poolmem subroutines every time a function is called, so it must be freed
88 * in/out - check API at bxattr.h
90 bRC_BXATTR BXATTR_OSX::os_get_xattr_names (JCR *jcr, POOLMEM ** pxlist, uint32_t * xlen){
95 /* check input data */
96 if (jcr == NULL || xlen == NULL || pxlist == NULL){
97 return bRC_BXATTR_inval;
99 /* get the length of the extended attributes */
100 len = listxattr(jcr->last_fname, NULL, 0, XATTR_NOFOLLOW);
107 /* no file available, skip it */
108 return bRC_BXATTR_skip;
110 /* no xattr supported on filesystem, clear a flag and skip it */
111 clear_flag(BXATTR_FLAG_NATIVE);
113 return bRC_BXATTR_skip;
115 Mmsg2(jcr->errmsg, _("llistxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
116 Dmsg2(100, "llistxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
117 return bRC_BXATTR_error;
122 /* xattr available but empty, skip it */
123 return bRC_BXATTR_skip;
129 * allocate memory for the extented attribute list
130 * default size is a 4k for PM_BSOCK, which should be sufficient on almost all
131 * Linux system where xattrs a limited in size to single filesystem block ~4kB
132 * so we need to check required size
134 list = get_pool_memory(PM_BSOCK);
135 list = check_pool_memory_size(list, len + 1);
136 memset(list, 0, len + 1);
138 /* get the list of extended attributes names for a file */
139 len = listxattr(jcr->last_fname, list, len, XATTR_NOFOLLOW);
146 /* no file available, skip it, first release allocated memory */
147 free_pool_memory(list);
148 return bRC_BXATTR_skip;
150 Mmsg2(jcr->errmsg, _("llistxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
151 Dmsg2(100, "llistxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
152 free_pool_memory(list);
153 return bRC_BXATTR_error;
160 /* ensure a list is nul terminated */
162 /* setup return data */
165 return bRC_BXATTR_ok;
169 * Return a value of the requested attribute name and a length of the allocated buffer.
170 * It allocates a memory with poolmem subroutines every time a function is called, so it must be freed
173 * in/out - check API at bxattr.h
175 bRC_BXATTR BXATTR_OSX::os_get_xattr_value (JCR *jcr, char * name, char ** pvalue, uint32_t * plen){
180 /* check input data */
181 if (jcr == NULL || name == NULL || plen == NULL || pvalue == NULL){
182 return bRC_BXATTR_inval;
185 /* get the length of the value for extended attribute */
186 len = getxattr(jcr->last_fname, name, NULL, 0, 0, XATTR_NOFOLLOW);
193 /* no file available, skip it */
194 return bRC_BXATTR_skip;
196 /* XXX: what about ENOATTR error value? */
197 Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
198 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
199 return bRC_BXATTR_error;
209 * allocate memory for the extented attribute value
210 * default size is a 256B for PM_MESSAGE, so we need to check required size
212 value = get_pool_memory(PM_MESSAGE);
213 value = check_pool_memory_size(value, len + 1);
214 memset(value, 0, len + 1);
215 /* value is not empty, get a data */
216 len = getxattr(jcr->last_fname, name, value, len, 0, XATTR_NOFOLLOW);
223 /* no file available, skip it, first release allocated memory */
224 free_pool_memory(value);
225 return bRC_BXATTR_skip;
227 Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
228 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
229 free_pool_memory(value);
230 return bRC_BXATTR_error;
237 /* ensure a value is nul terminated */
244 /* setup return data */
247 return bRC_BXATTR_ok;
251 * Low level OS specific runtime to set extended attribute on file
253 * in/out - check API at bxattr.h
255 bRC_BXATTR BXATTR_OSX::os_set_xattr (JCR *jcr, BXATTR_xattr *xattr){
257 /* check input data */
258 if (jcr == NULL || xattr == NULL){
259 return bRC_BXATTR_inval;
262 /* set extattr on file */
263 if (setxattr(jcr->last_fname, xattr->name, xattr->value, xattr->value_len, 0, XATTR_NOFOLLOW) != 0){
271 * If the filesystem reports it doesn't support XATTR we clear the
272 * BXATTR_FLAG_NATIVE flag so we skip XATTR restores on all other files
273 * on the same filesystem. The BXATTR_FLAG_NATIVE flag gets set again
274 * when we change from one filesystem to an other.
276 clear_flag(BXATTR_FLAG_NATIVE);
277 Mmsg1(jcr->errmsg, _("setxattr error on file \"%s\": filesystem doesn't support XATTR\n"), jcr->last_fname);
278 Dmsg3(100, "setxattr error name=%s value=%s file=%s filesystem doesn't support XATTR\n", xattr->name, xattr->value, jcr->last_fname);
281 Mmsg2(jcr->errmsg, _("setxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
282 Dmsg2(100, "setxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
283 return bRC_BXATTR_error;
286 return bRC_BXATTR_ok;
289 #endif /* HAVE_XATTR */
291 #endif /* HAVE_DARWIN_OS */