From: Marco van Wieringen Date: Thu, 16 Jul 2009 05:42:21 +0000 (+0200) Subject: Imported patch from older git tree. X-Git-Tag: Release-5.0.0~333^2~51 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=51a10b73cb544fda80b57e23cb285c7157d185f3;p=bacula%2Fbacula Imported patch from older git tree. --- diff --git a/bacula/src/filed/acl.c b/bacula/src/filed/acl.c index feae14bc7b..79fdbd6d57 100644 --- a/bacula/src/filed/acl.c +++ b/bacula/src/filed/acl.c @@ -44,9 +44,6 @@ * Its also interesting to see what the exact format of acl text is on * certain platforms and if they use they same encoding we might allow * different platform streams to be decoded on an other similar platform. - * As we implement the decoding/restoring process as a big switch based - * on the stream number being passed in extending the switching code is - * easy. * * Original written by Preben 'Peppe' Guldberg, December MMIV * Major rewrite by Marco van Wieringen, November MMVIII @@ -56,37 +53,38 @@ #include "bacula.h" #include "filed.h" +#include "acl.h" #if !defined(HAVE_ACL) /* * Entry points when compiled without support for ACLs or on an unsupported platform. */ -bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +bsub_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { - return false; + return bsub_exit_fatal; } -bool parse_acl_stream(JCR *jcr, int stream) +bsub_exit_code parse_acl_stream(JCR *jcr, int stream) { - return false; + return bsub_exit_fatal; } #else /* * Send an ACL stream to the SD. */ -static bool send_acl_stream(JCR *jcr, int stream) +static bsub_exit_code send_acl_stream(JCR *jcr, int stream) { BSOCK *sd = jcr->store_bsock; POOLMEM *msgsave; #ifdef FD_NO_SEND_TEST - return true; + return bsub_exit_ok; #endif /* * Sanity check */ if (jcr->acl_data_len <= 0) - return true; + return bsub_exit_ok; /* * Send header @@ -94,8 +92,7 @@ static bool send_acl_stream(JCR *jcr, int stream) if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); - - return false; + return bsub_exit_fatal; } /* @@ -110,8 +107,7 @@ static bool send_acl_stream(JCR *jcr, int stream) sd->msglen = 0; Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); - - return false; + return bsub_exit_fatal; } jcr->JobBytes += sd->msglen; @@ -119,42 +115,49 @@ static bool send_acl_stream(JCR *jcr, int stream) if (!sd->signal(BNET_EOD)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); - - return false; + return bsub_exit_fatal; } Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname); - - return true; + return bsub_exit_ok; } #if defined(HAVE_AIX_OS) #include -static bool aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +/* + * Define the supported ACL streams for this OS + */ +static int os_access_acl_streams[1] = { STREAM_ACL_AIX_TEXT }; +static int os_default_acl_streams[1] = { -1 }; + +static bsub_exit_code aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { char *acl_text; if ((acl_text = acl_get(jcr->last_fname)) != NULL) { jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text); actuallyfree(acl_text); - return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT); } - - return false; + return bsub_exit_nok; } -static bool aix_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code aix_parse_acl_streams(JCR *jcr, int stream) { if (acl_put(jcr->last_fname, jcr->acl_data, 0) != 0) { - return false; + return bsub_exit_nok; } - - return true; + return bsub_exit_ok; } +/* + * For this OS setup the build and parse function pointer to the OS specific functions. + */ +static bsub_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = aix_build_acl_streams; +static bsub_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = aix_parse_acl_streams; + #elif defined(HAVE_DARWIN_OS) \ || defined(HAVE_FREEBSD_OS) \ || defined(HAVE_IRIX_OS) \ @@ -222,13 +225,12 @@ static acl_type_t bac_to_os_acltype(bacl_type acltype) #endif default: /* - * This should never happen, as the per os version function only tries acl + * This should never happen, as the per OS version function only tries acl * types supported on a certain platform. */ ostype = (acl_type_t)ACL_TYPE_NONE; break; } - return ostype; } @@ -257,8 +259,7 @@ static bool acl_is_trivial(acl_t acl) * If we fail to get the tagtype we call the acl non-trivial. */ if (acl_get_tag_type(ace, &tag) < 0) - return false; - + return true; /* * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell. */ @@ -266,10 +267,8 @@ static bool acl_is_trivial(acl_t acl) tag != ACL_GROUP_OBJ && tag != ACL_OTHER) return false; - entry_available = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace); } - return true; #elif defined(HAVE_IRIX_OS) int n; @@ -286,7 +285,6 @@ static bool acl_is_trivial(acl_t acl) tag != ACL_OTHER_OBJ) return false; } - return true; #elif defined(HAVE_OSF1_OS) int count; @@ -296,7 +294,6 @@ static bool acl_is_trivial(acl_t acl) while (count > 0) { tag = ace->entry->acl_type; - /* * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell. */ @@ -304,18 +301,15 @@ static bool acl_is_trivial(acl_t acl) tag != ACL_GROUP_OBJ && tag != ACL_OTHER) return false; - /* * On Tru64, perm can also contain non-standard bits such as * PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */ if ((ace->entry->acl_perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE))) return false; - ace = ace->next; count--; } - return true; #endif } @@ -324,10 +318,9 @@ static bool acl_is_trivial(acl_t acl) /* * Generic wrapper around acl_get_file call. */ -static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype) +static bsub_exit_code generic_get_acl_from_os(JCR *jcr, bacl_type acltype) { acl_t acl; - int len; acl_type_t ostype; char *acl_text; @@ -349,8 +342,9 @@ static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype) */ if (acl->acl_cnt <= 0) { pm_strcpy(jcr->acl_data, ""); + jcr->acl_data_len = 0; acl_free(acl); - return 0; + return bsub_exit_ok; } #endif @@ -364,17 +358,17 @@ static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype) * So we don't send an ACL stream to the SD. */ pm_strcpy(jcr->acl_data, ""); + jcr->acl_data_len = 0; acl_free(acl); - return 0; + return bsub_exit_ok; } #endif if ((acl_text = acl_to_text(acl, NULL)) != NULL) { - len = pm_strcpy(jcr->acl_data, acl_text); + jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text); acl_free(acl); acl_free(acl_text); - - return len; + return bsub_exit_ok; } berrno be; @@ -384,9 +378,9 @@ static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype) jcr->last_fname, be.bstrerror()); pm_strcpy(jcr->acl_data, ""); + jcr->acl_data_len = 0; acl_free(acl); - - return 0; /* non-fatal error */ + return bsub_exit_nok; } /* @@ -398,6 +392,10 @@ static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype) case BACL_ENOTSUP: break; /* not supported */ #endif + case ENOENT: + pm_strcpy(jcr->acl_data, ""); + jcr->acl_data_len = 0; + return bsub_exit_ok; default: berrno be; /* Some real error */ @@ -407,20 +405,22 @@ static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype) jcr->last_fname, be.bstrerror()); pm_strcpy(jcr->acl_data, ""); - return 0; /* non-fatal error */ + jcr->acl_data_len = 0; + return bsub_exit_nok; } } /* * Not supported, just pretend there is nothing to see */ pm_strcpy(jcr->acl_data, ""); - return 0; + jcr->acl_data_len = 0; + return bsub_exit_ok; } /* * Generic wrapper around acl_set_file call. */ -static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype) +static bsub_exit_code generic_set_acl_on_os(JCR *jcr, bacl_type acltype) { acl_t acl; acl_type_t ostype; @@ -431,13 +431,17 @@ static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype) ostype = bac_to_os_acltype(acltype); if (ostype == ACL_TYPE_DEFAULT && strlen(jcr->acl_data) == 0) { if (acl_delete_def_file(jcr->last_fname) == 0) { - return true; + return bsub_exit_ok; + } + switch (errno) { + case ENOENT: + return bsub_exit_ok; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + return bsub_exit_nok; } - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - - return false; } acl = acl_from_text(jcr->acl_data); @@ -447,15 +451,14 @@ static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype) jcr->last_fname, be.bstrerror()); Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); - - return false; + return bsub_exit_nok; } +#ifndef HAVE_FREEBSD_OS /* * FreeBSD always fails acl_valid() - at least on valid input... * As it does the right thing, given valid input, just ignore acl_valid(). */ -#ifndef HAVE_FREEBSD_OS if (acl_valid(acl) != 0) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("ac_valid error on file \"%s\": ERR=%s\n"), @@ -463,8 +466,7 @@ static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype) Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); acl_free(acl); - - return false; + return bsub_exit_nok; } #endif @@ -475,25 +477,35 @@ static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype) * don't save acls of symlinks (which cannot have acls anyhow) */ if (acl_set_file(jcr->last_fname, ostype, acl) != 0 && jcr->last_type != FT_LNK) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("acl_set_file error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n", - jcr->acl_data, jcr->last_fname, be.bstrerror()); - acl_free(acl); - - return false; + switch (errno) { + case ENOENT: + acl_free(acl); + return bsub_exit_nok; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("acl_set_file error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n", + jcr->acl_data, jcr->last_fname, be.bstrerror()); + acl_free(acl); + return bsub_exit_nok; + } } acl_free(acl); - - return true; + return bsub_exit_ok; } /* * OS specific functions for handling different types of acl streams. */ #if defined(HAVE_DARWIN_OS) -static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +/* + * Define the supported ACL streams for this OS + */ +static int os_access_acl_streams[1] = { STREAM_ACL_DARWIN_ACCESS_ACL }; +static int os_default_acl_streams[1] = { -1 }; + +static bsub_exit_code darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { #if defined(ACL_TYPE_EXTENDED) /* @@ -505,189 +517,143 @@ static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) * * Read access ACLs for files, dirs and links */ - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0) - return false; + if (generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED) == bsub_exit_fatal) + return bsub_exit_fatal; #else /* * Read access ACLs for files, dirs and links */ - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0) - return false; + if (generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS) == bsub_exit_fatal) + return bsub_exit_fatal; #endif if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL)) - return false; + return send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL); } - - return true; + return bsub_exit_ok; } -static bool darwin_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code darwin_parse_acl_streams(JCR *jcr, int stream) { - switch (stream) { - case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_DARWIN_ACCESS_ACL: +#if defined(ACL_TYPE_EXTENDED) + return generic_set_acl_on_os(jcr, BACL_TYPE_EXTENDED); +#else return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS); - } - - return false; +#endif } -#elif defined(HAVE_FREEBSD_OS) -static bool freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - /* - * Read access ACLs for files, dirs and links - */ - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0) - return false; - - if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_ACCESS_ACL)) - return false; - } - /* - * Directories can have default ACLs too - */ - if (ff_pkt->type == FT_DIREND) { - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0) - return false; - - if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_DEFAULT_ACL)) - return false; - } - } - - return true; -} +/* + * For this OS setup the build and parse function pointer to the OS specific functions. + */ +static bsub_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = darwin_build_acl_streams; +static bsub_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = darwin_parse_acl_streams; -static bool freebsd_parse_acl_stream(JCR *jcr, int stream) -{ - switch (stream) { - case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_FREEBSD_ACCESS_ACL: - return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS); - case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_FREEBSD_DEFAULT_ACL: - return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT); - } +#elif defined(HAVE_FREEBSD_OS) || defined(HAVE_IRIX_OS) || defined(HAVE_LINUX_OS) - return false; -} +/* + * Define the supported ACL streams for these OSes + */ +#if defined(HAVE_FREEBSD_OS) +static int os_access_acl_streams[1] = { STREAM_ACL_FREEBSD_ACCESS_ACL }; +static int os_default_acl_streams[1] = { STREAM_ACL_FREEBSD_DEFAULT_ACL }; #elif defined(HAVE_IRIX_OS) -static bool irix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +static int os_access_acl_streams[1] = { STREAM_ACL_IRIX_ACCESS_ACL }; +static int os_default_acl_streams[1] = { STREAM_ACL_IRIX_DEFAULT_ACL }; +#elif defined(HAVE_LINUX_OS) +static int os_access_acl_streams[1] = { STREAM_ACL_LINUX_ACCESS_ACL }; +static int os_default_acl_streams[1] = { STREAM_ACL_LINUX_DEFAULT_ACL }; +#endif + +static bsub_exit_code generic_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { /* * Read access ACLs for files, dirs and links */ - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0) - return false; + if (generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS) == bsub_exit_fatal) + return bsub_exit_fatal; if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_IRIX_ACCESS_ACL)) - return false; + if (send_acl_stream(jcr, os_access_acl_streams[0]) == bsub_exit_fatal) + return bsub_exit_fatal; } /* * Directories can have default ACLs too */ if (ff_pkt->type == FT_DIREND) { - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0) - return false; - + if (generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT) == bsub_exit_fatal) + return bsub_exit_fatal; if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_IRIX_DEFAULT_ACL)) - return false; + if (send_acl_stream(jcr, os_default_acl_streams[0]) == bsub_exit_fatal) + return bsub_exit_fatal; } } - - return true; + return bsub_exit_ok; } -static bool irix_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code generic_parse_acl_streams(JCR *jcr, int stream) { + int cnt; + switch (stream) { case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_IRIX_ACCESS_ACL: return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS); case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_IRIX_DEFAULT_ACL: return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT); - } - - return false; -} -#elif defined(HAVE_LINUX_OS) -static bool linux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - /* - * Read access ACLs for files, dirs and links - */ - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0) - return false; - - if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_LINUX_ACCESS_ACL)) - return false; - } - - /* - * Directories can have default ACLs too - */ - if (ff_pkt->type == FT_DIREND) { - if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0) - return false; - - if (jcr->acl_data_len > 0) { - if (!send_acl_stream(jcr, STREAM_ACL_LINUX_DEFAULT_ACL)) - return false; + default: + /* + * See what type of acl it is. + */ + for (cnt = 0; cnt < sizeof(os_access_acl_streams) / sizeof(int); cnt++) { + if (os_access_acl_streams[cnt] == stream) { + return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS); + } + } + for (cnt = 0; cnt < sizeof(os_default_acl_streams) / sizeof(int); cnt++) { + if (os_default_acl_streams[cnt] == stream) { + return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT); + } } + break; } - - return true; + return bsub_exit_nok; } -static bool linux_parse_acl_stream(JCR *jcr, int stream) -{ - switch (stream) { - case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_LINUX_ACCESS_ACL: - return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS); - case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_LINUX_DEFAULT_ACL: - return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT); - } +/* + * For this OSes setup the build and parse function pointer to the OS specific functions. + */ +static bsub_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = generic_build_acl_streams; +static bsub_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = generic_parse_acl_streams; - return false; -} #elif defined(HAVE_OSF1_OS) -static bool tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) + +/* + * Define the supported ACL streams for this OS + */ +static int os_access_acl_streams[1] = { STREAM_ACL_TRU64_ACCESS_ACL }; +static int os_default_acl_streams[2] = { STREAM_ACL_TRU64_DEFAULT_ACL, STREAM_ACL_TRU64_DEFAULT_DIR_ACL }; + +static bsub_exit_code tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { /* * Read access ACLs for files, dirs and links */ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0) - return false; - + return bsub_exit_nok; if (jcr->acl_data_len > 0) { if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL)) - return false; + return bsub_exit_nok; } - /* * Directories can have default ACLs too */ if (ff_pkt->type == FT_DIREND) { if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0) - return false; - + return bsub_exit_nok; if (jcr->acl_data_len > 0) { if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL)) - return false; + return bsub_exit_nok; } - /* * Tru64 has next to BACL_TYPE_DEFAULT also BACL_TYPE_DEFAULT_DIR acls. * This is an inherited acl for all subdirs. @@ -695,18 +661,16 @@ static bool tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) * Section 21.5 Default ACLs */ if ((jcr->acl_data_len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0) - return false; - + return bsub_exit_nok; if (jcr->acl_data_len > 0) { if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL)) - return false; + return bsub_exit_nok; } } - - return true; + return bsub_exit_ok; } -static bool tru64_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code tru64_parse_acl_streams(JCR *jcr, int stream) { switch (stream) { case STREAM_UNIX_ACCESS_ACL: @@ -718,6 +682,13 @@ static bool tru64_parse_acl_stream(JCR *jcr, int stream) case STREAM_ACL_TRU64_DEFAULT_DIR_ACL: return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR); } + +/* + * For this OS setup the build and parse function pointer to the OS specific functions. + */ +static bsub_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = tru64_build_acl_streams; +static bsub_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = tru64_parse_acl_streams; + #endif #elif defined(HAVE_HPUX_OS) @@ -729,6 +700,12 @@ static bool tru64_parse_acl_stream(JCR *jcr, int stream) #include +/* + * Define the supported ACL streams for this OS + */ +static int os_access_acl_streams[1] = { STREAM_ACL_HPUX_ACL_ENTRY }; +static int os_default_acl_streams[1] = { -1 }; + /* * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.) * There is no need to store those acls as we already store the stat bits too. @@ -740,7 +717,6 @@ static bool acl_is_trivial(int count, struct acl_entry *entries, struct stat sb) for (n = 0; n < count; n++) { ace = entries[n]; - /* * See if this acl just is the stat mode in acl form. */ @@ -749,29 +725,33 @@ static bool acl_is_trivial(int count, struct acl_entry *entries, struct stat sb) (ace.uid == ACL_NSUSER && ace.gid == ACL_NSGROUP))) return false; } - return true; } /* * OS specific functions for handling different types of acl streams. */ -static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +static bsub_exit_code hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { int n; struct acl_entry acls[NACLENTRIES]; char *acl_text; if ((n = getacl(jcr->last_fname, 0, acls)) < 0) { - switch(errno) { + switch (errno) { #if defined(BACL_ENOTSUP) case BACL_ENOTSUP: /* * Not supported, just pretend there is nothing to see */ pm_strcpy(jcr->acl_data, ""); - return true; + jcr->acl_data_len = 0; + return bsub_exit_ok; #endif + case ENOENT: + pm_strcpy(jcr->acl_data, ""); + jcr->acl_data_len = 0; + return bsub_exit_ok; default: berrno be; Jmsg2(jcr, M_ERROR, 0, _("getacl error on file \"%s\": ERR=%s\n"), @@ -780,15 +760,15 @@ static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) jcr->last_fname, be.bstrerror()); pm_strcpy(jcr->acl_data, ""); - return false; + jcr->acl_data_len = 0; + return bsub_exit_nok; } } - if (n == 0) { pm_strcpy(jcr->acl_data, ""); - return true; + jcr->acl_data_len = 0; + return bsub_exit_ok; } - if ((n = getacl(jcr->last_fname, n, acls)) > 0) { if (acl_is_trivial(n, acls, ff_pkt->statp)) { /* @@ -796,29 +776,26 @@ static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) * So we don't send an ACL stream to the SD. */ pm_strcpy(jcr->acl_data, ""); - return true; + jcr->acl_data_len = 0; + return bsub_exit_ok; } - if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) { jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text); actuallyfree(acl_text); return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY); } - berrno be; Jmsg2(jcr, M_ERROR, 0, _("acltostr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror()); Dmsg3(100, "acltostr error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); - - return false; + return bsub_exit_nok; } - - return false; + return bsub_exit_nok; } -static bool hpux_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code hpux_parse_acl_streams(JCR *jcr, int stream) { int n, stat; struct acl_entry acls[NACLENTRIES]; @@ -830,8 +807,7 @@ static bool hpux_parse_acl_stream(JCR *jcr, int stream) jcr->last_fname, be.bstrerror()); Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); - - return false; + return bsub_exit_nok; } if (strtoacl(jcr->acl_data, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) { berrno be; @@ -840,7 +816,7 @@ static bool hpux_parse_acl_stream(JCR *jcr, int stream) Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); - return false; + return bsub_exit_nok; } /* * Restore the ACLs, but don't complain about links which really should @@ -849,18 +825,27 @@ static bool hpux_parse_acl_stream(JCR *jcr, int stream) * don't save acls of symlinks (which cannot have acls anyhow) */ if (setacl(jcr->last_fname, n, acls) != 0 && jcr->last_type != FT_LNK) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("setacl error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg3(100, "setacl error acl=%s file=%s ERR=%s\n", - jcr->acl_data, jcr->last_fname, be.bstrerror()); - - return false; + switch (errno) { + case ENOENT: + return bsub_exit_nok; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("setacl error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg3(100, "setacl error acl=%s file=%s ERR=%s\n", + jcr->acl_data, jcr->last_fname, be.bstrerror()); + return bsub_exit_nok; + } } - - return true; + return bsub_exit_ok; } +/* + * For this OS setup the build and parse function pointer to the OS specific functions. + */ +static bsub_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = hpux_build_acl_streams; +static bsub_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = hpux_parse_acl_streams; + #elif defined(HAVE_SUN_OS) #ifdef HAVE_SYS_ACL_H #include @@ -876,7 +861,7 @@ static bool hpux_parse_acl_stream(JCR *jcr, int stream) * and versions of Solaris we need to expose some data to be able * to determine the type of acl used to stuff it into the correct * data stream. I know this is far from portable, but maybe the - * propper interface is exposed later on and we can get ride of + * proper interface is exposed later on and we can get ride of * this kludge. Newer versions of Solaris include sys/acl_impl.h * which has implementation details of acls, if thats included we * don't have to define it ourself. @@ -896,19 +881,24 @@ int acl_type(acl_t *); char *acl_strerror(int); } +/* + * Define the supported ACL streams for this OS + */ +static int os_access_acl_streams[2] = { STREAM_ACL_SOLARIS_ACLENT, STREAM_ACL_SOLARIS_ACE }; +static int os_default_acl_streams[1] = { -1 }; + /* * As the new libsec interface with acl_totext and acl_fromtext also handles * the old format from acltotext we can use the new functions even * for acls retrieved and stored in the database with older fd versions. If the * new interface is not defined (Solaris 9 and older we fall back to the old code) */ -static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +static bsub_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { int acl_enabled, flags; acl_t *aclp; char *acl_text; - bool stream_status = false; - berrno be; + bsub_exit_code stream_status = bsub_exit_nok; /* * See if filesystem supports acls. @@ -917,15 +907,15 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) switch (acl_enabled) { case 0: pm_strcpy(jcr->acl_data, ""); - - return true; + jcr->acl_data_len = 0; + return bsub_exit_ok; case -1: + berrno be; Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror()); Dmsg2(100, "pathconf error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror()); - - return false; + return bsub_exit_nok; default: break; } @@ -938,8 +928,7 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) jcr->last_fname, acl_strerror(errno)); Dmsg2(100, "acl_get error file=%s ERR=%s\n", jcr->last_fname, acl_strerror(errno)); - - return false; + return bsub_exit_nok; } if (!aclp) { @@ -948,7 +937,8 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) * So we don't send an ACL stream to the SD. */ pm_strcpy(jcr->acl_data, ""); - return true; + jcr->acl_data_len = 0; + return bsub_exit_ok; } #if defined(ACL_SID_FMT) @@ -977,15 +967,13 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) acl_free(aclp); } - return stream_status; } -static bool solaris_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code solaris_parse_acl_streams(JCR *jcr, int stream) { acl_t *aclp; int acl_enabled, error; - berrno be; switch (stream) { case STREAM_UNIX_ACCESS_ACL: @@ -999,15 +987,14 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) case 0: Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without acl support\n"), jcr->last_fname); - - return false; + return bsub_exit_nok; case -1: + berrno be; Jmsg2(jcr, M_ERROR, 0, _("pathconf error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror()); Dmsg3(100, "pathconf error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); - - return false; + return bsub_exit_nok; default: /* * On a filesystem with ACL support make sure this particilar ACL type can be restored. @@ -1020,7 +1007,7 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) if ((acl_enabled & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED)) == 0) { Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without aclent acl support\n"), jcr->last_fname); - return false; + return bsub_exit_nok; } break; case STREAM_ACL_SOLARIS_ACE: @@ -1030,7 +1017,7 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) if ((acl_enabled & _ACL_ACE_ENABLED) == 0) { Jmsg1(jcr, M_ERROR, 0, _("Trying to restore acl on file \"%s\" on filesystem without ace acl support\n"), jcr->last_fname); - return false; + return bsub_exit_nok; } break; default: @@ -1047,7 +1034,7 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) jcr->last_fname, acl_strerror(error)); Dmsg3(100, "acl_fromtext error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, acl_strerror(error)); - return false; + return bsub_exit_nok; } /* @@ -1058,14 +1045,14 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) if (acl_type(aclp) != ACLENT_T) { Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"), jcr->last_fname); - return false; + return bsub_exit_nok; } break; case STREAM_ACL_SOLARIS_ACE: if (acl_type(aclp) != ACE_T) { Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"), jcr->last_fname); - return false; + return bsub_exit_nok; } break; default: @@ -1088,18 +1075,24 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) jcr->acl_data, jcr->last_fname, acl_strerror(error)); acl_free(aclp); - return false; + return bsub_exit_nok; } acl_free(aclp); - return true; + return bsub_exit_ok; default: - return false; + return bsub_exit_nok; } /* end switch (stream) */ } #else /* HAVE_EXTENDED_ACL */ +/* + * Define the supported ACL streams for this OS + */ +static int os_access_acl_streams[2] = { STREAM_ACL_SOLARIS_ACLENT }; +static int os_default_acl_streams[1] = { -1 }; + /* * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.) * There is no need to store those acls as we already store the stat bits too. @@ -1118,14 +1111,13 @@ static bool acl_is_trivial(int count, aclent_t *entries) ace->a_type == CLASS_OBJ)) return false; } - return true; } /* * OS specific functions for handling different types of acl streams. */ -static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +static bsub_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { int n; aclent_t *acls; @@ -1133,7 +1125,7 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) n = acl(jcr->last_fname, GETACLCNT, 0, NULL); if (n < MIN_ACL_ENTRIES) - return false; + return bsub_exit_nok; acls = (aclent_t *)malloc(n * sizeof(aclent_t)); if (acl(jcr->last_fname, GETACL, n, acls) == n) { @@ -1144,14 +1136,14 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) */ free(acls); pm_strcpy(jcr->acl_data, ""); - return true; + jcr->acl_data_len = 0; + return bsub_exit_ok; } if ((acl_text = acltotext(acls, n)) != NULL) { jcr->acl_data_len = pm_strcpy(jcr->acl_data, acl_text); actuallyfree(acl_text); free(acls); - return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT); } @@ -1163,10 +1155,10 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) } free(acls); - return false; + return bsub_exit_nok; } -static bool solaris_parse_acl_stream(JCR *jcr, int stream) +static bsub_exit_code solaris_parse_acl_streams(JCR *jcr, int stream) { int n; aclent_t *acls; @@ -1178,8 +1170,7 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) jcr->last_fname, be.bstrerror()); Dmsg3(100, "aclfromtext error acl=%s file=%s ERR=%s\n", jcr->acl_data, jcr->last_fname, be.bstrerror()); - - return false; + return bsub_exit_nok; } /* @@ -1187,21 +1178,31 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) * not have attributes, and the file it is linked to may not yet be restored. */ if (acl(jcr->last_fname, SETACL, n, acls) == -1 && jcr->last_type != FT_LNK) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("acl(SETACL) error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg3(100, "acl(SETACL) error acl=%s file=%s ERR=%s\n", - jcr->acl_data, jcr->last_fname, be.bstrerror()); - actuallyfree(acls); - - return false; + switch (errno) { + case ENOENT: + actuallyfree(acls); + return bsub_exit_nok; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("acl(SETACL) error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg3(100, "acl(SETACL) error acl=%s file=%s ERR=%s\n", + jcr->acl_data, jcr->last_fname, be.bstrerror()); + actuallyfree(acls); + return bsub_exit_nok; + } } - actuallyfree(acls); - return true; + return bsub_exit_ok; } - #endif /* HAVE_EXTENDED_ACL */ + +/* + * For this OS setup the build and parse function pointer to the OS specific functions. + */ +static bsub_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = solaris_build_acl_streams; +static bsub_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = solaris_parse_acl_streams; + #endif /* HAVE_SUN_OS */ /* @@ -1211,96 +1212,53 @@ static bool solaris_parse_acl_stream(JCR *jcr, int stream) /* * Read and send an ACL for the last encountered file. */ -bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +bsub_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { /* - * Call the appropriate function, the ifdefs make sure the proper code is compiled. + * Call the appropriate function. */ -#if defined(HAVE_AIX_OS) - return aix_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_DARWIN_OS) - return darwin_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_FREEBSD_OS) - return freebsd_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_HPUX_OS) - return hpux_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_IRIX_OS) - return irix_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_LINUX_OS) - return linux_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_OSF1_OS) - return tru64_build_acl_streams(jcr, ff_pkt); -#elif defined(HAVE_SUN_OS) - return solaris_build_acl_streams(jcr, ff_pkt); -#endif + if (os_build_acl_streams) { + return (*os_build_acl_streams)(jcr, ff_pkt); + } + return bsub_exit_nok; } -bool parse_acl_stream(JCR *jcr, int stream) +bsub_exit_code parse_acl_streams(JCR *jcr, int stream) { - /* - * Based on the stream being passed in dispatch to the right function - * for parsing and restoring a specific acl. The platform determines - * which streams are recognized and parsed and which are handled by - * the default case and ignored. The old STREAM_UNIX_ACCESS_ACL and - * STREAM_UNIX_DEFAULT_ACL is handled as a legacy stream by each function. - * As only one of the platform defines is true per compile we never end - * up with duplicate switch values. - */ switch (stream) { -#if defined(HAVE_AIX_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_AIX_TEXT: - return aix_parse_acl_stream(jcr, stream); -#elif defined(HAVE_DARWIN_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_DARWIN_ACCESS_ACL: - return darwin_parse_acl_stream(jcr, stream); -#elif defined(HAVE_FREEBSD_OS) case STREAM_UNIX_ACCESS_ACL: case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_FREEBSD_DEFAULT_ACL: - case STREAM_ACL_FREEBSD_ACCESS_ACL: - return freebsd_parse_acl_stream(jcr, stream); -#elif defined(HAVE_HPUX_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_HPUX_ACL_ENTRY: - return hpux_parse_acl_stream(jcr, stream); -#elif defined(HAVE_IRIX_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_IRIX_DEFAULT_ACL: - case STREAM_ACL_IRIX_ACCESS_ACL: - return irix_parse_acl_stream(jcr, stream); -#elif defined(HAVE_LINUX_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_LINUX_DEFAULT_ACL: - case STREAM_ACL_LINUX_ACCESS_ACL: - return linux_parse_acl_stream(jcr, stream); -#elif defined(HAVE_OSF1_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_UNIX_DEFAULT_ACL: - case STREAM_ACL_TRU64_DEFAULT_ACL: - case STREAM_ACL_TRU64_ACCESS_ACL: - case STREAM_ACL_TRU64_DEFAULT_DIR_ACL: - return tru64_parse_acl_stream(jcr, stream); -#elif defined(HAVE_SUN_OS) - case STREAM_UNIX_ACCESS_ACL: - case STREAM_ACL_SOLARIS_ACLENT: -#if defined(HAVE_EXTENDED_ACL) - case STREAM_ACL_SOLARIS_ACE: -#endif - return solaris_parse_acl_stream(jcr, stream); -#endif - default: /* - * Issue a warning and discard the message. But pretend the restore was ok. + * Handle legacy ACL streams. */ - Qmsg2(jcr, M_WARNING, 0, - _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"), - jcr->last_fname, stream); - return true; - } /* end switch (stream) */ + if (os_parse_acl_streams) { + return (*os_parse_acl_streams)(jcr, stream); + } + break; + default: + if (os_parse_acl_streams) { + /* + * Walk the os_access_acl_streams array with the supported Access ACL streams for this OS. + */ + for (cnt = 0; cnt < sizeof(os_access_acl_streams) / sizeof(int); cnt++) { + if (os_access_acl_streams[cnt] == stream) { + return (*os_parse_acl_streams)(jcr, stream); + } + } + /* + * Walk the os_default_acl_streams array with the supported Default ACL streams for this OS. + */ + for (cnt = 0; cnt < sizeof(os_default_acl_streams) / sizeof(int); cnt++) { + if (os_default_acl_streams[cnt] == stream) { + return (*os_parse_acl_streams)(jcr, stream); + } + } + } + break; + } + Qmsg2(jcr, M_WARNING, 0, + _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"), + jcr->last_fname, stream); + return bsub_exit_nok; } #endif diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index f1818260c8..bdca4fac2d 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -600,7 +600,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) */ if (have_acl) { if (ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK && !ff_pkt->cmd_plugin) { - if (!build_acl_streams(jcr, ff_pkt)) + if (build_acl_streams(jcr, ff_pkt) == bsub_exit_fatal) goto bail_out; } } @@ -610,7 +610,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level) */ if (have_xattr) { if (ff_pkt->flags & FO_XATTR && !ff_pkt->cmd_plugin) { - if (!build_xattr_streams(jcr, ff_pkt)) + if (build_xattr_streams(jcr, ff_pkt) == bsub_exit_fatal) goto bail_out; } } diff --git a/bacula/src/filed/filed.h b/bacula/src/filed/filed.h index 3c3649be30..eb2897256a 100644 --- a/bacula/src/filed/filed.h +++ b/bacula/src/filed/filed.h @@ -40,7 +40,6 @@ #include "fd_plugins.h" #include "findlib/find.h" #include "jcr.h" -#include "acl.h" #include "protos.h" /* file daemon prototypes */ #include "lib/runscript.h" #include "lib/breg.h" @@ -51,3 +50,9 @@ #endif extern CLIENT *me; /* "Global" Client resource */ + +typedef enum { + bsub_exit_fatal = -1, + bsub_exit_nok = 0, + bsub_exit_ok = 1 +} bsub_exit_code; diff --git a/bacula/src/filed/protos.h b/bacula/src/filed/protos.h index b5daaa8c19..4a6d476e37 100644 --- a/bacula/src/filed/protos.h +++ b/bacula/src/filed/protos.h @@ -47,8 +47,8 @@ void start_dir_heartbeat(JCR *jcr); void stop_dir_heartbeat(JCR *jcr); /* From acl.c */ -bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt); -bool parse_acl_stream(JCR *jcr, int stream); +bsub_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt); +bsub_exit_code parse_acl_streams(JCR *jcr, int stream); /* from accurate.c */ bool accurate_send_deleted_list(JCR *jcr); @@ -62,5 +62,5 @@ void strip_path(FF_PKT *ff_pkt); void unstrip_path(FF_PKT *ff_pkt); /* from xattr.c */ -bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt); -bool parse_xattr_stream(JCR *jcr, int stream); +bsub_exit_code build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt); +bsub_exit_code parse_xattr_streams(JCR *jcr, int stream); diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index e24abdf3f5..4bbd5dbd14 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -610,7 +610,7 @@ void do_restore(JCR *jcr) if (have_acl) { pm_memcpy(jcr->acl_data, sd->msg, sd->msglen); jcr->acl_data_len = sd->msglen; - if (!parse_acl_stream(jcr, rctx.stream)) { + if (parse_acl_streams(jcr, rctx.stream) != bsub_exit_ok) { Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACLs of %s\n"), jcr->last_fname); } } else { @@ -636,7 +636,7 @@ void do_restore(JCR *jcr) if (have_xattr) { pm_memcpy(jcr->xattr_data, sd->msg, sd->msglen); jcr->xattr_data_len = sd->msglen; - if (!parse_xattr_stream(jcr, rctx.stream)) { + if (parse_xattr_streams(jcr, rctx.stream) != bsub_exit_ok) { Qmsg1(jcr, M_WARNING, 0, _("Can't restore Extended Attributes of %s\n"), jcr->last_fname); } } else { diff --git a/bacula/src/filed/xattr.c b/bacula/src/filed/xattr.c index 99f9bbb63b..1bde9f8a18 100644 --- a/bacula/src/filed/xattr.c +++ b/bacula/src/filed/xattr.c @@ -51,32 +51,32 @@ /* * Entry points when compiled without support for XATTRs or on an unsupported platform. */ -bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) +bsub_exit_code build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) { - return false; + return bsub_exit_fatal; } -bool parse_xattr_stream(JCR *jcr, int stream) +bsub_exit_code parse_xattr_streams(JCR *jcr, int stream) { - return false; + return bsub_exit_fatal; } #else /* * Send a XATTR stream to the SD. */ -static bool send_xattr_stream(JCR *jcr, int stream) +static bsub_exit_code send_xattr_stream(JCR *jcr, int stream) { BSOCK *sd = jcr->store_bsock; POOLMEM *msgsave; #ifdef FD_NO_SEND_TEST - return true; + return bsub_exit_ok; #endif /* * Sanity check */ if (jcr->xattr_data_len <= 0) - return true; + return bsub_exit_ok; /* * Send header @@ -84,7 +84,7 @@ static bool send_xattr_stream(JCR *jcr, int stream) if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); - return false; + return bsub_exit_fatal; } /* @@ -99,7 +99,7 @@ static bool send_xattr_stream(JCR *jcr, int stream) sd->msglen = 0; Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); - return false; + return bsub_exit_fatal; } jcr->JobBytes += sd->msglen; @@ -107,11 +107,10 @@ static bool send_xattr_stream(JCR *jcr, int stream) if (!sd->signal(BNET_EOD)) { Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror()); - return false; + return bsub_exit_fatal; } Dmsg1(200, "XATTR of file: %s successfully backed up!\n", jcr->last_fname); - - return true; + return bsub_exit_ok; } /* @@ -226,11 +225,10 @@ static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len ser_end(jcr->xattr_data, expected_serialize_len + 10); jcr->xattr_data_len = ser_length(jcr->xattr_data); - return jcr->xattr_data_len; } -static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) +static bsub_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int default_stream) { int count = 0; int32_t xattr_list_len, @@ -244,14 +242,19 @@ static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) */ xattr_list_len = llistxattr(jcr->last_fname, NULL, 0); if (xattr_list_len < 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg2(100, "llistxattr error file=%s ERR=%s\n", - jcr->last_fname, be.bstrerror()); - return true; /* non-fatal return */ + switch (errno) { + case ENOENT: + return bsub_exit_nok; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "llistxattr error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + return bsub_exit_nok; + } } else if (xattr_list_len == 0) { - return true; + return bsub_exit_ok; } /* @@ -265,13 +268,19 @@ static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) */ xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len); if (xattr_list_len < 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg2(100, "llistxattr error file=%s ERR=%s\n", - jcr->last_fname, be.bstrerror()); - free(xattr_list); - return true; /* non-fatal return */ + switch (errno) { + case ENOENT: + free(xattr_list); + return bsub_exit_nok; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("llistxattr error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "llistxattr error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + free(xattr_list); + return bsub_exit_nok; + } } xattr_list[xattr_list_len] = '\0'; @@ -297,8 +306,7 @@ static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) if (count == 0) { free(xattr_list); - - return true; + return bsub_exit_ok; } /* @@ -342,12 +350,17 @@ static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) */ xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0); if (xattr_value_len < 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", - jcr->last_fname, be.bstrerror()); - goto bail_out; + switch (errno) { + case ENOENT: + goto bail_out; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + goto bail_out; + } } /* @@ -358,12 +371,17 @@ static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len); if (xattr_value_len < 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", - jcr->last_fname, be.bstrerror()); - goto bail_out; + switch (errno) { + case ENOENT: + goto bail_out; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("lgetxattr error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + goto bail_out; + } } /* @@ -405,19 +423,19 @@ static bool generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt, int stream) /* * Send the datastream to the SD. */ - return send_xattr_stream(jcr, stream); + return send_xattr_stream(jcr, default_stream); bail_out: xattr_drop_internal_table(xattr_value_list); free(xattr_list); - return true; /* non-fatal return */ + return bsub_exit_nok; } -static bool generic_xattr_parse_streams(JCR *jcr) +static bsub_exit_code generic_xattr_parse_streams(JCR *jcr, int stream) { unser_declare; xattr_t current_xattr; - bool retval = true; /* default non-fatal */ + bsub_exit_code retval = bsub_exit_nok; /* * Parse the stream and perform the setxattr calls on the file. @@ -437,7 +455,7 @@ static bool generic_xattr_parse_streams(JCR *jcr) jcr->last_fname); Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n", jcr->last_fname); - return true; /* non-fatal return */ + return bsub_exit_nok; } /* @@ -473,12 +491,18 @@ static bool generic_xattr_parse_streams(JCR *jcr) * we try to restore the other extended attributes too. */ if (lsetxattr(jcr->last_fname, current_xattr.name, current_xattr.value, - current_xattr.value_length, 0) != 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg2(100, "lsetxattr error file=%s ERR=%s\n", - jcr->last_fname, be.bstrerror()); + switch (errno) { + case ENOENT: + break; + default: + current_xattr.value_length, 0) != 0) { + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("lsetxattr error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "lsetxattr error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + break; + } } /* @@ -492,79 +516,25 @@ static bool generic_xattr_parse_streams(JCR *jcr) return retval; } -#if defined(HAVE_DARWIN_OS) -static bool darwin_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_DARWIN); -} +/* + * For all these os-es setup the build and parse function pointer to the generic functions. + */ +static bsub_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt, int default_stream) = generic_xattr_build_streams; +static bsub_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = generic_xattr_parse_streams; -static bool darwin_parse_xattr_stream(JCR *jcr, int stream) -{ - switch (stream) { - case STREAM_XATTR_DARWIN: - return generic_xattr_parse_streams(jcr); - default: - Jmsg2(jcr, M_WARNING, 0, - _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), - jcr->last_fname, stream); - return true; /* non-fatal error */ - } -} +/* + * All these os-es have 1 xattr stream. + */ +#if defined(HAVE_DARWIN_OS) +static int os_default_xattr_streams[1] = { STREAM_XATTR_DARWIN }; #elif defined(HAVE_FREEBSD_OS) -static bool freebsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_FREEBSD); -} - -static bool freebsd_parse_xattr_stream(JCR *jcr, int stream) -{ - switch (stream) { - case STREAM_XATTR_FREEBSD: - return generic_xattr_parse_streams(jcr); - default: - Jmsg2(jcr, M_WARNING, 0, - _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), - jcr->last_fname, stream); - return true; /* non-fatal error */ - } -} +static int os_default_xattr_streams[1] = { STREAM_XATTR_FREEBSD }; #elif defined(HAVE_LINUX_OS) -static bool linux_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_LINUX); -} - -static bool linux_parse_xattr_stream(JCR *jcr, int stream) -{ - switch (stream) { - case STREAM_XATTR_LINUX: - return generic_xattr_parse_streams(jcr); - default: - Jmsg2(jcr, M_WARNING, 0, - _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), - jcr->last_fname, stream); - return true; /* non-fatal error */ - } -} +static int os_default_xattr_streams[1] = { STREAM_XATTR_LINUX }; #elif defined(HAVE_NETBSD_OS) -static bool netbsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - return generic_xattr_build_streams(jcr, ff_pkt, STREAM_XATTR_NETBSD); -} - -static bool netbsd_parse_xattr_stream(JCR *jcr, int stream) -{ - switch (stream) { - case STREAM_XATTR_NETBSD: - return generic_xattr_parse_streams(jcr); - default: - Jmsg2(jcr, M_WARNING, 0, - _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), - jcr->last_fname, stream); - return true; /* non-fatal error */ - } -} +static int os_default_xattr_streams[1] = { STREAM_XATTR_NETBSD }; #endif + #elif defined(HAVE_SUN_OS) /* * Solaris extended attributes were introduced in Solaris 9 @@ -675,15 +645,14 @@ static int toplevel_hidden_dir_xattr_data_len; * This code creates a temporary cache with entries for each xattr which has * a link count > 1 (which indicates it has one or more hard linked counterpart(s)) */ -static xattr_link_cache_entry_t *xattr_link_cache_head = NULL, - *xattr_link_cache_tail = NULL; +static alist *xattr_link_cache = NULL; static struct xattr_link_cache_entry *find_xattr_link_cache_entry(ino_t inum) { xattr_link_cache_entry_t *ptr; - for (ptr = xattr_link_cache_head; ptr != NULL; ptr = ptr->next) { - if (ptr->inum == inum) { + foreach_alist(ptr, xattr_link_cache) { + if (ptr && ptr->inum == inum) { return ptr; } } @@ -698,24 +667,7 @@ static void add_xattr_link_cache_entry(ino_t inum, char *target) memset((caddr_t)ptr, 0, sizeof(struct xattr_link_cache_entry)); ptr->inum = inum; strncpy(ptr->target, target, sizeof(ptr->target)); - if (xattr_link_cache_head == NULL) { - xattr_link_cache_head = ptr; - } - if (xattr_link_cache_tail != NULL) { - xattr_link_cache_tail->next = ptr; - } -} - -static void drop_xattr_link_cache(void) -{ - xattr_link_cache_entry_t *ptr, *next; - - for (ptr = xattr_link_cache_tail; ptr != NULL; ptr = next) { - next = ptr->next; - free(ptr); - } - xattr_link_cache_head = NULL; - xattr_link_cache_tail = NULL; + xattr_link_cache->append(ptr); } #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) @@ -813,7 +765,7 @@ static bool acl_is_trivial(int count, aclent_t *entries) } #endif /* HAVE_ACL && !HAVE_EXTENDED_ACL */ -static bool solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text) +static bsub_exit_code solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char **acl_text) { #ifdef HAVE_ACL #ifdef HAVE_EXTENDED_ACL @@ -830,12 +782,17 @@ static bool solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char */ if ((fd != -1 && facl_get(fd, ACL_NO_TRIVIAL, &aclp) != 0) || acl_get(attrname, ACL_NO_TRIVIAL, &aclp) != 0) { - berrno be; - Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"), - attrname, jcr->last_fname, be.bstrerror()); - Dmsg3(100, "facl_get/acl_get of xattr %s on \"%s\" failed: ERR=%s\n", - attrname, jcr->last_fname, be.bstrerror()); - return true; /* non-fatal */ + switch (errno) { + case ENOENT: + return bsub_exit_nok; + default: + berrno be; + Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"), + attrname, jcr->last_fname, be.bstrerror()); + Dmsg3(100, "facl_get/acl_get of xattr %s on \"%s\" failed: ERR=%s\n", + attrname, jcr->last_fname, be.bstrerror()); + return bsub_exit_nok; + } } if (aclp != NULL) { @@ -856,8 +813,7 @@ static bool solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char } else { *acl_text = NULL; } - - return true; + return bsub_exit_ok; #else /* HAVE_EXTENDED_ACL */ int n; aclent_t *acls = NULL; @@ -875,13 +831,19 @@ static bool solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char acls = (aclent_t *)malloc(n * sizeof(aclent_t)); if ((fd != -1 && facl(fd, GETACL, n, acls) != n) || acl(attrname, GETACL, n, acls) != n) { - berrno be; - Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"), - attrname, jcr->last_fname, be.bstrerror()); - Dmsg3(100, "facl/acl of xattr %s on \"%s\" failed: ERR=%s\n", - attrname, jcr->last_fname, be.bstrerror()); - free(acls); - return true; /* non-fatal */ + switch (errno) { + case ENOENT: + free(acls); + return bsub_exit_nok; + default: + berrno be; + Jmsg3(jcr, M_ERROR, 0, _("Unable to get acl on xattr %s on file \"%s\": ERR=%s\n"), + attrname, jcr->last_fname, be.bstrerror()); + Dmsg3(100, "facl/acl of xattr %s on \"%s\" failed: ERR=%s\n", + attrname, jcr->last_fname, be.bstrerror()); + free(acls); + return bsub_exit_nok; + } } /* @@ -895,7 +857,7 @@ static bool solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char Dmsg3(100, "acltotext of xattr %s on \"%s\" failed: ERR=%s\n", attrname, jcr->last_fname, be.bstrerror()); free(acls); - return true; /* non-fatal */ + return bsub_exit_nok; } } else { *acl_text = NULL; @@ -905,19 +867,18 @@ static bool solaris_save_xattr_acl(JCR *jcr, int fd, const char *attrname, char } else { *acl_text = NULL; } - - return true; + return bsub_exit_ok; #endif /* HAVE_EXTENDED_ACL */ #else /* HAVE_ACL */ - return false; /* fatal return */ + return bsub_exit_ok; #endif /* HAVE_ACL */ } /* * Forward declaration for recursive function call. */ -static bool solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent); +static bsub_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent); /* * Save an extended or extensible attribute. @@ -934,8 +895,8 @@ static bool solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const cha * acl_string is an acl text when a non trivial acl is set on the xattr. * actual_xattr_data is the content of the xattr file. */ -static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, - const char *attrname, bool toplevel_hidden_dir, int stream) +static bsub_exit_code solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, + const char *attrname, bool toplevel_hidden_dir, int stream) { int cnt; int attrfd = -1; @@ -946,7 +907,7 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, char *acl_text = NULL; char attribs[MAXSTRING]; char buffer[BUFSIZ]; - bool retval = true; /* default is non-fatal */ + bsub_exit_code retval = bsub_exit_nok; snprintf(target_attrname, sizeof(target_attrname), "%s%s", xattr_namespace, attrname); @@ -954,12 +915,17 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, * Get the stats of the extended or extensible attribute. */ if (fstatat(fd, attrname, &st, AT_SYMLINK_NOFOLLOW) < 0) { - berrno be; - Jmsg3(jcr, M_ERROR, 0, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"), - target_attrname, jcr->last_fname, be.bstrerror()); - Dmsg3(100, "fstatat of xattr %s on \"%s\" failed: ERR=%s\n", - target_attrname, jcr->last_fname, be.bstrerror()); - goto cleanup; + switch (errno) { + case ENOENT: + goto cleanup; + default: + berrno be; + Jmsg3(jcr, M_ERROR, 0, _("Unable to get status on xattr %s on file \"%s\": ERR=%s\n"), + target_attrname, jcr->last_fname, be.bstrerror()); + Dmsg3(100, "fstatat of xattr %s on \"%s\" failed: ERR=%s\n", + target_attrname, jcr->last_fname, be.bstrerror()); + goto cleanup; + } } /* @@ -974,7 +940,7 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, /* * Get any acl on the xattr. */ - if (!solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text)) + if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bsub_exit_ok) goto cleanup; /* @@ -990,7 +956,7 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, /* * Get any acl on the xattr. */ - if (!solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text)) + if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bsub_exit_ok) goto cleanup; /* @@ -1055,7 +1021,7 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, /* * Get any acl on the xattr. */ - if (!solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text)) { + if (solaris_save_xattr_acl(jcr, attrfd, attrname, &acl_text) != bsub_exit_ok) { goto cleanup; } @@ -1071,12 +1037,17 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, * Open the extended or extensible attribute file. */ if ((attrfd = openat(fd, attrname, O_RDONLY)) < 0) { - berrno be; - Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on \"%s\": ERR=%s\n"), - target_attrname, jcr->last_fname, be.bstrerror()); - Dmsg3(100, "openat of xattr %s on \"%s\" failed: ERR=%s\n", - target_attrname, jcr->last_fname, be.bstrerror()); - goto cleanup; + switch (errno) { + case ENOENT: + goto cleanup; + default: + berrno be; + Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr %s on \"%s\": ERR=%s\n"), + target_attrname, jcr->last_fname, be.bstrerror()); + Dmsg3(100, "openat of xattr %s on \"%s\" failed: ERR=%s\n", + target_attrname, jcr->last_fname, be.bstrerror()); + goto cleanup; + } } break; @@ -1086,12 +1057,17 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, * Encode the stat struct into an ASCII representation. */ if (readlink(attrname, link_source, sizeof(link_source)) < 0) { - berrno be; - Jmsg3(jcr, M_ERROR, 0, _("Unable to read symlin %s on \"%s\": ERR=%s\n"), - target_attrname, jcr->last_fname, be.bstrerror()); - Dmsg3(100, "readlink of xattr %s on \"%s\" failed: ERR=%s\n", - target_attrname, jcr->last_fname, be.bstrerror()); - goto cleanup; + switch (errno) { + case ENOENT: + goto cleanup; + default: + berrno be; + Jmsg3(jcr, M_ERROR, 0, _("Unable to read symlin %s on \"%s\": ERR=%s\n"), + target_attrname, jcr->last_fname, be.bstrerror()); + Dmsg3(100, "readlink of xattr %s on \"%s\" failed: ERR=%s\n", + target_attrname, jcr->last_fname, be.bstrerror()); + goto cleanup; + } } /* @@ -1177,12 +1153,17 @@ static bool solaris_save_xattr(JCR *jcr, int fd, const char *xattr_namespace, * The recursive call could change our working dir so change back to the wanted workdir. */ if (fchdir(fd) < 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg3(100, "Unable to fchdir to xattr space of file \"%s\" using fd %d: ERR=%s\n", - jcr->last_fname, fd, be.bstrerror()); - goto cleanup; + switch (errno) { + case ENOENT: + goto cleanup; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to chdir to xattr space of file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg3(100, "Unable to fchdir to xattr space of file \"%s\" using fd %d: ERR=%s\n", + jcr->last_fname, fd, be.bstrerror()); + goto cleanup; + } } } @@ -1196,14 +1177,14 @@ cleanup: return retval; } -static bool solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent) +static bsub_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const char *attr_parent) { const char *name; int fd, filefd = -1, attrdirfd = -1; DIR *dirp; struct dirent *dp; char current_xattr_namespace[PATH_MAX]; - bool retval = true; /* default non-fatal error */ + bsub_exit_code retval = bsub_exit_nok; /* * Determine what argument to use. Use attr_parent when set @@ -1227,12 +1208,17 @@ static bool solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const cha * Open the file on which to save the xattrs read-only. */ if ((filefd = open(name, O_RDONLY | O_NONBLOCK)) < 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"), - jcr->last_fname, be.bstrerror()); - Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n", - jcr->last_fname, be.bstrerror()); - goto cleanup; + switch (errno) { + case ENOENT: + goto cleanup; + default: + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to open file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "Unable to open file \"%s\": ERR=%s\n", + jcr->last_fname, be.bstrerror()); + goto cleanup; + } } /* @@ -1246,16 +1232,18 @@ static bool solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const cha * Which is not problem we just forget about this this xattr. * But as this is not an error we return a positive return value. */ - retval = true; - break; + retval = bsub_exit_ok; + goto cleanup; + case ENOENT: + goto cleanup; default: berrno be; Jmsg3(jcr, M_ERROR, 0, _("Unable to open xattr space %s on file \"%s\": ERR=%s\n"), name, jcr->last_fname, be.bstrerror()); Dmsg3(100, "Unable to open xattr space %s on file \"%s\": ERR=%s\n", name, jcr->last_fname, be.bstrerror()); + goto cleanup; } - goto cleanup; } /* @@ -1353,7 +1341,7 @@ static bool solaris_save_xattrs(JCR *jcr, const char *xattr_namespace, const cha } closedir(dirp); - retval = true; + retval = bsub_exit_ok; cleanup: if (attrdirfd != -1) @@ -1364,7 +1352,7 @@ cleanup: } #ifdef HAVE_ACL -static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, char *acl_text) +static bsub_exit_code solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, char *acl_text) { #ifdef HAVE_EXTENDED_ACL int error; @@ -1372,8 +1360,8 @@ static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, ch if ((error = acl_fromtext(acl_text, &aclp)) != 0) { Jmsg1(jcr, M_ERROR, 0, _("Unable to convert acl from text on file \"%s\"\n"), - jcr->last_fname); - return true; /* non-fatal */ + jcr->last_fname); + return bsub_exit_nok; } if ((fd != -1 && facl_set(fd, aclp) != 0) || @@ -1383,13 +1371,13 @@ static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, ch attrname, jcr->last_fname, be.bstrerror()); Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n", attrname, jcr->last_fname, be.bstrerror()); - return true; /* non-fatal */ + return bsub_exit_nok; } if (aclp) { acl_free(aclp); } - return true; + return bsub_exit_ok; #else /* HAVE_EXTENDED_ACL */ int n; @@ -1404,21 +1392,21 @@ static bool solaris_restore_xattr_acl(JCR *jcr, int fd, const char *attrname, ch attrname, jcr->last_fname, be.bstrerror()); Dmsg3(100, "Unable to restore acl of xattr %s on file \"%s\": ERR=%s\n", attrname, jcr->last_fname, be.bstrerror()); - return true; /* non-fatal */ + return bsub_exit_nok; } } if (acls) { free(acls); } - return true; + return bsub_exit_ok; #endif /* HAVE_EXTENDED_ACL */ } #endif /* HAVE_ACL */ -static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) +static bsub_exit_code solaris_restore_xattrs(JCR *jcr, bool is_extensible) { int fd, filefd = -1, attrdirfd = -1, attrfd = -1; int used_bytes, total_bytes, cnt; @@ -1429,7 +1417,7 @@ static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) int32_t inum; struct stat st; struct timeval times[2]; - bool retval = true; /* default non-fatal */ + bsub_exit_code retval = bsub_exit_nok; /* * Parse the xattr stream. First the part that is the same for all xattrs. @@ -1618,7 +1606,7 @@ static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) /* * Successfully restored xattr. */ - retval = true; + retval = bsub_exit_ok; goto cleanup; } else { if ((bp = strchr(acl_text, '\0')) == (char *)NULL || @@ -1700,7 +1688,7 @@ static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) /* * Successfully restored xattr. */ - retval = true; + retval = bsub_exit_ok; goto cleanup; default: goto cleanup; @@ -1717,7 +1705,7 @@ static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) * Gentile way of the system saying this type of xattr layering is not supported. * But as this is not an error we return a positive return value. */ - retval = true; + retval = bsub_exit_ok; break; default: berrno be; @@ -1732,7 +1720,7 @@ static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) #ifdef HAVE_ACL if (acl_text && *acl_text) - if (!solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text)) + if (solaris_restore_xattr_acl(jcr, attrfd, target_attrname, acl_text) != bsub_exit_ok) goto cleanup; #endif /* HAVE_ACL */ @@ -1758,7 +1746,7 @@ static bool solaris_restore_xattrs(JCR *jcr, bool is_extensible) /* * Successfully restored xattr. */ - retval = true; + retval = bsub_exit_ok; goto cleanup; parse_error: @@ -1780,11 +1768,37 @@ cleanup: return retval; } -static bool solaris_extract_xattr(JCR *jcr, int stream) +static bsub_exit_code solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt, int default_stream) +{ + char cwd[PATH_MAX]; + bsub_exit_code retval = bsub_exit_ok; + + /* + * First see if extended attributes or extensible attributes are present. + * If not just pretend things went ok. + */ + if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) { + nr_xattr_saved = 0; + + /* + * As we change the cwd in the save function save the current cwd + * for restore after return from the solaris_save_xattrs function. + */ + xattr_link_cache = New(alist(10, not_owned_by_alist)); + getcwd(cwd, sizeof(cwd)); + retval = solaris_save_xattrs(jcr, NULL, NULL); + chdir(cwd); + delete xattr_link_cache; + xattr_link_cache = NULL; + } + return retval; +} + +static bsub_exit_code solaris_parse_xattr_streams(JCR *jcr, int stream) { char cwd[PATH_MAX]; bool is_extensible = false; - bool retval; + bsub_exit_code retval; /* * First make sure we can restore xattr on the filesystem. @@ -1798,7 +1812,7 @@ static bool solaris_extract_xattr(JCR *jcr, int stream) jcr->last_fname); Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n", jcr->last_fname); - return true; + return bsub_exit_nok; } is_extensible = true; @@ -1811,11 +1825,11 @@ static bool solaris_extract_xattr(JCR *jcr, int stream) jcr->last_fname); Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n", jcr->last_fname); - return true; + return bsub_exit_nok; } break; default: - return true; + return bsub_exit_nok; } /* @@ -1828,101 +1842,52 @@ static bool solaris_extract_xattr(JCR *jcr, int stream) return retval; } -static int solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) -{ - char cwd[PATH_MAX]; - bool retval = true; - /* - * First see if extended attributes or extensible attributes are present. - * If not just pretend things went ok. - */ - if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) { - nr_xattr_saved = 0; +/* + * Function pointers to the build and parse function to use for these xattrs. + */ +static bsub_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt, int default_stream) = solaris_build_xattr_streams; +static bsub_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = solaris_parse_xattr_streams; - /* - * As we change the cwd in the save function save the current cwd - * for restore after return from the solaris_save_xattrs function. - */ - getcwd(cwd, sizeof(cwd)); - retval = solaris_save_xattrs(jcr, NULL, NULL); - chdir(cwd); - drop_xattr_link_cache(); - } +/* + * Number of xattr streams this OS supports and an array with integers with the actual stream numbers. + */ +#if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) +static int os_default_xattr_streams[2] = { STREAM_XATTR_SOLARIS, STREAM_XATTR_SOLARIS_SYS}; +#else +static int os_default_xattr_streams[1] = { STREAM_XATTR_SOLARIS }; +#endif /* defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) */ - return retval; -} +#endif /* defined(HAVE_SUN_OS) */ -static bool solaris_parse_xattr_stream(JCR *jcr, int stream) +bsub_exit_code build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) { - switch (stream) { -#if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) - case STREAM_XATTR_SOLARIS_SYS: -#endif - case STREAM_XATTR_SOLARIS: - return solaris_extract_xattr(jcr, stream); - default: - Jmsg2(jcr, M_WARNING, 0, - _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), - jcr->last_fname, stream); - return true; /* non-fatal error */ + if (os_build_xattr_streams) { + return (*os_build_xattr_streams)(jcr, ff_pkt, os_default_xattr_streams[0]); } + return bsub_exit_nok; } -#endif -bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) +bsub_exit_code parse_xattr_streams(JCR *jcr, int stream) { -#if defined(HAVE_SUN_OS) - return solaris_build_xattr_streams(jcr, ff_pkt); -#elif defined(HAVE_DARWIN_OS) - return darwin_build_xattr_streams(jcr, ff_pkt); -#elif defined(HAVE_FREEBSD_OS) - return freebsd_build_xattr_streams(jcr, ff_pkt); -#elif defined(HAVE_LINUX_OS) - return linux_build_xattr_streams(jcr, ff_pkt); -#elif defined(HAVE_NETBSD_OS) - return netbsd_build_xattr_streams(jcr, ff_pkt); -#endif -} + int cnt; -bool parse_xattr_stream(JCR *jcr, int stream) -{ - /* - * Based on the stream being passed in dispatch to the right function - * for parsing and restoring a specific xattr. The platform determines - * which streams are recognized and parsed and which are handled by - * the default case and ignored. As only one of the platform defines - * is true per compile we never end up with duplicate switch values. - */ - switch (stream) { -#if defined(HAVE_SUN_OS) -#if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED) - case STREAM_XATTR_SOLARIS_SYS: -#endif - case STREAM_XATTR_SOLARIS: - return solaris_parse_xattr_stream(jcr, stream); -#elif defined(HAVE_DARWIN_OS) - case STREAM_XATTR_DARWIN: - return darwin_parse_xattr_stream(jcr, stream); -#elif defined(HAVE_FREEBSD_OS) - case STREAM_XATTR_FREEBSD: - return freebsd_parse_xattr_stream(jcr, stream); -#elif defined(HAVE_LINUX_OS) - case STREAM_XATTR_LINUX: - return linux_parse_xattr_stream(jcr, stream); -#elif defined(HAVE_NETBSD_OS) - case STREAM_XATTR_NETBSD: - return netbsd_parse_xattr_stream(jcr, stream); -#endif - default: + if (os_parse_xattr_streams) { /* - * Issue a warning and discard the message. But pretend the restore was ok. + * See if we can parse this stream, and ifso give it a try. */ - Qmsg2(jcr, M_WARNING, 0, - _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), - jcr->last_fname, stream); - return true; - } /* end switch (stream) */ + for (cnt = 0; cnt < sizeof(os_default_xattr_streams) / sizeof(int); cnt++) { + if (os_default_xattr_streams[cnt] == stream) { + return (*os_parse_xattr_streams)(jcr, stream); + } + } + } + /* + * Issue a warning and discard the message. But pretend the restore was ok. + */ + Jmsg2(jcr, M_WARNING, 0, + _("Can't restore Extended Attributes of %s - incompatible xattr stream encountered - %d\n"), + jcr->last_fname, stream); + return bsub_exit_nok; } - #endif diff --git a/bacula/src/filed/xattr.h b/bacula/src/filed/xattr.h index 2adec4fb97..ba66e1de4f 100644 --- a/bacula/src/filed/xattr.h +++ b/bacula/src/filed/xattr.h @@ -52,7 +52,6 @@ typedef struct xattr { typedef struct xattr_link_cache_entry { uint32_t inum; char target[PATH_MAX]; - struct xattr_link_cache_entry *next; } xattr_link_cache_entry_t; /*