1/* vi: set sw=4 ts=4: */ 2/* 3 * Utility routines. 4 * 5 * Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 */ 9 10#include "libbb.h" 11 12#if BUFSIZ < 4096 13#undef BUFSIZ 14#define BUFSIZ 4096 15#endif 16 17/* Used by NOFORK applets (e.g. cat) - must not use xmalloc */ 18 19static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) 20{ 21 int status = -1; 22 off_t total = 0; 23 char buffer[BUFSIZ]; 24 25 if (src_fd < 0) 26 goto out; 27 28 if (!size) { 29 size = BUFSIZ; 30 status = 1; /* copy until eof */ 31 } 32 33 while (1) { 34 ssize_t rd; 35 36 rd = safe_read(src_fd, buffer, size > BUFSIZ ? BUFSIZ : size); 37 38 if (!rd) { /* eof - all done */ 39 status = 0; 40 break; 41 } 42 if (rd < 0) { 43 bb_perror_msg(bb_msg_read_error); 44 break; 45 } 46 /* dst_fd == -1 is a fake, else... */ 47 if (dst_fd >= 0) { 48 ssize_t wr = full_write(dst_fd, buffer, rd); 49 if (wr < rd) { 50 bb_perror_msg(bb_msg_write_error); 51 break; 52 } 53 } 54 total += rd; 55 if (status < 0) { /* if we aren't copying till EOF... */ 56 size -= rd; 57 if (!size) { 58 /* 'size' bytes copied - all done */ 59 status = 0; 60 break; 61 } 62 } 63 } 64 out: 65 return status ? -1 : total; 66} 67 68 69 70off_t bb_copyfd_size(int fd1, int fd2, off_t size) 71{ 72 if (size) { 73 return bb_full_fd_action(fd1, fd2, size); 74 } 75 return 0; 76} 77 78void bb_copyfd_exact_size(int fd1, int fd2, off_t size) 79{ 80 off_t sz = bb_copyfd_size(fd1, fd2, size); 81 if (sz == size) 82 return; 83 if (sz != -1) 84 bb_error_msg_and_die("short read"); 85 /* if sz == -1, bb_copyfd_XX already complained */ 86 xfunc_die(); 87} 88 89off_t bb_copyfd_eof(int fd1, int fd2) 90{ 91 return bb_full_fd_action(fd1, fd2, 0); 92} 93