X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/182dca5c80c40c5abe429a6c5307be25cc4b4d90..d5ee1f8e7a370884aa9c5353de5129728ed9a37b:/io.c diff --git a/io.c b/io.c index fda04dd8..9b6bdc82 100644 --- a/io.c +++ b/io.c @@ -103,7 +103,15 @@ static int readfd(int fd,char *buffer,int N) read_buffer_p += ret; read_buffer_len -= ret; } else { - ret = read(fd,buffer + total,N - total); + while ((ret = read(fd,buffer + total,N - total)) == -1) { + fd_set fds; + + if (errno != EAGAIN && errno != EWOULDBLOCK) + return -1; + FD_ZERO(&fds); + FD_SET(fd, &fds); + select(fd+1, &fds, NULL, NULL, NULL); + } } if (ret <= 0) @@ -116,11 +124,13 @@ static int readfd(int fd,char *buffer,int N) int read_int(int f) { + int ret; char b[4]; - if (readfd(f,b,4) != 4) { + if ((ret=readfd(f,b,4)) != 4) { if (verbose > 1) - fprintf(stderr,"Error reading %d bytes : %s\n",4,strerror(errno)); - exit(1); + fprintf(stderr,"Error reading %d bytes : %s\n", + 4,ret==-1?strerror(errno):"EOF"); + exit_cleanup(1); } total_read += 4; return IVAL(b,0); @@ -128,10 +138,12 @@ int read_int(int f) void read_buf(int f,char *buf,int len) { - if (readfd(f,buf,len) != len) { + int ret; + if ((ret=readfd(f,buf,len)) != len) { if (verbose > 1) - fprintf(stderr,"Error reading %d bytes : %s\n",len,strerror(errno)); - exit(1); + fprintf(stderr,"Error reading %d bytes : %s\n", + len,ret==-1?strerror(errno):"EOF"); + exit_cleanup(1); } total_read += len; } @@ -143,10 +155,49 @@ unsigned char read_byte(int f) return (unsigned char)c; } + +static char last_byte=0; +static int last_sparse = 0; + +int sparse_end(int f) +{ +#if SPARSE_FILES + if (last_sparse) { + lseek(f,-1,SEEK_CUR); + return (write(f,&last_byte,1) == 1 ? 0 : -1); + } +#endif + last_sparse = 0; + return 0; +} + +int write_sparse(int f,char *buf,int len) +{ + int l=0; + +#if SPARSE_FILES + for (l=0;l 0) + lseek(f,l,SEEK_CUR); + + last_byte = buf[len-1]; +#endif + + if (l == len) { + last_sparse = 1; + return len; + } + + last_sparse = 0; + + return (l + write(f,buf+l,len-l)); +} + int read_write(int fd_in,int fd_out,int size) { static char *buf=NULL; - static int bufsize = WRITE_BLOCK_SIZE; + static int bufsize = CHUNK_SIZE; int total=0; if (!buf) { @@ -157,7 +208,7 @@ int read_write(int fd_in,int fd_out,int size) while (total < size) { int n = MIN(size-total,bufsize); read_buf(fd_in,buf,n); - if (write(fd_out,buf,n) != n) + if (write_sparse(fd_out,buf,n) != n) return total; total += n; } @@ -179,8 +230,8 @@ static int writefd(int fd,char *buf,int len) if (ret == 0) return total; - if (ret == -1 && errno != EWOULDBLOCK) - return total?total:-1; + if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN)) + return -1; if (ret == -1) { read_check(buffer_f_in); @@ -189,7 +240,7 @@ static int writefd(int fd,char *buf,int len) FD_SET(fd,&fds); tv.tv_sec = BLOCKING_TIMEOUT; tv.tv_usec = 0; - select(16,NULL,&fds,NULL,&tv); + select(fd+1,NULL,&fds,NULL,&tv); } else { total += ret; } @@ -202,20 +253,24 @@ static int writefd(int fd,char *buf,int len) void write_int(int f,int x) { + int ret; char b[4]; SIVAL(b,0,x); - if (writefd(f,b,4) != 4) { - fprintf(stderr,"write_int failed : %s\n",strerror(errno)); - exit(1); + if ((ret=writefd(f,b,4)) != 4) { + fprintf(stderr,"write_int failed : %s\n", + ret==-1?strerror(errno):"EOF"); + exit_cleanup(1); } total_written += 4; } void write_buf(int f,char *buf,int len) { - if (writefd(f,buf,len) != len) { - fprintf(stderr,"write_buf failed : %s\n",strerror(errno)); - exit(1); + int ret; + if ((ret=writefd(f,buf,len)) != len) { + fprintf(stderr,"write_buf failed : %s\n", + ret==-1?strerror(errno):"EOF"); + exit_cleanup(1); } total_written += len; }