Improved the progress_is_active code to not overwrite the progress
[rsync/rsync.git] / xattrs.c
index 53363bd..b6a82e4 100644 (file)
--- a/xattrs.c
+++ b/xattrs.c
@@ -178,8 +178,9 @@ static char *get_xattr_data(const char *fname, const char *name, size_t *len_ptr
 
        if (!datum_len && !extra_len)
                extra_len = 1; /* request non-zero amount of memory */
-       if (datum_len + extra_len < datum_len /* checks for overflow */
-        || !(ptr = new_array(char, datum_len + extra_len)))
+       if (datum_len + extra_len < datum_len)
+               overflow_exit("get_xattr_data");
+       if (!(ptr = new_array(char, datum_len + extra_len)))
                out_of_memory("get_xattr_data");
 
        if (datum_len) {
@@ -287,6 +288,48 @@ int get_xattr(const char *fname, stat_x *sxp)
        return 0;
 }
 
+int copy_xattrs(const char *source, const char *dest)
+{
+       ssize_t list_len, name_len;
+       size_t datum_len;
+       char *name, *ptr;
+#ifdef HAVE_LINUX_XATTRS
+       int user_only = am_sender ? 0 : !am_root;
+#endif
+
+       /* This puts the name list into the "namebuf" buffer. */
+       if ((list_len = get_xattr_names(source)) < 0)
+               return -1;
+
+       for (name = namebuf; list_len > 0; name += name_len) {
+               name_len = strlen(name) + 1;
+               list_len -= name_len;
+
+#ifdef HAVE_LINUX_XATTRS
+               /* We always ignore the system namespace, and non-root
+                * ignores everything but the user namespace. */
+               if (user_only ? !HAS_PREFIX(name, USER_PREFIX)
+                             : HAS_PREFIX(name, SYSTEM_PREFIX))
+                       continue;
+#endif
+
+               datum_len = 0;
+               if (!(ptr = get_xattr_data(source, name, &datum_len, 0)))
+                       return -1;
+               if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
+                       int save_errno = errno ? errno : EINVAL;
+                       rsyserr(FERROR_XFER, errno,
+                               "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
+                               dest, name);
+                       errno = save_errno;
+                       return -1;
+               }
+               free(ptr);
+       }
+
+       return 0;
+}
+
 static int find_matching_xattr(item_list *xalp)
 {
        size_t i, j;
@@ -350,15 +393,14 @@ int send_xattr(stat_x *sxp, int f)
                int count = sxp->xattr->count;
                write_varint(f, count);
                for (rxa = sxp->xattr->items; count--; rxa++) {
-                       int name_len = rxa->name_len;
+                       size_t name_len = rxa->name_len;
                        const char *name = rxa->name;
                        /* Strip the rsync prefix from disguised namespaces. */
-                       if (
+                       if (name_len > RPRE_LEN
 #ifdef HAVE_LINUX_XATTRS
-                           am_root < 0
+                        && am_root < 0
 #endif
-                        && name_len > RPRE_LEN && name[RPRE_LEN] != '%'
-                        && HAS_PREFIX(name, RSYNC_PREFIX)) {
+                        && name[RPRE_LEN] != '%' && HAS_PREFIX(name, RSYNC_PREFIX)) {
                                name += RPRE_LEN;
                                name_len -= RPRE_LEN;
                        }
@@ -558,7 +600,7 @@ int recv_xattr_request(struct file_struct *file, int f_in)
                rxa->datum_len = read_varint(f_in);
 
                if (rxa->name_len + rxa->datum_len < rxa->name_len)
-                       out_of_memory("recv_xattr_request"); /* overflow */
+                       overflow_exit("recv_xattr_request");
                rxa->datum = new_array(char, rxa->datum_len + rxa->name_len);
                if (!rxa->datum)
                        out_of_memory("recv_xattr_request");
@@ -610,10 +652,9 @@ void receive_xattr(struct file_struct *file, int f)
                size_t datum_len = read_varint(f);
                size_t dget_len = datum_len > MAX_FULL_DATUM ? 1 + MAX_DIGEST_LEN : datum_len;
                size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0;
-               if (dget_len + extra_len < dget_len)
-                       out_of_memory("receive_xattr"); /* overflow */
-               if (dget_len + extra_len + name_len < dget_len)
-                       out_of_memory("receive_xattr"); /* overflow */
+               if ((dget_len + extra_len < dget_len)
+                || (dget_len + extra_len + name_len < dget_len))
+                       overflow_exit("receive_xattr");
                ptr = new_array(char, dget_len + extra_len + name_len);
                if (!ptr)
                        out_of_memory("receive_xattr");
@@ -699,7 +740,8 @@ static int rsync_xal_set(const char *fname, item_list *xalp,
        ssize_t list_len;
        size_t i, len;
        char *name, *ptr, sum[MAX_DIGEST_LEN];
-       int name_len, ret = 0;
+       size_t name_len;
+       int ret = 0;
 
        /* This puts the current name list into the "namebuf" buffer. */
        if ((list_len = get_xattr_names(fname)) < 0)