X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/c5b975c4dbee994e9d79195dfcac81fd0cc9dd24..70d794dce9ba8fbf978185ea36f2ad4198b269ee:/util.c diff --git a/util.c b/util.c index 856ed199..f9985ef2 100644 --- a/util.c +++ b/util.c @@ -24,176 +24,80 @@ */ #include "rsync.h" -static int total_written = 0; -static int total_read = 0; - -extern int verbose; - -int write_total(void) -{ - return total_written; -} - -int read_total(void) -{ - return total_read; -} - -void write_int(int f,int x) -{ - char b[4]; - SIVAL(b,0,x); - if (write(f,b,4) != 4) { - fprintf(stderr,"write_int failed : %s\n",strerror(errno)); - exit(1); - } - total_written += 4; -} - -void write_buf(int f,char *buf,int len) -{ - if (write(f,buf,len) != len) { - fprintf(stderr,"write_buf failed : %s\n",strerror(errno)); - exit(1); - } - total_written += len; -} - -static int num_waiting(int fd) +int num_waiting(int fd) { int len=0; -#ifdef FIONREAD ioctl(fd,FIONREAD,&len); -#endif return(len); } -static char *read_buffer = NULL; -static char *read_buffer_p = NULL; -static int read_buffer_len = 0; -static int read_buffer_size = 0; +static int map_fd = -1; +static off_t map_size = 0; +static char *p = NULL; +static int p_size = 0; +static int p_offset = 0; +static int p_len = 0; -void write_flush(int f) +char *map_file(int fd,off_t len) { + char *ret = NULL; +#ifdef HAVE_MMAP + if (len < MAX_MAP_SIZE) + ret = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0); +#endif + map_fd = fd; + map_size = len; + return ret; } - -/* This function was added to overcome a deadlock problem when using - * ssh. It looks like we can't allow our receive queue to get full or - * ssh will clag up. Uggh. */ -void read_check(int f) +char *map_ptr(char *buf,off_t offset,int len) { - int n; + if (buf) + return buf+offset; - if (read_buffer_len == 0) { - read_buffer_p = read_buffer; - } + if (len == 0) + return NULL; - if ((n=num_waiting(f)) <= 0) - return; + len = MIN(len,map_size-offset); - if (read_buffer_p != read_buffer) { - memmove(read_buffer,read_buffer_p,read_buffer_len); - read_buffer_p = read_buffer; + if (offset >= p_offset && + offset+len <= p_offset+p_len) { + return (p + (offset - p_offset)); } - if (n > (read_buffer_size - read_buffer_len)) { - read_buffer_size += n; - if (!read_buffer) - read_buffer = (char *)malloc(read_buffer_size); - else - read_buffer = (char *)realloc(read_buffer,read_buffer_size); - if (!read_buffer) out_of_memory("read check"); - read_buffer_p = read_buffer; - } - - n = read(f,read_buffer+read_buffer_len,n); - if (n > 0) { - read_buffer_len += n; - } -} - - -static int readfd(int fd,char *buffer,int N) -{ - int ret; - int total=0; - - while (total < N) - { - if (read_buffer_len > 0) { - ret = MIN(read_buffer_len,N-total); - memcpy(buffer+total,read_buffer_p,ret); - read_buffer_p += ret; - read_buffer_len -= ret; - } else { - ret = read(fd,buffer + total,N - total); - } - - if (ret <= 0) - return total; - total += ret; - } - return total; -} - + len = MAX(len,CHUNK_SIZE); + len = MIN(len,map_size - offset); -int read_int(int f) -{ - char b[4]; - if (readfd(f,b,4) != 4) { - if (verbose > 1) - fprintf(stderr,"Error reading %d bytes : %s\n",4,strerror(errno)); - exit(1); + if (len > p_size) { + if (p) free(p); + p = (char *)malloc(len); + if (!p) out_of_memory("map_ptr"); + p_size = len; } - total_read += 4; - return IVAL(b,0); -} -void read_buf(int f,char *buf,int len) -{ - if (readfd(f,buf,len) != len) { - if (verbose > 1) - fprintf(stderr,"Error reading %d bytes : %s\n",len,strerror(errno)); - exit(1); + if (lseek(map_fd,offset,SEEK_SET) != offset || + read(map_fd,p,len) != len) { + fprintf(FERROR,"EOF in map_ptr!\n"); + exit_cleanup(1); } - total_read += len; -} + p_offset = offset; + p_len = len; -char *map_file(int fd,off_t len) -{ - char *ret = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0); - return ret; + return p; } + void unmap_file(char *buf,off_t len) { +#ifdef HAVE_MMAP if (len > 0 && buf) munmap(buf,len); -} - - -int read_write(int fd_in,int fd_out,int size) -{ - static char *buf=NULL; - static int bufsize = WRITE_BLOCK_SIZE; - int total=0; - - if (!buf) { - buf = (char *)malloc(bufsize); - if (!buf) out_of_memory("read_write"); - } - - while (total < size) { - int n = MIN(size-total,bufsize); - read_buf(fd_in,buf,n); - if (write(fd_out,buf,n) != n) - return total; - total += n; - } - return total; +#endif + map_fd = -1; + map_size = 0; + p_len = 0; } @@ -206,15 +110,15 @@ int piped_child(char **command,int *f_in,int *f_out) if (pipe(to_child_pipe) < 0 || pipe(from_child_pipe) < 0) { - fprintf(stderr,"pipe: %s\n",strerror(errno)); - exit(1); + fprintf(FERROR,"pipe: %s\n",strerror(errno)); + exit_cleanup(1); } pid = fork(); if (pid < 0) { - fprintf(stderr,"fork: %s\n",strerror(errno)); - exit(1); + fprintf(FERROR,"fork: %s\n",strerror(errno)); + exit_cleanup(1); } if (pid == 0) @@ -223,19 +127,19 @@ int piped_child(char **command,int *f_in,int *f_out) close(to_child_pipe[1]) < 0 || close(from_child_pipe[0]) < 0 || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) { - fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno)); - exit(1); + fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno)); + exit_cleanup(1); } execvp(command[0], command); - fprintf(stderr,"Failed to exec %s : %s\n", + fprintf(FERROR,"Failed to exec %s : %s\n", command[0],strerror(errno)); - exit(1); + exit_cleanup(1); } if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) { - fprintf(stderr,"Failed to close : %s\n",strerror(errno)); - exit(1); + fprintf(FERROR,"Failed to close : %s\n",strerror(errno)); + exit_cleanup(1); } *f_in = from_child_pipe[0]; @@ -247,8 +151,8 @@ int piped_child(char **command,int *f_in,int *f_out) void out_of_memory(char *str) { - fprintf(stderr,"out of memory in %s\n",str); - exit(1); + fprintf(FERROR,"out of memory in %s\n",str); + exit_cleanup(1); } @@ -286,3 +190,33 @@ int set_modtime(char *fname,time_t modtime) #endif } + + +/**************************************************************************** +Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, +else +if SYSV use O_NDELAY +if BSD use FNDELAY +****************************************************************************/ +int set_blocking(int fd, int set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return fcntl( fd, F_SETFL, val); +#undef FLAG_TO_SET +}