From b089dc37d3cd08b58c171723a2c00cfcdc66cedc Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Fri, 24 Sep 2010 21:09:56 +0200 Subject: [PATCH] Added support for TRU64 Extended Attributes interface. --- bacula/src/baconfig.h | 5 +- bacula/src/filed/acl.c | 8 +- bacula/src/filed/restore.c | 1 + bacula/src/filed/xattr.c | 313 +++++++++++++++++++++++++++++++++- bacula/src/findlib/bfile.c | 6 +- bacula/src/findlib/fstype.c | 4 +- bacula/src/lib/mntent_cache.c | 8 +- bacula/src/stored/bscan.c | 1 + bacula/src/stored/dev.c | 2 +- 9 files changed, 326 insertions(+), 22 deletions(-) diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 7cea63d155..b4f62ff649 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -306,6 +306,7 @@ void InitWinAPIWrapper(); #define STREAM_ACL_AIX_NFS4 1016 /* AIX specific string representation from * aclx_printStr (NFSv4 acl) */ +#define STREAM_XATTR_TRU64 1991 /* TRU64 specific extended attributes */ #define STREAM_XATTR_AIX 1992 /* AIX specific extended attributes */ #define STREAM_XATTR_OPENBSD 1993 /* OpenBSD specific extended attributes */ #define STREAM_XATTR_SOLARIS_SYS 1994 /* Solaris specific extensible attributes or @@ -698,7 +699,7 @@ extern int thr_setconcurrency(int); #endif -#if defined(HAVE_DARWIN_OS) || defined(HAVE_OSF1_OS) +#if defined(HAVE_DARWIN_OS) || defined(HAVE_TRU64_OS) /* Apparently someone forgot to wrap getdomainname as a C function */ extern "C" int getdomainname(char *name, int len); #endif @@ -745,7 +746,7 @@ extern "C" int setdomainname(char *name, int namelen); #endif /* HAVE_HPUX_OS */ -#ifdef HAVE_OSF1_OS +#ifdef HAVE_TRU64_OS extern "C" int fchdir(int filedes); extern "C" long gethostid(void); extern "C" int mknod(const char *path, int mode, dev_t device ); diff --git a/bacula/src/filed/acl.c b/bacula/src/filed/acl.c index e3be782f3a..d3a4d2dcda 100644 --- a/bacula/src/filed/acl.c +++ b/bacula/src/filed/acl.c @@ -404,7 +404,7 @@ static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = aix_parse_ #elif defined(HAVE_DARWIN_OS) || \ defined(HAVE_FREEBSD_OS) || \ defined(HAVE_IRIX_OS) || \ - defined(HAVE_OSF1_OS) || \ + defined(HAVE_TRU64_OS) || \ defined(HAVE_LINUX_OS) #include @@ -457,7 +457,7 @@ static acl_type_t bac_to_os_acltype(bacl_type acltype) #ifdef ACL_TYPE_DEFAULT_DIR case BACL_TYPE_DEFAULT_DIR: /** - * OSF1 has an additional acl type named ACL_TYPE_DEFAULT_DIR. + * TRU64 has an additional acl type named ACL_TYPE_DEFAULT_DIR. */ ostype = ACL_TYPE_DEFAULT_DIR; break; @@ -534,7 +534,7 @@ static bool acl_is_trivial(acl_t acl) return false; } return true; -#elif defined(HAVE_OSF1_OS) +#elif defined(HAVE_TRU64_OS) int count; ace = acl->acl_first; @@ -879,7 +879,7 @@ static bacl_exit_code generic_parse_acl_streams(JCR *jcr, int stream) static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = generic_build_acl_streams; static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = generic_parse_acl_streams; -#elif defined(HAVE_OSF1_OS) +#elif defined(HAVE_TRU64_OS) /** * Define the supported ACL streams for this OS diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 0832b99be1..c06d0c5e85 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -687,6 +687,7 @@ void do_restore(JCR *jcr) } break; + case STREAM_XATTR_TRU64: case STREAM_XATTR_AIX: case STREAM_XATTR_OPENBSD: case STREAM_XATTR_SOLARIS_SYS: diff --git a/bacula/src/filed/xattr.c b/bacula/src/filed/xattr.c index 55b814c89f..49b4788410 100644 --- a/bacula/src/filed/xattr.c +++ b/bacula/src/filed/xattr.c @@ -121,14 +121,9 @@ static bxattr_exit_code send_xattr_stream(JCR *jcr, int stream) /* * First some generic functions for OSes that use the same xattr encoding scheme. + * Currently for all OSes except for Solaris. */ -#if defined(HAVE_AIX_OS) || \ - defined(HAVE_DARWIN_OS) || \ - defined(HAVE_LINUX_OS) || \ - defined(HAVE_NETBSD_OS) || \ - defined(HAVE_FREEBSD_OS) || \ - defined(HAVE_OPENBSD_OS) - +#if !defined(HAVE_SUN_OS) static void xattr_drop_internal_table(alist *xattr_value_list) { xattr_t *current_xattr; @@ -1371,6 +1366,310 @@ bail_out: static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = bsd_build_xattr_streams; static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = bsd_parse_xattr_streams; +#elif defined(HAVE_TRU64_OS) + +#if !defined(HAVE_GETPROPLIST) || \ + !defined(HAVE_GET_PROPLIST_ENTRY) || \ + !defined(HAVE_SIZEOF_PROPLIST_ENTRY) || \ + !defined(HAVE_ADD_PROPLIST_ENTRY) || \ + !defined(HAVE_SETPROPLIST) +#error "Missing full support for the Extended Attributes functions." +#endif + +#ifdef HAVE_SYS_PROPLIST_H +#include +#else +#error "Missing sys/proplist.h header file" +#endif + +/* + * Define the supported XATTR streams for this OS + */ +static int os_default_xattr_streams[1] = { STREAM_XATTR_TRU64 }; +static const char *xattr_acl_skiplist[1] = { NULL }; +static const char *xattr_skiplist[1] = { NULL }; + +static bxattr_exit_code tru64_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt) +{ + char *bp, + *xattr_name, + *xattr_value; + int xattr_count = 0; + int32_t *flags, + *xattr_value_len; + int32_t xattr_list_len, + xattrbuf_size, + xattrbuf_min_size; + uint32_t expected_serialize_len = 0; + xattr_t *current_xattr; + alist *xattr_value_list = NULL; + struct proplistname_args prop_args; + bxattr_exit_code retval = bxattr_exit_error; + POOLMEM *xattrbuf = get_pool_memory(PM_MESSAGE); + berrno be; + + xattrbuf_size = sizeof_pool_memory(xattrbuf); + xattrbuf_min_size = 0; + xattr_list_len = getproplist(jcr->last_fname, 1, &prop_args, xattrbuf_size, + xattrbuf, &xattrbuf_min_size); + + /** + * See what xattr are available. + */ + switch (xattr_list_len) { + case -1: + switch (errno) { + case EOPNOTSUPP: + retval = bacl_exit_ok; + goto bail_out; + default: + Mmsg2(jcr->errmsg, _("getproplist error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "getproplist error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + goto bail_out; + } + break; + case 0: + if (xattrbuf_min_size) { + /** + * The buffer isn't big enough to hold the xattr data, we now have + * a minimum buffersize so we resize the buffer and try again. + */ + xattrbuf = check_pool_memory_size(xattrbuf, xattrbuf_min_size + 1); + xattrbuf_size = xattrbuf_min_size + 1; + xattr_list_len = getproplist(jcr->last_fname, 1, &prop_args, xattrbuf_size, + xattrbuf, &xattrbuf_min_size); + switch (xattr_list_len) { + case -1: + switch (errno) { + case EOPNOTSUPP: + retval = bacl_exit_ok; + goto bail_out; + default: + Mmsg2(jcr->errmsg, _("getproplist error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "getproplist error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + goto bail_out; + } + break; + case 0: + /** + * This should never happen as we sized the buffer according to the minimumsize + * returned by a previous getproplist call. If it does happen things are fishy and + * we are better of forgetting this xattr as it seems its list is changing at this + * exact moment so we can never make a good backup copy of it. + */ + retval = bacl_exit_ok; + goto bail_out; + default: + break; + } + } else { + /** + * No xattr on file. + */ + retval = bacl_exit_ok; + goto bail_out; + } + break; + default: + break; + } + + xattr_value_list = New(alist(10, not_owned_by_alist)); + + /** + * Walk the list of extended attributes names and retrieve the data. + * We already count the bytes needed for serializing the stream later on. + */ + bp = xattrbuf; + while (xattrbuf_size > 0) { + /* + * Call getproplist_entry to initialize name and value + * pointers to entries position within buffer. + */ + xattrbuf_size -= get_proplist_entry(&xattr_name, &flags, &xattr_value_len, &xattr_value, &bp); + + /* + * On some OSes you also get the acls in the extented attribute list. + * So we check if we are already backing up acls and if we do we + * don't store the extended attribute with the same info. + */ + if (ff_pkt->flags & FO_ACL) { + for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) { + if (bstrcmp(xattr_name, xattr_acl_skiplist[cnt])) { + skip_xattr = true; + break; + } + } + } + + /* + * On some OSes we want to skip certain xattrs which are in the xattr_skiplist array. + */ + if (!skip_xattr) { + for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) { + if (bstrcmp(xattr_name, xattr_skiplist[cnt])) { + skip_xattr = true; + break; + } + } + } + + if (skip_xattr) { + continue; + } + + /* + * Each xattr valuepair starts with a magic so we can parse it easier. + */ + current_xattr = (xattr_t *)malloc(sizeof(xattr_t)); + current_xattr->magic = XATTR_MAGIC; + expected_serialize_len += sizeof(current_xattr->magic); + + current_xattr->name_length = strlen(xattr_name); + current_xattr->name = bstrdup(xattr_name); + + expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length; + + current_xattr->value_length = *xattr_value_len; + current_xattr->value = (char *)malloc(current_xattr->value_length); + memcpy(current_xattr->value, xattr_value, current_xattr->value_length); + + expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length; + + /* + * Protect ourself against things getting out of hand. + */ + if (expected_serialize_len >= MAX_XATTR_STREAM) { + Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"), + jcr->last_fname, MAX_XATTR_STREAM); + free(current_xattr->value); + free(current_xattr->name); + free(current_xattr); + goto bail_out; + } + + xattr_value_list->append(current_xattr); + xattr_count++; + } + + /* + * If we found any xattr send them to the SD. + */ + if (xattr_count > 0) { + /* + * Serialize the datastream. + */ + if (serialize_xattr_stream(jcr, expected_serialize_len, xattr_value_list) < expected_serialize_len) { + Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"), + jcr->last_fname); + Dmsg1(100, "Failed to serialize extended attributes on file \"%s\"\n", + jcr->last_fname); + goto bail_out; + } + + /* + * Send the datastream to the SD. + */ + retval = send_xattr_stream(jcr, os_default_xattr_streams[0]); + } + +bail_out: + if (xattr_value_list != NULL) { + xattr_drop_internal_table(xattr_value_list); + } + free_pool_memory(xattrbuf); + + return retval; +} + +static bxattr_exit_code tru64_parse_xattr_streams(JCR *jcr, int stream) +{ + char *bp, *xattrbuf; + int32_t xattrbuf_size, cnt; + xattr_t *current_xattr; + alist *xattr_value_list; + berrno be; + + xattr_value_list = New(alist(10, not_owned_by_alist)); + + if (unserialize_xattr_stream(jcr, xattr_value_list) != bxattr_exit_ok) { + xattr_drop_internal_table(xattr_value_list); + return bxattr_exit_error; + } + + /** + * See how big the propertylist must be. + */ + xattrbuf_size = 0; + foreach_alist(current_xattr, xattr_value_list) { + xattrbuf_size += sizeof_proplist_entry(current_xattr->name, current_xattr->value_length); + } + + xattrbuf = (char *)malloc(xattrbuf_size); + + cnt = 0; + bp = xattrbuf; + /** + * Add all value pairs to the proplist. + */ + foreach_alist(current_xattr, xattr_value_list) { + cnt = add_proplist_entry(current_xattr->name, 0, current_xattr->value_length, + current_xattr->value, &bp); + } + + if (cnt != xattrbuf_size) { + Mmsg1(jcr->errmsg, _("Unable create proper proplist to restore xattrs on file \"%s\"\n"), + jcr->last_fname); + Dmsg1(100, "Unable create proper proplist to restore xattrs on file \"%s\"\n", + jcr->last_fname); + free(xattrbuf); + goto bail_out; + } + + /** + * Restore the list of extended attributes on the file. + */ + cnt = setproplist(jcr->last_fname, 1, xattrbuf_size, xattrbuf); + switch (cnt) { + case -1: + switch (errno) { + case EOPNOTSUPP: + retval = bacl_exit_ok; + free(xattrbuf); + goto bail_out; + default: + Mmsg2(jcr->errmsg, _("setproplist error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "setproplist error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + free(xattrbuf); + goto bail_out; + } + break; + default: + break; + } + + free(xattrbuf); + + xattr_drop_internal_table(xattr_value_list); + return bxattr_exit_ok; + +bail_out: + xattr_drop_internal_table(xattr_value_list); + return bxattr_exit_error; +} + +/* + * Function pointers to the build and parse function to use for these xattrs. + */ +static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = tru64_build_xattr_streams; +static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = tru64_parse_xattr_streams; + #elif defined(HAVE_SUN_OS) /* * Solaris extended attributes were introduced in Solaris 9 diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index 6d2d797c6f..584902c380 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -160,9 +160,9 @@ const char *stream_to_ascii(int stream) case STREAM_ACL_LINUX_ACCESS_ACL: return _("Linux Specific Access ACL attribs"); case STREAM_ACL_TRU64_DEFAULT_ACL: - return _("OSF1 Specific Default ACL attribs"); + return _("TRU64 Specific Default ACL attribs"); case STREAM_ACL_TRU64_ACCESS_ACL: - return _("OSF1 Specific Access ACL attribs"); + return _("TRU64 Specific Access ACL attribs"); case STREAM_ACL_SOLARIS_ACLENT: return _("Solaris Specific ACL attribs"); case STREAM_ACL_SOLARIS_ACE: @@ -173,6 +173,8 @@ const char *stream_to_ascii(int stream) return _("AIX Specific ACL attribs"); case STREAM_ACL_AIX_NFS4: return _("AIX Specific ACL attribs"); + case STREAM_XATTR_TRU64: + return _("TRU64 Specific Extended attribs"); case STREAM_XATTR_AIX: return _("AIX Specific Extended attribs"); case STREAM_XATTR_OPENBSD: diff --git a/bacula/src/findlib/fstype.c b/bacula/src/findlib/fstype.c index 4765f9415b..21cd969546 100644 --- a/bacula/src/findlib/fstype.c +++ b/bacula/src/findlib/fstype.c @@ -53,7 +53,7 @@ "HAVE_NETBSD_OS\n" \ "HAVE_OPENBSD_OS\n" \ "HAVE_SUN_OS\n" \ - "HAVE_OSF1_OS\n" \ + "HAVE_TRU64_OS\n" \ "HAVE_WIN32\n" #define false 0 #define true 1 @@ -131,7 +131,7 @@ bool fstype(const char *fname, char *fs, int fslen) } #elif defined(HAVE_LINUX_OS) || \ - defined(HAVE_OSF1_OS) + defined(HAVE_TRU64_OS) #include #include "lib/mntent_cache.h" diff --git a/bacula/src/lib/mntent_cache.c b/bacula/src/lib/mntent_cache.c index c130fa2d95..998dbdb6b9 100644 --- a/bacula/src/lib/mntent_cache.c +++ b/bacula/src/lib/mntent_cache.c @@ -41,10 +41,10 @@ * - DARWIN (OSX) * - IRIX * - AIX - * - OSF1 (True64) + * - TRU64 (True64) * - Solaris * - * Currently we only use this code for Linux and OSF1 based fstype determination. + * Currently we only use this code for Linux and TRU64 based fstype determination. * For the other OS-es we can use the fstype present in stat structure on those OS-es. * * This code replaces the big switch we used before based on SUPER_MAGIC present in @@ -88,7 +88,7 @@ #elif defined(HAVE_AIX_OS) #include #include -#elif defined(HAVE_OSF1_OS) +#elif defined(HAVE_TRU64_OS) #include #endif @@ -275,7 +275,7 @@ static void refresh_mount_cache(void) cnt++; } free(entries); -#elif defined(HAVE_OSF1_OS) +#elif defined(HAVE_TRU64_OS) struct statfs *entries, *current; struct stat st; int n_entries, cnt; diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 5c487c29ee..195448f73e 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -812,6 +812,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) /* Ignore Unix ACL attributes */ break; + case STREAM_XATTR_TRU64: case STREAM_XATTR_AIX: case STREAM_XATTR_OPENBSD: case STREAM_XATTR_SOLARIS_SYS: diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index 9fa2e31f52..e40948d538 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -1686,7 +1686,7 @@ void DEVICE::clrerror(int func) } #endif -/* Clear Subsystem Exception OSF1 */ +/* Clear Subsystem Exception TRU64 */ #ifdef MTCSE { struct mtop mt_com; -- 2.39.5