problem related to filename length

Hiroshi Umezaki umezaki at i-d-i-m.com
Fri Jun 7 12:04:01 EST 2002


 hi, all.

 I had an problem with rsync-2.5.4/5 related to filename length.

 On Linux box (kernel-2.4.18 + ext3 fs), filename length limits to
255byte, but rsync can't handle fn > (255 -9) byte. So I had an instant
hack to avoid this problem. Patch file attatched works fine in my case,
but I'm not sure that it is correct or not. Any suggestions ?

 Please cc me, I'm not on this list.

 Regards,

 Hiroshi
-------------- next part --------------
diff -urN rsync-2.5.5.orig/receiver.c rsync-2.5.5/receiver.c
--- rsync-2.5.5.orig/receiver.c	Thu Feb 14 03:41:58 2002
+++ rsync-2.5.5/receiver.c	Sat Jun  8 03:41:22 2002
@@ -163,10 +163,16 @@
 	}
 }
 
+#include <sys/vfs.h>
+static inline int fname_syslimit(const char* path) {
+  struct statfs sb;
+  return !statfs(path,&sb) ? sb.f_namelen : 255;
+}
 
 static int get_tmpname(char *fnametmp, char *fname)
 {
 	char *f;
+	int  fn_max;
 
 	/* open tmp file */
 	if (tmpdir) {
@@ -179,7 +185,12 @@
 			rprintf(FERROR,"filename too long\n");
 			return 0;
 		}
-		snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
+		fn_max = fname_syslimit(tmpdir);
+		if(strlen(f)+9 > fn_max) {
+		  snprintf(fnametmp,MAXPATHLEN, "%s/%s",tmpdir,f);
+		  strncpy(fnametmp + strlen(fnametmp) - 6,"XXXXXX",6);
+		}else
+		  snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
 		return 1;
 	} 
 
@@ -190,13 +201,23 @@
 		return 0;
 	}
 
+	fn_max = fname_syslimit(fname);
+
 	if (f) {
 		*f = 0;
-		snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
-			 fname,f+1);
+		if(strlen(f+1)+9 > fn_max) {
+		  snprintf(fnametmp,MAXPATHLEN, "%s/%s",fname,f + 1);
+		  strncpy(fnametmp + strlen(fnametmp) - 6,"XXXXXX",6);
+		}else
+		  snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
+			   fname,f+1);
 		*f = '/';
 	} else {
-		snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
+		if(strlen(fname)+9 > fn_max) {
+		  snprintf(fnametmp,MAXPATHLEN, "%s",fname);
+		  strncpy(fnametmp + strlen(fnametmp) - 6,"XXXXXX",6);
+		}else
+		  snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
 	}
 
 	return 1;
@@ -408,21 +429,33 @@
 			buf = NULL;
 		}
 
-		if (!get_tmpname(fnametmp,fname)) {
-			if (buf) unmap_file(buf);
-			if (fd1 != -1) close(fd1);
-			continue;
+		{
+		  static const int max_retry = 10;
+		  int retry = 0;
+		  int flag = 0;
+
+		  do {
+		    if (!get_tmpname(fnametmp,fname)) {
+		      if (buf) unmap_file(buf);
+		      if (fd1 != -1) close(fd1);
+		      flag = 1;
+		      break;
+		    }
+
+		    strlcpy(template, fnametmp, sizeof(template));
+
+		    /* we initially set the perms without the
+		       setuid/setgid bits to ensure that there is no race
+		       condition. They are then correctly updated after
+		       the lchown. Thanks to snabb at epipe.fi for pointing
+		       this out.  We also set it initially without group
+		       access because of a similar race condition. */
+
+		    fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+		  }while(!flag && (retry++ < max_retry) &&
+			 (fd2 == -1 && errno == EEXIST));
+		  if(flag) continue;
 		}
-
-		strlcpy(template, fnametmp, sizeof(template));
-
-		/* we initially set the perms without the
-		   setuid/setgid bits to ensure that there is no race
-		   condition. They are then correctly updated after
-		   the lchown. Thanks to snabb at epipe.fi for pointing
-		   this out.  We also set it initially without group
-		   access because of a similar race condition. */
-		fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
 		if (fd2 == -1) {
 			rprintf(FERROR,"mkstemp %s failed: %s\n",fnametmp,strerror(errno));
 			receive_data(f_in,buf,-1,NULL,file->length);


More information about the rsync mailing list