#include "bacula.h"
#include "filed.h"
-#include "xattr.h"
#if !defined(HAVE_XATTR)
/*
/*
* Sanity check
*/
- if (jcr->xattr_data_len <= 0)
+ if (jcr->xattr_data->content_length <= 0) {
return bxattr_exit_ok;
+ }
/*
* Send header
/*
* Send the buffer to the storage deamon
*/
- Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data);
+ Dmsg1(400, "Backing up XATTR <%s>\n", jcr->xattr_data->content);
msgsave = sd->msg;
- sd->msg = jcr->xattr_data;
- sd->msglen = jcr->xattr_data_len;
+ sd->msg = jcr->xattr_data->content;
+ sd->msglen = jcr->xattr_data->content_length;
if (!sd->send()) {
sd->msg = msgsave;
sd->msglen = 0;
*/
#if defined(HAVE_DARWIN_OS)
static int os_default_xattr_streams[1] = { STREAM_XATTR_DARWIN };
+static const char *xattr_acl_skiplist[2] = { "com.apple.system.Security", NULL };
+static const char *xattr_skiplist[3] = { "com.apple.system.extendedsecurity", "com.apple.ResourceFork", NULL };
#elif defined(HAVE_FREEBSD_OS)
static int os_default_xattr_streams[1] = { STREAM_XATTR_FREEBSD };
+static const char *xattr_acl_skiplist[1] = { NULL };
+static const char *xattr_skiplist[1] = { NULL };
#elif defined(HAVE_LINUX_OS)
static int os_default_xattr_streams[1] = { STREAM_XATTR_LINUX };
+static const char *xattr_acl_skiplist[2] = { "system.posix_acl_access", NULL };
+static const char *xattr_skiplist[1] = { NULL };
#elif defined(HAVE_NETBSD_OS)
static int os_default_xattr_streams[1] = { STREAM_XATTR_NETBSD };
+static const char *xattr_acl_skiplist[1] = { NULL };
+static const char *xattr_skiplist[1] = { NULL };
#endif
/*
* Make sure the serialized stream fits in the poolmem buffer.
* We allocate some more to be sure the stream is gonna fit.
*/
- jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, expected_serialize_len + 10);
- ser_begin(jcr->xattr_data, expected_serialize_len + 10);
+ jcr->xattr_data->content = check_pool_memory_size(jcr->xattr_data->content, expected_serialize_len + 10);
+ ser_begin(jcr->xattr_data->content, expected_serialize_len + 10);
/*
* Walk the list of xattrs and serialize the data.
ser_bytes(current_xattr->value, current_xattr->value_length);
}
- ser_end(jcr->xattr_data, expected_serialize_len + 10);
- jcr->xattr_data_len = ser_length(jcr->xattr_data);
- return jcr->xattr_data_len;
+ ser_end(jcr->xattr_data->content, expected_serialize_len + 10);
+ jcr->xattr_data->content_length = ser_length(jcr->xattr_data->content);
+ return jcr->xattr_data->content_length;
}
static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
{
- int count = 0;
+ bool skip_xattr;
+ int cnt, xattr_count = 0;
int32_t xattr_list_len,
xattr_value_len;
uint32_t expected_serialize_len = 0;
*/
bp = xattr_list;
while ((bp - xattr_list) + 1 < xattr_list_len) {
-#if defined(HAVE_LINUX_OS)
+ skip_xattr = false;
+
/*
- * On Linux you also get the acls in the extented attribute list.
+ * 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) == 0 || strcmp(bp, "system.posix_acl_access"))
- count++;
-#else
- count++;
-#endif
+ if (ff_pkt->flags & FO_ACL) {
+ for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
+ if (!strcmp(bp, 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 (!strcmp(bp, xattr_skiplist[cnt])) {
+ skip_xattr = true;
+ break;
+ }
+ }
+ }
+
+ if (!skip_xattr) {
+ xattr_count++;
+ }
bp = strchr(bp, '\0') + 1;
}
- if (count == 0) {
+ if (xattr_count == 0) {
retval = bxattr_exit_ok;
goto bail_out;
}
* Allocate enough room to hold all extended attributes.
* After allocating the storage make sure its empty by zeroing it.
*/
- xattr_value_list = (xattr_t *)malloc(count * sizeof(xattr_t));
- memset((caddr_t)xattr_value_list, 0, count * sizeof(xattr_t));
+ xattr_value_list = (xattr_t *)malloc(xattr_count * sizeof(xattr_t));
+ memset((caddr_t)xattr_value_list, 0, xattr_count * sizeof(xattr_t));
/*
* Walk the list of extended attributes names and retrieve the data.
current_xattr = xattr_value_list;
bp = xattr_list;
while ((bp - xattr_list) + 1 < xattr_list_len) {
-#if defined(HAVE_LINUX_OS)
+ skip_xattr = false;
+
/*
- * On Linux you also get the acls in the extented attribute list.
+ * 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 && !strcmp(bp, "system.posix_acl_access")) {
+ if (ff_pkt->flags & FO_ACL) {
+ for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
+ if (!strcmp(bp, 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 (!strcmp(bp, xattr_skiplist[cnt])) {
+ skip_xattr = true;
+ break;
+ }
+ }
+ }
+
+ if (skip_xattr) {
bp = strchr(bp, '\0') + 1;
continue;
}
-#endif
/*
* Each xattr valuepair starts with a magic so we can parse it easier.
* Start unserializing the data. We keep on looping while we have not
* unserialized all bytes in the stream.
*/
- unser_begin(jcr->xattr_data, jcr->xattr_data_len);
- while (unser_length(jcr->xattr_data) < jcr->xattr_data_len) {
+ unser_begin(jcr->xattr_data->content, jcr->xattr_data->content_length);
+ while (unser_length(jcr->xattr_data->content) < jcr->xattr_data->content_length) {
/*
* First make sure the magic is present. This way we can easily catch corruption.
* Any missing MAGIC is fatal we do NOT try to continue.
free(current_xattr.value);
}
- unser_end(jcr->xattr_data, jcr->xattr_data_len);
+ unser_end(jcr->xattr_data->content, jcr->xattr_data->content_length);
return retval;
}
static xattr_link_cache_entry_t *find_xattr_link_cache_entry(JCR *jcr, ino_t inum)
{
xattr_link_cache_entry_t *ptr;
- xattr_private_data_t *xpd = (xattr_private_data_t *)jcr->xattr_private_data;
- foreach_alist(ptr, xpd->xattr_link_cache) {
+ foreach_alist(ptr, jcr->xattr_data->link_cache) {
if (ptr && ptr->inum == inum) {
return ptr;
}
static void add_xattr_link_cache_entry(JCR *jcr, ino_t inum, char *target)
{
xattr_link_cache_entry_t *ptr;
- xattr_private_data_t *xpd = (xattr_private_data_t *)jcr->xattr_private_data;
ptr = (xattr_link_cache_entry_t *)malloc(sizeof(xattr_link_cache_entry_t));
memset((caddr_t)ptr, 0, sizeof(xattr_link_cache_entry_t));
ptr->inum = inum;
bstrncpy(ptr->target, target, sizeof(ptr->target));
- xpd->xattr_link_cache->append(ptr);
+ jcr->xattr_data->link_cache->append(ptr);
}
#if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
char *acl_text = NULL;
char attribs[MAXSTRING];
char buffer[BUFSIZ];
- xattr_private_data_t *xpd = (xattr_private_data_t *)jcr->xattr_private_data;
bxattr_exit_code retval = bxattr_exit_error;
berrno be;
cnt = bsnprintf(buffer, sizeof(buffer), "%s%c%s%c%s%c",
target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
break;
-
case S_IFDIR:
/*
* Get any acl on the xattr.
*/
if (toplevel_hidden_dir) {
/*
- * Save the data for later storage when we encounter a real xattr.
- * Encode the stat struct into an ASCII representation and jump out of the function.
+ * Save the data for later storage when we encounter a real xattr. We store the data
+ * in the jcr->xattr_data->content buffer and flush that just before sending out the
+ * first real xattr. Encode the stat struct into an ASCII representation and jump
+ * out of the function.
*/
encode_stat(attribs, &st, 0, stream);
- xpd->toplevel_hidden_dir_xattr_data_len = bsnprintf(xpd->toplevel_hidden_dir_xattr_data,
- sizeof(xpd->toplevel_hidden_dir_xattr_data),
- "%s%c%s%c%s%c",
- target_attrname, 0, attribs, 0,
- (acl_text) ? acl_text : "", 0);
+ cnt = bsnprintf(buffer, sizeof(buffer),
+ "%s%c%s%c%s%c",
+ target_attrname, 0, attribs, 0, (acl_text) ? acl_text : "", 0);
+ pm_memcpy(jcr->xattr_data->content, buffer, cnt);
+ jcr->xattr_data->content_length = cnt;
goto bail_out;
} else {
/*
cnt = bsnprintf(buffer, sizeof(buffer),
"%s%c%s%c%s%c",
target_attrname, 0, attribs, 0, xlce->target, 0);
- pm_memcpy(jcr->xattr_data, buffer, cnt);
- jcr->xattr_data_len = cnt;
+ pm_memcpy(jcr->xattr_data->content, buffer, cnt);
+ jcr->xattr_data->content_length = cnt;
retval = send_xattr_stream(jcr, stream);
/*
}
}
break;
-
case S_IFLNK:
/*
* The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
cnt = bsnprintf(buffer, sizeof(buffer),
"%s%c%s%c%s%c",
target_attrname, 0, attribs, 0, link_source, 0);
- pm_memcpy(jcr->xattr_data, buffer, cnt);
- jcr->xattr_data_len = cnt;
+ pm_memcpy(jcr->xattr_data->content, buffer, cnt);
+ jcr->xattr_data->content_length = cnt;
retval = send_xattr_stream(jcr, stream);
+ if (retval == bxattr_exit_ok) {
+ jcr->xattr_data->nr_saved++;
+ }
+
/*
* For a soft linked file we are ready now, no need to recursively save the attributes.
*/
goto bail_out;
-
default:
goto bail_out;
}
/*
- * See if this is the first real xattr being saved. If it is save the toplevel_hidden_dir attributes first.
+ * See if this is the first real xattr being saved.
+ * If it is save the toplevel_hidden_dir attributes first.
+ * This is easy as its stored already in the jcr->xattr_data->content buffer.
*/
- if (xpd->nr_xattr_saved == 0) {
- pm_memcpy(jcr->xattr_data, xpd->toplevel_hidden_dir_xattr_data, xpd->toplevel_hidden_dir_xattr_data_len);
- jcr->xattr_data_len = xpd->toplevel_hidden_dir_xattr_data_len;
+ if (jcr->xattr_data->nr_saved == 0) {
retval = send_xattr_stream(jcr, STREAM_XATTR_SOLARIS);
+ if (retval != bxattr_exit_ok) {
+ goto bail_out;
+ }
+ jcr->xattr_data->nr_saved++;
}
- pm_memcpy(jcr->xattr_data, buffer, cnt);
- jcr->xattr_data_len = cnt;
+ pm_memcpy(jcr->xattr_data->content, buffer, cnt);
+ jcr->xattr_data->content_length = cnt;
/*
* Only dump the content of regular files.
}
while ((cnt = read(attrfd, buffer, sizeof(buffer))) > 0) {
- jcr->xattr_data = check_pool_memory_size(jcr->xattr_data, jcr->xattr_data_len + cnt);
- memcpy(jcr->xattr_data + jcr->xattr_data_len, buffer, cnt);
- jcr->xattr_data_len += cnt;
+ jcr->xattr_data->content = check_pool_memory_size(jcr->xattr_data->content, jcr->xattr_data->content_length + cnt);
+ memcpy(jcr->xattr_data->content + jcr->xattr_data->content_length, buffer, cnt);
+ jcr->xattr_data->content_length += cnt;
}
if (cnt < 0) {
if (retval) {
retval = send_xattr_stream(jcr, stream);
- xpd->nr_xattr_saved++;
+ if (retval == bxattr_exit_ok) {
+ jcr->xattr_data->nr_saved++;
+ }
}
/*
* Parse the xattr stream. First the part that is the same for all xattrs.
*/
used_bytes = 0;
- total_bytes = jcr->xattr_data_len;
+ total_bytes = jcr->xattr_data->content_length;
/*
* The name of the target xattr has a leading / we are not interested
* in that so skip it when decoding the string. We always start a the /
* of the xattr space anyway.
*/
- target_attrname = jcr->xattr_data + 1;
+ target_attrname = jcr->xattr_data->content + 1;
if ((bp = strchr(target_attrname, '\0')) == (char *)NULL ||
- (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
+ (used_bytes = (bp - jcr->xattr_data->content)) >= (total_bytes - 1)) {
goto parse_error;
}
attribs = ++bp;
* Decode the next field (acl_text).
*/
if ((bp = strchr(attribs, '\0')) == (char *)NULL ||
- (used_bytes = (bp - jcr->xattr_data)) >= (total_bytes - 1)) {
+ (used_bytes = (bp - jcr->xattr_data->content)) >= (total_bytes - 1)) {
goto parse_error;
}
acl_text = ++bp;
goto bail_out;
} else {
if ((bp = strchr(acl_text, '\0')) == (char *)NULL ||
- (used_bytes = (bp - jcr->xattr_data)) >= total_bytes) {
+ (used_bytes = (bp - jcr->xattr_data->content)) >= total_bytes) {
goto parse_error;
}
* Restore the actual data.
*/
if (st.st_size > 0) {
- used_bytes = (data - jcr->xattr_data);
+ used_bytes = (data - jcr->xattr_data->content);
cnt = total_bytes - used_bytes;
/*
static bxattr_exit_code solaris_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
{
char cwd[PATH_MAX];
- xattr_private_data_t *xpd;
bxattr_exit_code retval = bxattr_exit_ok;
/*
* If not just pretend things went ok.
*/
if (pathconf(jcr->last_fname, _PC_XATTR_EXISTS) > 0) {
- xpd = (xattr_private_data_t *)malloc(sizeof(xattr_private_data_t));
- memset((caddr_t)xpd, 0, sizeof(xattr_private_data_t));
- xpd->xattr_link_cache = New(alist(10, not_owned_by_alist));
- jcr->xattr_private_data = (void *)xpd;
+ jcr->xattr_data->nr_saved = 0;
+ jcr->xattr_data->link_cache = New(alist(10, not_owned_by_alist));
/*
* As we change the cwd in the save function save the current cwd
getcwd(cwd, sizeof(cwd));
retval = solaris_save_xattrs(jcr, NULL, NULL);
chdir(cwd);
- delete xpd->xattr_link_cache;
- xpd->xattr_link_cache = NULL;
- free(xpd);
- jcr->xattr_private_data = NULL;
+ delete jcr->xattr_data->link_cache;
+ jcr->xattr_data->link_cache = NULL;
}
return retval;
}