Avoid directory permission issues with --fake-super.
[rsync/rsync.git] / lib / sysxattrs.c
index 40619e3..d55ee0c 100644 (file)
@@ -133,20 +133,20 @@ static ssize_t read_xattr(int attrfd, void *buf, size_t buflen)
        STRUCT_STAT sb;
        ssize_t ret;
 
-       if (fstat(fd, &sb) < 0)
+       if (fstat(attrfd, &sb) < 0)
                ret = -1;
        else if (sb.st_size > SSIZE_MAX) {
                errno = ERANGE;
                ret = -1;
-       } else if (size == 0)
+       } else if (buflen == 0)
                ret = sb.st_size;
-       else if (sb.st_size > size) {
+       else if (sb.st_size > buflen) {
                errno = ERANGE;
                ret = -1;
        } else {
                size_t bufpos;
-               for (bufpos = 0; bufpos < buflen; ) {
-                       ssize_t cnt = read(attrfd, buf + bufpos, buflen - bufpos);
+               for (bufpos = 0; bufpos < sb.st_size; ) {
+                       ssize_t cnt = read(attrfd, buf + bufpos, sb.st_size - bufpos);
                        if (cnt <= 0) {
                                if (cnt < 0 && errno == EINTR)
                                        continue;
@@ -193,7 +193,7 @@ int sys_lsetxattr(const char *path, const char *name, const void *value, size_t
        size_t bufpos;
        mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
 
-       if ((attrfd = attropen(path, name, O_CREAT|O_WRONLY|O_NOFOLLOW, mode)) < 0)
+       if ((attrfd = attropen(path, name, O_CREAT|O_TRUNC|O_WRONLY, mode)) < 0)
                return -1;
 
        for (bufpos = 0; bufpos < size; ) {
@@ -217,7 +217,7 @@ int sys_lremovexattr(const char *path, const char *name)
        int attrdirfd;
        int ret;
 
-       if ((attrdirfd = attropen(path, ".", O_RDWR)) < 0)
+       if ((attrdirfd = attropen(path, ".", O_RDONLY)) < 0)
                return -1;
 
        ret = unlinkat(attrdirfd, name, 0);
@@ -254,6 +254,8 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
                        continue;
 
                if ((ret += len+1) > size) {
+                       if (size == 0)
+                               continue;
                        ret = -1;
                        errno = ERANGE;
                        break;