Bug 6633 - Extended attributes under Solaris are not supported.
Summary: Extended attributes under Solaris are not supported.
Status: ASSIGNED
Alias: None
Product: rsync
Classification: Unclassified
Component: core (show other bugs)
Version: 3.0.6
Hardware: All Solaris
: P3 normal (vote)
Target Milestone: ---
Assignee: Wayne Davison
QA Contact: Rsync QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-08-12 19:52 UTC by Lloyd Parkes
Modified: 2009-09-03 07:30 UTC (History)
2 users (show)

See Also:


Attachments
Patch to add support for solaris extended attributes (3.72 KB, application/octet-stream)
2009-08-12 19:53 UTC, Lloyd Parkes
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Lloyd Parkes 2009-08-12 19:52:53 UTC
Solaris supports extended attributes, and I have written some code to add support for them. This has been tested with --fake-super. I'll attach the patch to thsi report once I work out how to do that.
Comment 1 Lloyd Parkes 2009-08-12 19:53:45 UTC
Created attachment 4550 [details]
Patch to add support for solaris extended attributes
Comment 2 Wayne Davison 2009-08-13 12:29:57 UTC
I had some preliminary Solaris xattr code in the git repo, though it had some bugs.  I used some ideas from your patch to get squash the ones I saw, but the result is not tested.  If you could snag the latest git repo or the latest "nightly" tar file and try it out, let me know if you find any problems.

Note that my version just ignores symlink xattrs, as I'm not liking the idea of attaching symlink xattrs to the parent directory.

I have been thinking that --fake-super should convert symlinks into regular files on a system where NO_SYMLINK_XATTRS is defined (saving the symlink either in the file contents or as a special rsync xattr), which would at least allow backups of symlink xattrs onto a system that doesn't support that.
Comment 3 Lloyd Parkes 2009-08-16 16:37:31 UTC
I thought of saving the symlink contents as normal file contents as well, but I wanted to keep my changes out of the core rsync code. Attaching the symlink attributes to the parent directory was carefully written to work for rsync and there are problems with my code that prevent it being more general.

I'll try the nightly tar. I'm pretty sure that my corporate firewalls are git hostile. I'll write some code to handle NO_SYMLINK_XATTRS in the next few days because it's a show stopper for me.
Comment 4 Enrico Cavalli 2009-08-31 03:56:26 UTC
I tried this patch which of course is much cleanear of the one I sent to the devel mailing list, but this does not work for me. I am only testing from linux to opensolaris using --fake-super

The rsync.%stat xattr is written correctly but i always get errors like these in reading:


rsync: failed to read xattr rsync.%stat for "/data/cavalli/test/.": Error 0 (0)
./

Still not sure where the problem is (
Comment 5 Enrico Cavalli 2009-08-31 04:54:38 UTC
I think the problem is that bufpos (and so ret) is always set to "-1" in this code ( in read_xattr).

If cnt==0 shouldn't this indicate that end of file is reached?

 for (bufpos = 0; bufpos < buflen; ) {
                        ssize_t cnt = read(attrfd, buf + bufpos, buflen - bufpos);
                        if (cnt <= 0) {
                                if (cnt < 0 && errno == EINTR)
                                        continue;
                                 bufpos = -1; 
                                break;
                        }
                        bufpos += cnt;
                }
                ret = bufpos;


Comment 6 Wayne Davison 2009-08-31 15:04:56 UTC
Make sure you're trying the latest version from the git repo, a nightly tar file, or a file grabbed from the unpacked files:

    http://rsync.samba.org/download.html

The code you cited fails on read() == 0 because it only tries to read data when the data isn't long enough yet, and an early EOF should be an error, AFAIK.
Comment 7 Enrico Cavalli 2009-09-01 01:11:21 UTC
I do not undestand you point. The last niglty snapshot and also the last git commit show the same results. Actually I put this line in the code to do some debugging:

 ssize_t cnt = read(attrfd, buf + bufpos, buflen - bufpos);
 rsyserr(FERROR_XFER, errno, "read %d bytes, buflen %d",cnt,buflen);


This clearly shows two reads 

rsync: read 13 bytes, buflen 255: Error 0 (0)
rsync: read 0 bytes, buflen 255: Error 0 (0)
rsync: failed to read xattr rsync.%stat for "/data/cavalli/test/.": Error 0 (0)

0 on the second read indicates EOF reached but not early EOF in this case I think: what is wrong with this reasoning?
Comment 8 Wayne Davison 2009-09-01 13:50:29 UTC
Aha.  The loop is being limited by buflen instead of sb.st_size.  Change this:

-               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);
Comment 9 Enrico Cavalli 2009-09-02 02:51:34 UTC
Thanks for the correction in comment #8. I have another small change to suggest:

-       if ((attrfd = attropen(path, name, O_CREAT|O_WRONLY|O_NOFOLLOW, mode)) < 0)
+       if ((attrfd = attropen(path, name, O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, mode)) < 0)


O_TRUNC is needed otherwise for instance if you change a file owner from 1002 to 0 you start with attribute set to

100640 0,0 1002:1002

and end up with this mess:

100640 0,0 0:02:1002

Also about O_NOFOLLOW: does it should avoid setting attributes from symlinks? From the open(2) manpage 
"   If the path names a symbolic link, open() fails and sets
         errno to ELOOP"

But unfortunately this does not work with attropen. There is also  AT_SYMLINK_NOFOLLOW but I do not exatly understand its job with fstatat...

The only way I came up was a stat of path...

Finally, what about opening a discussion about where/how to write attributes of symlinks?

Comment 10 Wayne Davison 2009-09-02 11:17:14 UTC
Thanks for the write fix.

The latest code turns a symlink into a file when using --fake-super on a system that has NO_SYMLINK_XATTRS defined in config.h.  You can snag that via git or the latest nightly tar file.
Comment 11 Enrico Cavalli 2009-09-03 04:18:48 UTC
(In reply to comment #10)
> Thanks for the write fix.
> 
> The latest code turns a symlink into a file when using --fake-super on a system
> that has NO_SYMLINK_XATTRS defined in config.h.  You can snag that via git or
> the latest nightly tar file.
> 

Thanks for the immediate action, it seems to work as expected, both ways during backup and restore. Actually now, after some reasoning, I think your solution of using a file is much cleaner than putting the xattr in the parent dir.

Now I only see an issue in "file browsing". Suppose I want to browse a backup: I do

rsync -a --rsync-path='... --fake-super' user@host:/backup_dir/

and I see this

lrwxrwxrwx          10 2009/09/03 10:56:44 link-a-dir -> directory/
drwxr-xr-x           3 2009/09/03 10:56:50 directory

So let's cd to "link-a-dir"  I get:

rsync -a --rsync-path='... --fake-super' user@host:/backup_dir/link-a-dir/
 
rsync: change_dir "/data/cavalli/test/link-a-dir" failed: Not a directory (20)

Actually this is not exactly a real issue, but just a usability improvement... I don't know if I clearly explained my concern.

Probably this could be even done outside of rsync itself, writing something like described in rsyncsh.txt...


Comment 12 Enrico Cavalli 2009-09-03 07:30:27 UTC

Small correction to sys_lremovexattr, NOT UNDERSTOOD, unlink of attributes works only of attropen is called without O_RDWR .... 

This is not strictly related with fake-super on receiving side, but with -X on sender 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);


During my tests this was the error I got 

rsync: rsync_xal_clear: lremovexattr("cavalli","pippo") failed: Is a directory (21)


user.pippo was the user extended attribute on linux side correctly backed up by -X, and now I was trying to delete it.