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