Detect and report when open or opendir succeed but read and
authorJ.W. Schultz <jw@samba.org>
Tue, 16 Sep 2003 02:49:59 +0000 (02:49 +0000)
committerJ.W. Schultz <jw@samba.org>
Tue, 16 Sep 2003 02:49:59 +0000 (02:49 +0000)
readdir fail caused by network filesystems issues and
truncated files.
Thanks to David Norwood and Michael Brown

NEWS
fileio.c
flist.c
rsync.c
rsync.h
sender.c

diff --git a/NEWS b/NEWS
index 317157a..6d78a51 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -92,6 +92,10 @@ Changes since version 2.5.6:
       same path.  A directory still cannot be replaced by a
       regular file unless --delete specified.  (J.W. Schultz)
 
+    * Detect and report when open or opendir succeed but read and
+      readdir fail caused by network filesystems issues and truncated
+      files.  (David Norwood, Michael Brown, J.W. Schultz)
+
   INTERNAL:
 
     * Eliminated vestigial support for old versions that we stopped
index e8eaa10..088ed63 100644 (file)
--- a/fileio.c
+++ b/fileio.c
@@ -115,6 +115,7 @@ struct map_struct *map_file(int fd,OFF_T len)
        map->p_offset = 0;
        map->p_fd_offset = 0;
        map->p_len = 0;
+       map->status = 0;
 
        return map;
 }
@@ -191,7 +192,11 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
                }
 
                if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
-                       if (nread < 0) nread = 0;
+                       if (nread < 0) {
+                               nread = 0;
+                               if (!map->status)
+                                       map->status = errno;
+                       }
                        /* the best we can do is zero the buffer - the file
                           has changed mid transfer! */
                        memset(map->p+read_offset+nread, 0, read_size - nread);
@@ -206,13 +211,18 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
 }
 
 
-void unmap_file(struct map_struct *map)
+int unmap_file(struct map_struct *map)
 {
+       int     ret;
+
        if (map->p) {
                free(map->p);
                map->p = NULL;
        }
+       ret = map->status;
        memset(map, 0, sizeof(*map));
        free(map);
+
+       return ret;
 }
 
diff --git a/flist.c b/flist.c
index b5ccbf5..8bc3ab3 100644 (file)
--- a/flist.c
+++ b/flist.c
@@ -877,14 +877,19 @@ static void send_directory(int f, struct file_list *flist, char *dir)
                }
        }
 
-       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')))
+               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): (%d) %s\n",
+                   dir, errno, strerror(errno));
+       }
 
        if (local_exclude_list)
                free_exclude_list(&local_exclude_list); /* Zeros pointer too */
diff --git a/rsync.c b/rsync.c
index 1141402..0fdc479 100644 (file)
--- a/rsync.c
+++ b/rsync.c
@@ -88,10 +88,10 @@ int delete_file(char *fname)
                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)
+               if (strcmp(dname,".") == 0
+                   || strcmp(dname,"..") == 0)
                        continue;
                snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
                if (verbose > 0)
@@ -101,6 +101,12 @@ int delete_file(char *fname)
                        return -1;
                }
        }       
+       if (errno) {
+               rprintf(FERROR, "delete_file: readdir(%s): (%d) %s\n",
+                   fname, errno, strerror(errno));
+               closedir(d);
+               return -1;
+       }
 
        closedir(d);
        
@@ -148,7 +154,7 @@ static int is_in_group(gid_t gid)
 }
 
 int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
-             int report)
+               int report)
 {
        int updated = 0;
        STRUCT_STAT st2;
@@ -218,7 +224,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
                }
        }
 #endif
-    
+
        if (verbose > 1 && report) {
                if (updated)
                        rprintf(FINFO,"%s\n",fname);
@@ -245,7 +251,7 @@ void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
        /* move tmp file over real file */
        if (robust_rename(fnametmp,fname) != 0) {
                if (errno == EXDEV) {
-                       /* rename failed on cross-filesystem link.  
+                       /* rename failed on cross-filesystem link.
                           Copy the file instead. */
                        if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
                                rprintf(FERROR, "copy %s -> \"%s\": %s\n",
diff --git a/rsync.h b/rsync.h
index 3d10af6..21a1988 100644 (file)
--- a/rsync.h
+++ b/rsync.h
@@ -416,9 +416,17 @@ struct sum_struct {
 };
 
 struct map_struct {
-       char *p;
-       int fd,p_size,p_len;
-       OFF_T file_size, p_offset, p_fd_offset;
+       char *p;                /* Window pointer                       */
+       int fd;                 /* File Descriptor                      */
+       int p_size;             /* Window size at allocation            */
+       int p_len;              /* Window size after fill               */
+                               /*    p_size and p_len could be
+                                *    consolodated by using a local
+                                *    variable in map_ptr()             */
+       int status;             /* first errno from read errors         */
+       OFF_T file_size;        /* File size (from stat)                */
+       OFF_T p_offset;         /* Window start                         */
+       OFF_T p_fd_offset;      /* offset of cursor in fd ala lseek     */
 };
 
 #define MATCHFLG_WILD          0x0001 /* pattern has '*', '[', and/or '?' */
index f9a18d2..3d39052 100644 (file)
--- a/sender.c
+++ b/sender.c
@@ -277,7 +277,17 @@ void send_files(struct file_list *flist, int f_out, int f_in)
                }
 
                if (!read_batch) { /* dw */
-                       if (buf) unmap_file(buf);
+                       if (buf) {
+                               j = unmap_file(buf);
+                               if (j) {
+                                       io_error = 1;
+                                       rprintf(FERROR,
+                                           "read errors mapping %s: (%d) %s\n",
+                                           full_fname(fname),
+                                           j,
+                                           strerror(j));
+                               }
+                       }
                        close(fd);
                }