+@@ -365,4 +384,100 @@ int set_xattr(const char *fname, const s
+ return rsync_xal_set(fname, lst + ndx); /* TODO: This needs to return 1 if no xattrs changed! */
+ }
+
++int get_stat_xattr(const char *fname, int fd, STRUCT_STAT *st)
++{
++ int mode, rdev_major, rdev_minor, uid, gid, len;
++ char buf[256];
++
++ if (fname)
++ len = sys_lgetxattr(fname, FAKE_XATTR, buf, sizeof buf - 1);
++ else
++ len = sys_fgetxattr(fd, FAKE_XATTR, buf, sizeof buf - 1);
++ if (len < 0 || len >= (int)sizeof buf) {
++ if (errno == ENOTSUP || errno == ENOATTR)
++ return -1;
++ return -1;
++ }
++ buf[len] = '\0';
++
++ if (sscanf(buf, "%o %d,%d %d:%d",
++ &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) {
++ errno = EINVAL;
++ return -1;
++ }
++
++ st->st_mode = mode;
++ st->st_rdev = MAKEDEV(rdev_major, rdev_minor);
++ st->st_uid = uid;
++ st->st_gid = gid;
++
++ return 0;
++}
++
++int set_stat_xattr(const char *fname, struct file_struct *file)
++{
++ STRUCT_STAT fst, xst;
++ dev_t rdev;
++
++ if (dry_run)
++ return 0;
++
++ if (x_stat(fname, &fst, &xst) < 0)
++ return -1;
++
++ if (IS_DEVICE(file->mode) || IS_SPECIAL(file->mode))
++ rdev = file->u.rdev;
++ else
++ rdev = 0;
++
++ /* This is the mode that the file will be. */
++ fst.st_mode &= ~CHMOD_BITS;
++ fst.st_mode |= (S_ISDIR(file->mode) ? 0777 : 0666) & ~orig_umask;
++ if (!IS_DEVICE(fst.st_mode) && !IS_SPECIAL(fst.st_mode))
++ fst.st_rdev = 0; /* just in case */
++
++ if (fst.st_mode == file->mode && fst.st_rdev == rdev
++ && fst.st_uid == file->uid && fst.st_gid == file->gid) {
++ /* xst.st_mode will be 0 if there's no current stat xattr */
++ if (xst.st_mode && sys_lremovexattr(fname, FAKE_XATTR) < 0)
++ return -2;
++ return 0;
++ }
++
++ if (xst.st_mode != file->mode || xst.st_rdev != rdev
++ || xst.st_uid != file->uid || xst.st_gid != file->gid) {
++ char buf[256];
++ int len = snprintf(buf, sizeof buf, "%o %u,%u %u:%u",
++ (int)file->mode,
++ (int)major(rdev), (int)minor(rdev),
++ (int)file->uid, (int)file->gid);
++ return sys_lsetxattr(fname, FAKE_XATTR, buf, len, 0);
++ }
++ return 0;
++}
++
++int x_stat(const char *fname, STRUCT_STAT *fst, STRUCT_STAT *xst)
++{
++ int ret = do_stat(fname, fst);
++ if (get_stat_xattr(fname, -1, xst? xst : fst) != 0 && xst)
++ xst->st_mode = 0;
++ return ret;
++}
++
++int x_lstat(const char *fname, STRUCT_STAT *fst, STRUCT_STAT *xst)
++{
++ int ret = do_lstat(fname, fst);
++ if (get_stat_xattr(fname, -1, xst? xst : fst) != 0 && xst)
++ xst->st_mode = 0;
++ return ret;
++}
++
++int x_fstat(int fd, STRUCT_STAT *fst, STRUCT_STAT *xst)
++{
++ int ret = do_fstat(fd, fst);
++ if (get_stat_xattr(NULL, fd, xst? xst : fst) != 0 && xst)
++ xst->st_mode = 0;
++ return ret;
++}
++
+ #endif /* SUPPORT_XATTRS */