diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/util.c | 105 |
1 files changed, 39 insertions, 66 deletions
diff --git a/source3/lib/util.c b/source3/lib/util.c index 1a2f8fd84a..9b92e412d0 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -511,81 +511,54 @@ int set_blocking(int fd, BOOL set) } /**************************************************************************** -transfer some data between two fd's + Transfer some data between two fd's. ****************************************************************************/ -SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align) -{ - static char *buf=NULL; - static int size=0; - char *buf1,*abuf; - SMB_OFF_T total = 0; - - DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen)); - - if (size == 0) { - size = lp_readsize(); - size = MAX(size,1024); - } - - while (!buf && size>0) { - buf = (char *)malloc(size+8); - if (!buf) size /= 2; - } - if (!buf) { - DEBUG(0,("Can't allocate transfer buffer!\n")); - exit(1); - } - - abuf = buf + (align%8); - - if (header) - n += headlen; - - while (n > 0) - { - int s = (int)MIN(n,(SMB_OFF_T)size); - int ret,ret2=0; +ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t), + ssize_t (*write_fn)(int, const void *, size_t)) +{ + static char buf[16384]; + size_t total = 0; + ssize_t read_ret; + size_t write_total = 0; + ssize_t write_ret; - ret = 0; + while (total < n) { + size_t num_to_read_thistime = MIN((n - total), sizeof(buf)); - if (header && (headlen >= MIN(s,1024))) { - buf1 = header; - s = headlen; - ret = headlen; - headlen = 0; - header = NULL; - } else { - buf1 = abuf; - } + read_ret = (*read_fn)(infd, buf + total, num_to_read_thistime); + if (read_ret == -1) { + DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (read_ret == 0) + break; - if (header && headlen > 0) - { - ret = MIN(headlen,size); - memcpy(buf1,header,ret); - headlen -= ret; - header += ret; - if (headlen <= 0) header = NULL; - } + write_total = 0; + + while (write_total < read_ret) { + write_ret = (*write_fn)(outfd,buf + total, read_ret); + + if (write_ret == -1) { + DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (write_ret == 0) + return (ssize_t)total; + + write_total += (size_t)write_ret; + } - if (s > ret) - ret += read(infd,buf1+ret,s-ret); + total += (size_t)read_ret; + } - if (ret > 0) - { - ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret); - if (ret2 > 0) total += ret2; - /* if we can't write then dump excess data */ - if (ret2 != ret) - transfer_file(infd,-1,n-(ret+headlen),NULL,0,0); - } - if (ret <= 0 || ret2 != ret) - return(total); - n -= ret; - } - return(total); + return (ssize_t)total; } +SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n) +{ + return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, read, write); +} /******************************************************************* sleep for a specified number of milliseconds |