copyfd.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  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. #include <errno.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include "busybox.h"
  14. #include "libbb.h"
  15. #if BUFSIZ < 4096
  16. #undef BUFSIZ
  17. #define BUFSIZ 4096
  18. #endif
  19. static ssize_t bb_full_fd_action(int src_fd, int dst_fd, size_t size)
  20. {
  21. int status = -1;
  22. size_t total = 0;
  23. RESERVE_CONFIG_BUFFER(buffer,BUFSIZ);
  24. if (src_fd < 0) goto out;
  25. while (!size || total < size)
  26. {
  27. ssize_t wrote, xread;
  28. xread = safe_read(src_fd, buffer,
  29. (!size || size - total > BUFSIZ) ? BUFSIZ : size - total);
  30. if (xread > 0) {
  31. /* A -1 dst_fd means we need to fake it... */
  32. wrote = (dst_fd < 0) ? xread : bb_full_write(dst_fd, buffer, xread);
  33. if (wrote < xread) {
  34. bb_perror_msg(bb_msg_write_error);
  35. break;
  36. }
  37. total += wrote;
  38. if (total == size) status = 0;
  39. } else if (xread < 0) {
  40. bb_perror_msg(bb_msg_read_error);
  41. break;
  42. } else if (xread == 0) {
  43. /* All done. */
  44. status = 0;
  45. break;
  46. }
  47. }
  48. out:
  49. RELEASE_CONFIG_BUFFER(buffer);
  50. return status ? status : (ssize_t)total;
  51. }
  52. int bb_copyfd_size(int fd1, int fd2, const off_t size)
  53. {
  54. if (size) {
  55. return(bb_full_fd_action(fd1, fd2, size));
  56. }
  57. return(0);
  58. }
  59. int bb_copyfd_eof(int fd1, int fd2)
  60. {
  61. return(bb_full_fd_action(fd1, fd2, 0));
  62. }