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
This commit is contained in:
J.W. Schultz
2003-09-16 02:49:59 +00:00
parent aa6dc37ccb
commit 6a7cc46cb2
6 changed files with 58 additions and 15 deletions

4
NEWS
View File

@@ -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

View File

@@ -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;
}

11
flist.c
View File

@@ -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 */

18
rsync.c
View File

@@ -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",

14
rsync.h
View File

@@ -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 '?' */

View File

@@ -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);
}