X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/71c4617611ca07d7c249faa2dfd2cfc5cb32b836..3bee67337d0491f55654cf8e926592365e5a8502:/io.c diff --git a/io.c b/io.c index aae64b75..0021d956 100644 --- a/io.c +++ b/io.c @@ -29,6 +29,7 @@ static int64 total_read; extern int verbose; extern int sparse_files; +extern int io_timeout; int64 write_total(void) { @@ -95,39 +96,71 @@ static void read_check(int f) } } +static time_t last_io; + + +static void check_timeout(void) +{ + time_t t; + + if (!io_timeout) return; + + if (!last_io) { + last_io = time(NULL); + return; + } + + t = time(NULL); + + if (last_io && io_timeout && (t-last_io)>io_timeout) { + fprintf(FERROR,"read timeout after %d second - exiting\n", + (int)(t-last_io)); + exit_cleanup(1); + } +} static int readfd(int fd,char *buffer,int N) { - int ret; - int total=0; - - if (read_buffer_len < N) - read_check(buffer_f_in); - - while (total < N) - { - if (read_buffer_len > 0 && buffer_f_in == fd) { - ret = MIN(read_buffer_len,N-total); - memcpy(buffer+total,read_buffer_p,ret); - read_buffer_p += ret; - read_buffer_len -= ret; - } else { - 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); + int ret; + int total=0; + struct timeval tv; + + if (read_buffer_len < N) + read_check(buffer_f_in); + + while (total < N) { + if (read_buffer_len > 0 && buffer_f_in == fd) { + ret = MIN(read_buffer_len,N-total); + memcpy(buffer+total,read_buffer_p,ret); + read_buffer_p += ret; + read_buffer_len -= ret; + total += ret; + continue; + } + + 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); + tv.tv_sec = io_timeout; + tv.tv_usec = 0; + + if (select(fd+1, &fds, NULL, NULL, &tv) != 1) { + check_timeout(); + } + } + + if (ret <= 0) + return total; + total += ret; } - } - if (ret <= 0) + if (io_timeout) + last_io = time(NULL); return total; - total += ret; - } - return total; } @@ -154,7 +187,7 @@ int64 read_longint(int f) if (ret != -1) return ret; -#ifndef HAVE_LONGLONG +#ifdef NO_INT64 fprintf(FERROR,"Integer overflow - attempted 64 bit offset\n"); exit_cleanup(1); #else @@ -185,6 +218,12 @@ void read_buf(int f,char *buf,int len) total_read += len; } +void read_sbuf(int f,char *buf,int len) +{ + read_buf(f,buf,len); + buf[len] = 0; +} + unsigned char read_byte(int f) { unsigned char c; @@ -198,45 +237,66 @@ static int last_sparse; int sparse_end(int f) { - if (last_sparse) { - lseek(f,-1,SEEK_CUR); - return (write(f,&last_byte,1) == 1 ? 0 : -1); - } - last_sparse = 0; - return 0; + if (last_sparse) { + lseek(f,-1,SEEK_CUR); + return (write(f,&last_byte,1) == 1 ? 0 : -1); + } + last_sparse = 0; + return 0; } -int write_sparse(int f,char *buf,int len) + +static int write_sparse(int f,char *buf,int len) { - int l1=0,l2=0; - int ret; + int l1=0,l2=0; + int ret; - if (!sparse_files) - return write(f,buf,len); + for (l1=0;l1 0) + last_sparse=1; - if (l1 == len || l2 > 0) - last_sparse=1; + if (l1 > 0) + lseek(f,l1,SEEK_CUR); - if (l1 > 0) - lseek(f,l1,SEEK_CUR); + if (l1 == len) + return len; - if (l1 == len) - return len; + if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) { + if (ret == -1 || ret == 0) return ret; + return (l1+ret); + } - if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) { - if (ret == -1 || ret == 0) return ret; - return (l1+ret); - } + if (l2 > 0) + lseek(f,l2,SEEK_CUR); + + return len; +} - if (l2 > 0) - lseek(f,l2,SEEK_CUR); - return len; + +int write_file(int f,char *buf,int len) +{ + int ret = 0; + + if (!sparse_files) + return write(f,buf,len); + + while (len>0) { + int len1 = MIN(len, SPARSE_WRITE_SIZE); + int r1 = write_sparse(f, buf, len1); + if (r1 <= 0) { + if (ret > 0) return ret; + return r1; + } + len -= r1; + buf += r1; + ret += r1; + } + return ret; } @@ -295,7 +355,10 @@ static int writefd(int fd,char *buf,int len) exit_cleanup(1); } - if (count == 0) continue; + if (count == 0) { + check_timeout(); + continue; + } if (FD_ISSET(fd, &w_fds)) { got_select = 1; @@ -305,6 +368,9 @@ static int writefd(int fd,char *buf,int len) } } + if (io_timeout) + last_io = time(NULL); + return total; }