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