supporting --fake-super on opensolaris (zfs) destination
Enrico Cavalli
cavalli at cilea.it
Mon Jul 27 01:30:48 MDT 2009
Hello everybody. I wrote a small patch in order to support what I think
is an absolutely needed feature in order to make rsync-based backups
retaining complete ownership permission when writing to an opensolaris
machine using --fake-super.
My goal is making backups of linux boxes to opensolaris/zfs.
In order to make it work just do
patch -p1 < patch_file.txt
inside rsync source tree.
and set
#define SUPPORT_XATTRS 1
in config.h
I tested the patch with rsync 3.0.6 and the last git commit.
Disclaimer:
1) I'm not a filesystem programmer
2) the patch is surely full of nasty bugs and could be insecure/break
your systems. etc etc.
3) even if you define SUPPORT_XATTRS, rsync -X won't work
TODO
- write true xattr support for opensolaris
- wrap this up with configure to recognize opensolaris and define
HAVE_SOLARIS_XATTRS for instance
- support linux XATTRS on symlinks on the solaris side: for instance
if I have /usr/bin/xyz -> /usr/bin/abc I could write the extended
attributes of symlink xyz inside a directory named xyz rooted at the
parent /usr/bin
I hope my little effort would encourage some true system programmers to
write somthing more general and useful.
Please do not laugh reading my code: see disclaimer :)
--
Enrico Cavalli
CILEA - via R. Sanzio 4, 20090 - Segrate (MI), Italy
phone: +39 02 26995.1 - fax: +39 02 2135520 - skype: enricocavalli
GTalk/Jabber/iChat: enrico.cavalli at gmail.com
PGP Fingerprint: 3762 7B1B 743E 029C 8F94 8ADE BC4B 43A7 0485 30E5
-------------- next part --------------
diff --git a/lib/sysxattrs.c b/lib/sysxattrs.c
index 12e456e..8655760 100644
--- a/lib/sysxattrs.c
+++ b/lib/sysxattrs.c
@@ -128,7 +128,155 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
#else
-#error You need to create xattr compatibility functions.
+ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+
+
+ int attrfd;
+ size_t bufpos,r;
+ STRUCT_STAT fst;
+
+ do_lstat(path,&fst);
+ if(S_ISLNK(fst.st_mode)) {
+ errno=EPERM;
+ return(-1);
+ }
+
+ attrfd = attropen(path, name, O_RDONLY);
+
+ if (attrfd<0) {
+ errno = ENOATTR;
+ return -1;
+ }
+
+
+ for(bufpos=0;bufpos<size;) {
+ r=read(attrfd,value+bufpos,512);
+ if (r==0) break;
+ if(r<0) {
+ return -errno;
+ }
+ bufpos+=r;
+ }
+close(attrfd);
+return (bufpos);
+
+}
+
+ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
+{
+ int attrfd;
+ size_t bufpos,r;
+
+ attrfd=openat(filedes,name,O_RDONLY);
+ if (attrfd<0) {
+ errno = ENOATTR;
+ return -1;
+ }
+
+
+ for(bufpos=0;bufpos<size;) {
+ r=read(attrfd,value+bufpos,512);
+ if (r==0) break;
+
+ if(r<0) {
+ return -errno;
+ }
+ bufpos+=r;
+ }
+
+
+close(attrfd);
+return (bufpos);
+
+}
+
+int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
+{
+ int attrfd;
+ size_t bufpos,w;
+
+ STRUCT_STAT fst;
+
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+
+ do_lstat(path,&fst);
+
+ if(S_ISLNK(fst.st_mode)) {
+ errno=EPERM;
+ return(-1);
+ }
+
+ attrfd = attropen(path, name, AT_SYMLINK_NOFOLLOW|O_CREAT|O_RDWR,mode);
+
+ if(attrfd>0) {
+
+ for(bufpos=0;bufpos<size;) {
+ w = write(attrfd, value+bufpos, size);
+ if(w<0) return -errno;
+ bufpos+=w;
+
+ }
+ close(attrfd);
+ return (bufpos);
+}
+return 0;
+}
+
+int sys_lremovexattr(const char *path, const char *name)
+{
+ int attrdirfd;
+ int error;
+ STRUCT_STAT fst;
+
+ do_lstat(path,&fst);
+
+ if(S_ISLNK(fst.st_mode)) {
+ errno=EPERM;
+ return(-1);
+ }
+
+ attrdirfd = attropen(path, ".", O_RDONLY);
+
+ error = unlinkat(attrdirfd,name,0);
+
+ close (attrdirfd);
+ return error;
+}
+
+ssize_t sys_llistxattr(const char *path, char *list, size_t size)
+{
+ int attrdirfd;
+ DIR *dirp;
+ struct dirent *dp;
+ int len=0;
+
+ attrdirfd = attropen(path, ".", O_RDONLY);
+
+ if (!attrdirfd) {
+ errno=ENOTSUP;
+ return -1;
+ }
+
+ dirp = fdopendir(attrdirfd);
+ while ((dp = readdir(dirp))) {
+ if ((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..") == 0) ||
+ (strcmp(dp->d_name, "SUNWattr_ro") == 0) || (strcmp(dp->d_name, "SUNWattr_rw") == 0))
+ continue;
+
+ sprintf(list,dp->d_name);
+ len=len+strlen(dp->d_name);
+ list+=strlen(dp->d_name);
+ list[len]='\0';
+ list+=1;
+
+ }
+
+ close(attrdirfd);
+ closedir(dirp);
+ return(len);
+
+}
#endif
More information about the rsync
mailing list