dd.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini dd implementation for busybox
  4. *
  5. *
  6. * Copyright (C) 2000,2001 Matt Kraai
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. */
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <unistd.h>
  28. #include <string.h>
  29. #include <fcntl.h>
  30. #include "busybox.h"
  31. static const struct suffix_mult dd_suffixes[] = {
  32. { "c", 1 },
  33. { "w", 2 },
  34. { "b", 512 },
  35. { "kD", 1000 },
  36. { "k", 1024 },
  37. { "MD", 1000000 },
  38. { "M", 1048576 },
  39. { "GD", 1000000000 },
  40. { "G", 1073741824 },
  41. { NULL, 0 }
  42. };
  43. int dd_main(int argc, char **argv)
  44. {
  45. size_t out_full = 0;
  46. size_t out_part = 0;
  47. size_t in_full = 0;
  48. size_t in_part = 0;
  49. size_t count = -1;
  50. size_t bs = 512;
  51. ssize_t n;
  52. off_t seek = 0;
  53. off_t skip = 0;
  54. int sync_flag = FALSE;
  55. int noerror = FALSE;
  56. int trunc_flag = TRUE;
  57. int oflag;
  58. int ifd;
  59. int ofd;
  60. int i;
  61. const char *infile = NULL;
  62. const char *outfile = NULL;
  63. char *buf;
  64. for (i = 1; i < argc; i++) {
  65. if (strncmp("bs=", argv[i], 3) == 0)
  66. bs = bb_xparse_number(argv[i]+3, dd_suffixes);
  67. else if (strncmp("count=", argv[i], 6) == 0)
  68. count = bb_xparse_number(argv[i]+6, dd_suffixes);
  69. else if (strncmp("seek=", argv[i], 5) == 0)
  70. seek = bb_xparse_number(argv[i]+5, dd_suffixes);
  71. else if (strncmp("skip=", argv[i], 5) == 0)
  72. skip = bb_xparse_number(argv[i]+5, dd_suffixes);
  73. else if (strncmp("if=", argv[i], 3) == 0)
  74. infile = argv[i]+3;
  75. else if (strncmp("of=", argv[i], 3) == 0)
  76. outfile = argv[i]+3;
  77. else if (strncmp("conv=", argv[i], 5) == 0) {
  78. buf = argv[i]+5;
  79. while (1) {
  80. if (strncmp("notrunc", buf, 7) == 0) {
  81. trunc_flag = FALSE;
  82. buf += 7;
  83. } else if (strncmp("sync", buf, 4) == 0) {
  84. sync_flag = TRUE;
  85. buf += 4;
  86. } else if (strncmp("noerror", buf, 7) == 0) {
  87. noerror = TRUE;
  88. buf += 7;
  89. } else {
  90. bb_error_msg_and_die("invalid conversion `%s'", argv[i]+5);
  91. }
  92. if (buf[0] == '\0')
  93. break;
  94. if (buf[0] == ',')
  95. buf++;
  96. }
  97. } else
  98. bb_show_usage();
  99. }
  100. buf = xmalloc(bs);
  101. if (infile != NULL) {
  102. ifd = bb_xopen(infile, O_RDONLY);
  103. } else {
  104. ifd = STDIN_FILENO;
  105. infile = bb_msg_standard_input;
  106. }
  107. if (outfile != NULL) {
  108. oflag = O_WRONLY | O_CREAT;
  109. if (!seek && trunc_flag) {
  110. oflag |= O_TRUNC;
  111. }
  112. if ((ofd = open(outfile, oflag, 0666)) < 0) {
  113. bb_perror_msg_and_die("%s", outfile);
  114. }
  115. if (seek && trunc_flag) {
  116. if (ftruncate(ofd, seek * bs) < 0) {
  117. struct stat st;
  118. if (fstat (ofd, &st) < 0 || S_ISREG (st.st_mode) ||
  119. S_ISDIR (st.st_mode)) {
  120. bb_perror_msg_and_die("%s", outfile);
  121. }
  122. }
  123. }
  124. } else {
  125. ofd = STDOUT_FILENO;
  126. outfile = bb_msg_standard_output;
  127. }
  128. if (skip) {
  129. if (lseek(ifd, skip * bs, SEEK_CUR) < 0) {
  130. bb_perror_msg_and_die("%s", infile);
  131. }
  132. }
  133. if (seek) {
  134. if (lseek(ofd, seek * bs, SEEK_CUR) < 0) {
  135. bb_perror_msg_and_die("%s", outfile);
  136. }
  137. }
  138. while (in_full + in_part != count) {
  139. if (noerror) {
  140. /* Pre-zero the buffer when doing the noerror thing */
  141. memset(buf, '\0', bs);
  142. }
  143. n = safe_read(ifd, buf, bs);
  144. if (n < 0) {
  145. if (noerror) {
  146. n = bs;
  147. bb_perror_msg("%s", infile);
  148. } else {
  149. bb_perror_msg_and_die("%s", infile);
  150. }
  151. }
  152. if (n == 0) {
  153. break;
  154. }
  155. if (n == bs) {
  156. in_full++;
  157. } else {
  158. in_part++;
  159. }
  160. if (sync_flag) {
  161. memset(buf + n, '\0', bs - n);
  162. n = bs;
  163. }
  164. n = bb_full_write(ofd, buf, n);
  165. if (n < 0) {
  166. bb_perror_msg_and_die("%s", outfile);
  167. }
  168. if (n == bs) {
  169. out_full++;
  170. } else {
  171. out_part++;
  172. }
  173. }
  174. if (close (ifd) < 0) {
  175. bb_perror_msg_and_die("%s", infile);
  176. }
  177. if (close (ofd) < 0) {
  178. bb_perror_msg_and_die("%s", outfile);
  179. }
  180. fprintf(stderr, "%ld+%ld records in\n%ld+%ld records out\n",
  181. (long)in_full, (long)in_part,
  182. (long)out_full, (long)out_part);
  183. return EXIT_SUCCESS;
  184. }