aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ.W. Schultz <jw@samba.org>2003-09-16 02:49:59 +0000
committerJ.W. Schultz <jw@samba.org>2003-09-16 02:49:59 +0000
commit6a7cc46cb279b9dbf12977177330aeebb912aa34 (patch)
tree6e3b7760f73eb3610228467999714af25378f3d4
parentaa6dc37ccb73c83f652e72ed1ca7700934a52331 (diff)
downloadandroid_external_rsync-6a7cc46cb279b9dbf12977177330aeebb912aa34.tar.gz
android_external_rsync-6a7cc46cb279b9dbf12977177330aeebb912aa34.tar.bz2
android_external_rsync-6a7cc46cb279b9dbf12977177330aeebb912aa34.zip
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
-rw-r--r--NEWS4
-rw-r--r--fileio.c14
-rw-r--r--flist.c11
-rw-r--r--rsync.c18
-rw-r--r--rsync.h14
-rw-r--r--sender.c12
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);
}