]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/xattr.c
Correct missing return in Darwin code.
[bacula/bacula] / bacula / src / filed / xattr.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2008-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * Functions to handle Extended Attributes for bacula.
30  *
31  * Extended Attributes are so OS specific we only restore Extended Attributes if
32  * they were saved using a filed on the same platform.
33  *
34  * Currently we support the following OSes:
35  *   - FreeBSD
36  *   - Darwin
37  *   - Linux
38  *   - NetBSD
39  *
40  *   Written by Marco van Wieringen, November MMVIII
41  *
42  *   Version $Id: xattr.c 7879 2008-10-23 10:12:36Z kerns $
43  */
44
45 #include "bacula.h"
46 #include "filed.h"
47 #include "xattr.h"
48
49 /*
50  * List of supported OSs.
51  */
52 #if !defined(HAVE_XATTR)            /* Extended Attributes support is required, of course */ \
53    || !( defined(HAVE_DARWIN_OS) \
54       || defined(HAVE_FREEBSD_OS) \
55       || defined(HAVE_LINUX_OS) \
56       || defined(HAVE_NETBSD_OS) \
57         )
58
59 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
60 {
61    Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
62    return false;
63 }
64
65 bool parse_xattr_stream(JCR *jcr, int stream)
66 {
67    Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
68    return false;
69 }
70
71 #else
72
73 #ifdef HAVE_SYS_XATTR_H
74 #include <sys/xattr.h>
75 #endif
76
77 /*
78  * OSX doesn't have llistxattr, lgetxattr and lsetxattr but has
79  * listxattr, getxattr and setxattr with an extra options argument
80  * which mimics the l variants of the functions when we specify
81  * XATTR_NOFOLLOW as the options value.
82  */
83 #if defined(HAVE_DARWIN_OS)
84    #define llistxattr(path, list, size) listxattr((path), (list), (size), XATTR_NOFOLLOW)
85    #define lgetxattr(path, name, value, size) getxattr((path), (name), (value), (size), 0, XATTR_NOFOLLOW)
86    #define lsetxattr(path, name, value, size, flags) setxattr((path), (name), (value), (size), (flags), XATTR_NOFOLLOW)
87 #else
88    /*
89     * Fallback to the non l-functions when those are not available.
90     */
91    #if defined(HAVE_GETXATTR) && !defined(HAVE_LGETXATTR)
92    #define lgetxattr getxattr
93    #endif
94    #if defined(HAVE_SETXATTR) && !defined(HAVE_LSETXATTR)
95    #define lsetxattr setxattr
96    #endif
97    #if defined(HAVE_LISTXATTR) && !defined(HAVE_LLISTXATTR)
98    #define llistxattr listxattr
99    #endif
100 #endif
101
102 /*
103  * Send a XATTR stream to the SD.
104  */
105 static bool send_xattr_stream(JCR *jcr, int stream, int len)
106 {
107    BSOCK *sd = jcr->store_bsock;
108    POOLMEM *msgsave;
109 #ifdef FD_NO_SEND_TEST
110    return true;
111 #endif
112
113    /*
114     * Send header
115     */
116    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
117       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
118             sd->bstrerror());
119
120       return false;
121    }
122
123    /*
124     * Send the buffer to the storage deamon
125     */
126    Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
127    msgsave = sd->msg;
128    sd->msg = jcr->xattr_data;
129    sd->msglen = len;
130    if (!sd->send()) {
131       sd->msg = msgsave;
132       sd->msglen = 0;
133       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
134             sd->bstrerror());
135
136       return false;
137    }
138
139    jcr->JobBytes += sd->msglen;
140    sd->msg = msgsave;
141    if (!sd->signal(BNET_EOD)) {
142       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
143             sd->bstrerror());
144
145       return false;
146    }
147
148    Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname);
149
150    return true;
151 }
152
153 static void xattr_drop_internal_table(xattr_t *xattr_value_list)
154 {
155    xattr_t *current_xattr;
156
157    /*
158     * Walk the list of xattrs and free allocated memory on traversing.
159     */
160    for (current_xattr = xattr_value_list;
161         current_xattr != (xattr_t *)NULL;
162         current_xattr++) {
163       /*
164        * See if we can shortcut.
165        */
166       if (current_xattr->magic != XATTR_MAGIC)
167          break;
168
169       free(current_xattr->name);
170
171       if (current_xattr->value_length > 0)
172          free(current_xattr->value);
173    }
174
175    /*
176     * Free the array of control structs.
177     */
178    free(xattr_value_list);
179 }
180
181
182 static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len, xattr_t *xattr_value_list)
183 {
184    xattr_t *current_xattr;
185    ser_declare;
186
187    /*
188     * Make sure the serialized stream fits in the poolmem buffer.
189     * We allocate some more to be sure the stream is gonna fit.
190     */
191    jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
192    ser_begin(jcr->xattr_data, expected_serialize_len + 10);
193
194    /*
195     * Walk the list of xattrs and serialize the data.
196     */
197    for (current_xattr = xattr_value_list; current_xattr != (xattr_t *)NULL; current_xattr++) {
198       /*
199        * See if we can shortcut.
200        */
201       if (current_xattr->magic != XATTR_MAGIC)
202          break;
203
204       ser_uint32(current_xattr->magic);
205       ser_uint32(current_xattr->name_length);
206       ser_bytes(current_xattr->name, current_xattr->name_length);
207
208       ser_uint32(current_xattr->value_length);
209       ser_bytes(current_xattr->value, current_xattr->value_length);
210    }
211
212    ser_end(jcr->xattr_data, expected_serialize_len + 10);
213
214    return ser_length(jcr->xattr_data);
215 }
216
217 static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream)
218 {
219    int count = 0;
220    int32_t xattr_list_len,
221            xattr_value_len,
222            expected_serialize_len = 0,
223            serialize_len = 0;
224    char *xattr_list, *bp;
225    xattr_t *xattr_value_list, *current_xattr;
226
227    /*
228     * First get the length of the available list with extended attributes.
229     */
230    xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
231    if (xattr_list_len < 0) {
232       berrno be;
233       Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
234          jcr->last_fname, be.bstrerror());
235       Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
236          jcr->last_fname, be.bstrerror());
237       return false;
238    } else if (xattr_list_len == 0) {
239       return true;
240    }
241
242    /*
243     * Allocate room for the extented attribute list.
244     */
245    if ((xattr_list = (char *)malloc(xattr_list_len + 1)) == (char *)NULL) {
246       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_list_len + 1);
247
248       return false;
249    }
250    memset((caddr_t)xattr_list, 0, xattr_list_len + 1);
251
252    /*
253     * Get the actual list of extended attributes names for a file.
254     */
255    xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
256    if (xattr_list_len < 0) {
257       berrno be;
258       Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"),
259          jcr->last_fname, be.bstrerror());
260       Dmsg2(100, "llistxattr error file=%s ERR=%s\n",
261          jcr->last_fname, be.bstrerror());
262
263       free(xattr_list);
264       return false;
265    }
266    xattr_list[xattr_list_len] = '\0';
267
268    /*
269     * Count the number of extended attributes on a file.
270     */
271    bp = xattr_list;
272    while ((bp - xattr_list) + 1 < xattr_list_len) {
273       count++;
274
275       bp = strchr(bp, '\0') + 1;
276    }
277
278    /*
279     * Allocate enough room to hold all extended attributes.
280     * After allocating the storage make sure its empty by zeroing it.
281     */
282    if ((xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t))) == (xattr_t *)NULL) {
283       Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), count * sizeof(xattr_t));
284
285       return false;
286    }
287    memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
288
289    /*
290     * Walk the list of extended attributes names and retrieve the data.
291     * We already count the bytes needed for serializing the stream later on.
292     */
293    current_xattr = xattr_value_list;
294    bp = xattr_list;
295    while ((bp - xattr_list) + 1 < xattr_list_len) {
296 #if defined(HAVE_LINUX_OS)
297       /*
298        * On Linux you also get the acls in the extented attribute list.
299        * So we check if we are already backing up acls and if we do we
300        * don't store the extended attribute with the same info.
301        */
302       if (ff_pkt->flags & FO_ACL && !strcmp(bp, "system.posix_acl_access")) {
303          bp = strchr(bp, '\0') + 1;
304
305          continue;
306       }
307 #endif
308
309       /*
310        * Each xattr valuepair starts with a magic so we can parse it easier.
311        */
312       current_xattr->magic = XATTR_MAGIC;
313       expected_serialize_len += sizeof(current_xattr->magic);
314
315       /*
316        * Allocate space for storing the name.
317        */
318       current_xattr->name_length = strlen(bp);
319       if ((current_xattr->name = (char *)malloc(current_xattr->name_length)) == (char *)NULL) {
320          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr->name_length);
321
322          goto bail_out;
323       }
324       memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
325
326       expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
327
328       /*
329        * First see how long the value is for the extended attribute.
330        */
331       xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
332       if (xattr_value_len < 0) {
333          berrno be;
334          Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
335             jcr->last_fname, be.bstrerror());
336          Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
337             jcr->last_fname, be.bstrerror());
338
339          goto bail_out;
340       }
341
342       /*
343        * Allocate space for storing the value.
344        */
345       if ((current_xattr->value = (char *)malloc(xattr_value_len)) == (char *)NULL) {
346          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), xattr_value_len);
347
348          goto bail_out;
349       }
350       memset((caddr_t)current_xattr->value, 0, xattr_value_len);
351
352       xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
353       if (xattr_value_len < 0) {
354          berrno be;
355          Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"),
356             jcr->last_fname, be.bstrerror());
357          Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
358             jcr->last_fname, be.bstrerror());
359
360          goto bail_out;
361       }
362
363       /*
364        * Store the actual length of the value.
365        */
366       current_xattr->value_length = xattr_value_len;
367
368       expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
369       
370       /*
371        * Next attribute.
372        */
373       current_xattr++;
374       bp = strchr(bp, '\0') + 1;
375    }
376
377    /*
378     * Serialize the datastream.
379     */
380    if ((serialize_len = serialize_xattr_stream(jcr, expected_serialize_len,
381          xattr_value_list)) < expected_serialize_len) {
382       Jmsg1(jcr, M_ERROR, 0, _("failed to serialize extended attributes on file \"%s\"\n"),
383          jcr->last_fname);
384
385       goto bail_out;
386    }
387
388    xattr_drop_internal_table(xattr_value_list);
389    free(xattr_list);
390
391    /*
392     * Send the datastream to the SD.
393     */
394    return send_xattr_stream(jcr, stream, serialize_len);
395
396 bail_out:
397    xattr_drop_internal_table(xattr_value_list);
398    free(xattr_list);
399
400    return false;
401 }
402
403 static bool generic_xattr_parse_streams(JCR *jcr)
404 {
405    unser_declare;
406    xattr_t current_xattr;
407    bool retval = true;
408
409    /*
410     * Parse the stream and perform the setxattr calls on the file.
411     *
412     * Start unserializing the data. We keep on looping while we have not
413     * unserialized all bytes in the stream.
414     */
415    unser_begin(jcr->xattr_data, jcr->xattr_data_len);
416    while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
417       /*
418        * First make sure the magic is present. This way we can easily catch corruption.
419        * Any missing MAGIC is fatal we do NOT try to continue.
420        */
421       unser_uint32(current_xattr.magic);
422       if (current_xattr.magic != XATTR_MAGIC) {
423          Jmsg1(jcr, M_ERROR, 0, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
424             jcr->last_fname);
425
426          return false;
427       }
428
429       /*
430        * Decode the valuepair. First decode the length of the name.
431        */
432       unser_uint32(current_xattr.name_length);
433       
434       /*
435        * Allocate room for the name and decode its content.
436        */
437       if ((current_xattr.name = (char *)malloc(current_xattr.name_length + 1)) == (char *)NULL) {
438          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.name_length + 1);
439
440          return false;
441       }
442       unser_bytes(current_xattr.name, current_xattr.name_length);
443
444       /*
445        * The xattr_name needs to be null terminated for lsetxattr.
446        */
447       current_xattr.name[current_xattr.name_length] = '\0';
448
449       /*
450        * Decode the value length.
451        */
452       unser_uint32(current_xattr.value_length);
453
454       /*
455        * Allocate room for the value and decode its content.
456        */
457       if ((current_xattr.value = (char *)malloc(current_xattr.value_length)) == (char *)NULL) {
458          Emsg1(M_ABORT, 0, _("Out of memory requesting %d bytes\n"), current_xattr.value_length);
459
460          return false;
461       }
462       unser_bytes(current_xattr.value, current_xattr.value_length);
463
464       /*
465        * Try to set the extended attribute on the file.
466        * If we fail to set this attribute we flag the error but its not fatal,
467        * we try to restore the other extended attributes too.
468        */
469       if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value,
470          current_xattr.value_length, 0) != 0) {
471          berrno be;
472          Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"),
473             jcr->last_fname, be.bstrerror());
474          Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
475             jcr->last_fname, be.bstrerror());
476
477          /*
478           * Reset the return flag to false to indicate one or more extended attributes
479           * could not be restored.
480           */
481          retval = false;
482       }
483
484       /*
485        * Free the temporary buffers.
486        */
487       free(current_xattr.name);
488       free(current_xattr.value);
489    }
490
491    unser_end(jcr->xattr_data, jcr->xattr_data_len);
492    return retval;
493 }
494
495 #if defined(HAVE_DARWIN_OS)
496 static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
497 {
498    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN);
499 }
500
501 static bool darwin_parse_xattr_stream(JCR *jcr, int stream)
502 {
503    switch (stream) {
504    case STREAM_XATTR_DARWIN:
505       return generic_xattr_parse_streams(jcr);
506    }
507    return false;
508 }
509 #elif defined(HAVE_FREEBSD_OS)
510 static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
511 {
512    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD);
513 }
514
515 static bool freebsd_parse_xattr_stream(JCR *jcr, int stream)
516 {
517    switch (stream) {
518    case STREAM_XATTR_FREEBSD:
519       return generic_xattr_parse_streams(jcr);
520    }
521 }
522 #elif defined(HAVE_LINUX_OS)
523 static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
524 {
525    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX);
526 }
527
528 static bool linux_parse_xattr_stream(JCR *jcr, int stream)
529 {
530    switch (stream) {
531    case STREAM_XATTR_LINUX:
532       return generic_xattr_parse_streams(jcr);
533    }
534    return false;
535 }
536 #elif defined(HAVE_NETBSD_OS)
537 static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
538 {
539    return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD);
540 }
541
542 static bool netbsd_parse_xattr_stream(JCR *jcr, int stream)
543 {
544    switch (stream) {
545    case STREAM_XATTR_NETBSD:
546       return generic_xattr_parse_streams(jcr);
547    }
548    return false;
549 }
550 #endif
551
552 bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
553 {
554 #if defined(HAVE_DARWIN_OS)
555    return darwin_build_xattr_streams(jcr, ff_pkt);
556 #elif defined(HAVE_FREEBSD_OS)
557    return freebsd_build_xattr_streams(jcr, ff_pkt);
558 #elif defined(HAVE_LINUX_OS)
559    return linux_build_xattr_streams(jcr, ff_pkt);
560 #elif defined(HAVE_NETBSD_OS)
561    return netbsd_build_xattr_streams(jcr, ff_pkt);
562 #endif
563 }
564
565 bool parse_xattr_stream(JCR *jcr, int stream)
566 {
567    /*
568     * Based on the stream being passed in dispatch to the right function
569     * for parsing and restoring a specific xattr. The platform determines
570     * which streams are recognized and parsed and which are handled by
571     * the default case and ignored. As only one of the platform defines
572     * is true per compile we never end up with duplicate switch values.
573     */
574    switch (stream) {
575 #if defined(HAVE_DARWIN_OS)
576    case STREAM_XATTR_DARWIN:
577       return darwin_parse_xattr_stream(jcr, stream);
578 #elif defined(HAVE_FREEBSD_OS)
579    case STREAM_XATTR_FREEBSD:
580       return freebsd_parse_xattr_stream(jcr, stream);
581 #elif defined(HAVE_LINUX_OS)
582    case STREAM_XATTR_LINUX:
583       return linux_parse_xattr_stream(jcr, stream);
584 #elif defined(HAVE_NETBSD_OS)
585    case STREAM_XATTR_NETBSD:
586       return netbsd_parse_xattr_stream(jcr, stream);
587 #endif
588    default:
589       /*
590        * Issue a warning and discard the message. But pretend the restore was ok.
591        */
592       Qmsg2(jcr, M_WARNING, 0,
593          _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"),
594          jcr->last_fname, stream);
595       return true;
596    } /* end switch (stream) */
597 }
598
599 #endif