From 6a7cc46cb279b9dbf12977177330aeebb912aa34 Mon Sep 17 00:00:00 2001 From: "J.W. Schultz" Date: Tue, 16 Sep 2003 02:49:59 +0000 Subject: [PATCH] Detect and report when open or opendir succeed but read and readdir fail caused by network filesystems issues and truncated files. Thanks to David Norwood and Michael Brown --- NEWS | 4 ++++ fileio.c | 14 ++++++++++++-- flist.c | 11 ++++++++--- rsync.c | 18 ++++++++++++------ rsync.h | 14 +++++++++++--- sender.c | 12 +++++++++++- 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index 317157ad..6d78a518 100644 --- 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 diff --git a/fileio.c b/fileio.c index e8eaa100..088ed639 100644 --- 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 b5ccbf56..8bc3ab37 100644 --- 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 11414025..0fdc4794 100644 --- 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 3d10af6d..21a19884 100644 --- 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 '?' */ diff --git a/sender.c b/sender.c index f9a18d26..3d390526 100644 --- 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); } -- 2.34.1