readdir() and read() errors ignored
Michael Brown
mbrown at fensystems.co.uk
Sun Aug 24 19:51:20 EST 2003
> > A similar error can occur when open() succeeds but subsequent calls to
> > read() fail: under these circumstances rsync will transfer zeroes instead
> > of the actual file data and will again report no errors to the user.
> > The attached patch fixes both of these problems.
> There is a patch on-list for the read error. Your fix is
> incorrect because it causes rsync to exit if a file is
> truncated during read.
I think it will only exit if an error occurs, not just if EOF is reached
unexpectedly (it checks for read() returning <0, not !=expected), but no
matter since there is already a patch. Is your patch going to be
integrated into HEAD CVS?
> I'll look closer at the readir error when i get a chance.
I've attached a new patch that only addresses the readdir() issue. This
patch has been tested and does solve the problem:
Before the patch:
[root at angel root]# ls /mnt/nfs/rsync-test/
ls: reading directory /mnt/nfs/rsync-test/: Permission denied
[root at angel root]# rsync -avP /mnt/nfs/rsync-test/ rsync-test/
building file list ...
1 file to consider
wrote 70 bytes read 20 bytes 180.00 bytes/sec
total size is 0 speedup is 0.00
[root at angel root]# ls rsync-test/
[root at angel root]#
Here you can see rsync silently failing on an NFS-mounted directory for
which opendir() succeeds but readdir() fails.
After the patch:
[root at angel root]# ls /mnt/nfs/rsync-test/
ls: reading directory /mnt/nfs/rsync-test/: Permission denied
[root at angel root]# ~/fixed-rsync -avP /mnt/nfs/rsync-test/ rsync-test/
building file list ...
readdir(.): Permission denied
1 file to consider
wrote 70 bytes read 20 bytes 180.00 bytes/sec
total size is 0 speedup is 0.00
rsync error: some files could not be transferred (code 23) at main.c(628)
[root at angel root]#
Now rsync acts correctly and reports a partial transfer error to the user.
You can easily reproduce this situation: create an NFS export with the
default flag of "root_squash", create a directory on the NFS server with
permissions of e.g. 750 and try to rsync it as root. opendir() succeeds
because Linux just looks at the directory permissions and doesn't bother
contacting the NFS server but readdir() fails because the NFS server maps
requests from root to the anonymous user, who doesn't have access to the
directory.
(Please Cc me on replies)
Michael
-------------- next part --------------
Index: flist.c
===================================================================
RCS file: /cvsroot/rsync/flist.c,v
retrieving revision 1.139
diff -u -r1.139 flist.c
--- flist.c 17 Aug 2003 21:29:11 -0000 1.139
+++ flist.c 23 Aug 2003 23:03:02 -0000
@@ -877,13 +877,18 @@
}
}
- for (di = readdir(d); di; di = readdir(d)) {
+ for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
char *dname = d_name(di);
if (dname[0] == '.' && (dname[1] == '\0' ||
(dname[1] == '.' && dname[2] == '\0')))
continue;
strlcpy(p, dname, MAXPATHLEN - l);
send_file_name(f, flist, fname, recurse, 0);
+ }
+ if ( errno ) {
+ io_error = 1;
+ rprintf(FERROR, "readdir(%s): %s\n", dir, strerror(errno));
+ /* Don't return yet; we want to clean up first */
}
if (local_exclude_list)
Index: rsync.c
===================================================================
RCS file: /cvsroot/rsync/rsync.c,v
retrieving revision 1.120
diff -u -r1.120 rsync.c
--- rsync.c 18 Feb 2003 18:07:36 -0000 1.120
+++ rsync.c 23 Aug 2003 23:03:02 -0000
@@ -86,7 +86,7 @@
return -1;
}
- for (di=readdir(d); di; di=readdir(d)) {
+ for (errno = 0, di=readdir(d); di; errno = 0, di=readdir(d)) {
char *dname = d_name(di);
if (strcmp(dname,".")==0 ||
strcmp(dname,"..")==0)
@@ -99,6 +99,12 @@
return -1;
}
}
+ if ( errno ) {
+ closedir(d);
+ rprintf(FERROR,"delete_file: readdir(%s): %s\n",
+ fname,strerror(errno));
+ return -1;
+ }
closedir(d);
More information about the rsync
mailing list