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