*** empty log message ***
[coreutils.git] / src / dd.c
blobdd473c0709410a316253eb269f58d188510a0596
1 /* dd -- convert a file while copying it.
2 Copyright (C) 85, 90, 91, 1995-1999 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Paul Rubin, David MacKenzie, and Stuart Kemp. */
20 #include <config.h>
21 #include <stdio.h>
23 #define SWAB_ALIGN_OFFSET 2
25 #if HAVE_INTTYPES_H
26 # include <inttypes.h>
27 #endif
28 #include <sys/types.h>
29 #include <signal.h>
30 #include <getopt.h>
32 #include "system.h"
33 #include "error.h"
34 #include "getpagesize.h"
35 #include "human.h"
36 #include "long-options.h"
37 #include "safe-read.h"
38 #include "xstrtol.h"
40 /* The official name of this program (e.g., no `g' prefix). */
41 #define PROGRAM_NAME "dd"
43 #define AUTHORS "Paul Rubin, David MacKenzie, and Stuart Kemp"
45 #ifndef SIGINFO
46 # define SIGINFO SIGUSR1
47 #endif
49 #define ROUND_UP_OFFSET(X, M) ((M) - 1 - (((X) + (M) - 1) % (M)))
50 #define PTR_ALIGN(Ptr, M) ((Ptr) \
51 + ROUND_UP_OFFSET ((char *)(Ptr) - (char *)0, (M)))
53 #define max(a, b) ((a) > (b) ? (a) : (b))
54 #define output_char(c) \
55 do { \
56 obuf[oc++] = (c); if (oc >= output_blocksize) write_output (); \
57 } while (0)
59 /* Default input and output blocksize. */
60 #define DEFAULT_BLOCKSIZE 512
62 /* Conversions bit masks. */
63 #define C_ASCII 01
64 #define C_EBCDIC 02
65 #define C_IBM 04
66 #define C_BLOCK 010
67 #define C_UNBLOCK 020
68 #define C_LCASE 040
69 #define C_UCASE 0100
70 #define C_SWAB 0200
71 #define C_NOERROR 0400
72 #define C_NOTRUNC 01000
73 #define C_SYNC 02000
74 /* Use separate input and output buffers, and combine partial input blocks. */
75 #define C_TWOBUFS 04000
77 int full_write ();
79 /* The name this program was run with. */
80 char *program_name;
82 /* The name of the input file, or NULL for the standard input. */
83 static char *input_file = NULL;
85 /* The name of the output file, or NULL for the standard output. */
86 static char *output_file = NULL;
88 /* The number of bytes in which atomic reads are done. */
89 static size_t input_blocksize = 0;
91 /* The number of bytes in which atomic writes are done. */
92 static size_t output_blocksize = 0;
94 /* Conversion buffer size, in bytes. 0 prevents conversions. */
95 static size_t conversion_blocksize = 0;
97 /* Skip this many records of `input_blocksize' bytes before input. */
98 static uintmax_t skip_records = 0;
100 /* Skip this many records of `output_blocksize' bytes before output. */
101 static uintmax_t seek_record = 0;
103 /* Copy only this many records. The default is effectively infinity. */
104 static uintmax_t max_records = (uintmax_t) -1;
106 /* Bit vector of conversions to apply. */
107 static int conversions_mask = 0;
109 /* If nonzero, filter characters through the translation table. */
110 static int translation_needed = 0;
112 /* Number of partial blocks written. */
113 static uintmax_t w_partial = 0;
115 /* Number of full blocks written. */
116 static uintmax_t w_full = 0;
118 /* Number of partial blocks read. */
119 static uintmax_t r_partial = 0;
121 /* Number of full blocks read. */
122 static uintmax_t r_full = 0;
124 /* Records truncated by conv=block. */
125 static uintmax_t r_truncate = 0;
127 /* Output representation of newline and space characters.
128 They change if we're converting to EBCDIC. */
129 static unsigned char newline_character = '\n';
130 static unsigned char space_character = ' ';
132 /* Output buffer. */
133 static unsigned char *obuf;
135 /* Current index into `obuf'. */
136 static size_t oc = 0;
138 /* Index into current line, for `conv=block' and `conv=unblock'. */
139 static size_t col = 0;
141 struct conversion
143 char *convname;
144 int conversion;
147 static struct conversion conversions[] =
149 {"ascii", C_ASCII | C_TWOBUFS}, /* EBCDIC to ASCII. */
150 {"ebcdic", C_EBCDIC | C_TWOBUFS}, /* ASCII to EBCDIC. */
151 {"ibm", C_IBM | C_TWOBUFS}, /* Slightly different ASCII to EBCDIC. */
152 {"block", C_BLOCK | C_TWOBUFS}, /* Variable to fixed length records. */
153 {"unblock", C_UNBLOCK | C_TWOBUFS}, /* Fixed to variable length records. */
154 {"lcase", C_LCASE | C_TWOBUFS}, /* Translate upper to lower case. */
155 {"ucase", C_UCASE | C_TWOBUFS}, /* Translate lower to upper case. */
156 {"swab", C_SWAB | C_TWOBUFS}, /* Swap bytes of input. */
157 {"noerror", C_NOERROR}, /* Ignore i/o errors. */
158 {"notrunc", C_NOTRUNC}, /* Do not truncate output file. */
159 {"sync", C_SYNC}, /* Pad input records to ibs with NULs. */
160 {NULL, 0}
163 /* Translation table formed by applying successive transformations. */
164 static unsigned char trans_table[256];
166 static unsigned char const ascii_to_ebcdic[] =
168 0, 01, 02, 03, 067, 055, 056, 057,
169 026, 05, 045, 013, 014, 015, 016, 017,
170 020, 021, 022, 023, 074, 075, 062, 046,
171 030, 031, 077, 047, 034, 035, 036, 037,
172 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175,
173 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
174 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
175 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
176 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
177 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
178 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
179 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155,
180 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
181 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
182 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
183 0247, 0250, 0251, 0300, 0152, 0320, 0241, 07,
184 040, 041, 042, 043, 044, 025, 06, 027,
185 050, 051, 052, 053, 054, 011, 012, 033,
186 060, 061, 032, 063, 064, 065, 066, 010,
187 070, 071, 072, 073, 04, 024, 076, 0341,
188 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
189 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
190 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
191 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
192 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
193 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
194 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
195 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
196 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
197 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
198 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
199 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
202 static unsigned char const ascii_to_ibm[] =
204 0, 01, 02, 03, 067, 055, 056, 057,
205 026, 05, 045, 013, 014, 015, 016, 017,
206 020, 021, 022, 023, 074, 075, 062, 046,
207 030, 031, 077, 047, 034, 035, 036, 037,
208 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
209 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
210 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
211 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
212 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
213 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
214 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
215 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
216 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
217 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
218 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
219 0247, 0250, 0251, 0300, 0117, 0320, 0241, 07,
220 040, 041, 042, 043, 044, 025, 06, 027,
221 050, 051, 052, 053, 054, 011, 012, 033,
222 060, 061, 032, 063, 064, 065, 066, 010,
223 070, 071, 072, 073, 04, 024, 076, 0341,
224 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
225 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
226 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
227 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
228 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
229 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
230 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
231 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
232 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
233 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
234 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
235 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
238 static unsigned char const ebcdic_to_ascii[] =
240 0, 01, 02, 03, 0234, 011, 0206, 0177,
241 0227, 0215, 0216, 013, 014, 015, 016, 017,
242 020, 021, 022, 023, 0235, 0205, 010, 0207,
243 030, 031, 0222, 0217, 034, 035, 036, 037,
244 0200, 0201, 0202, 0203, 0204, 012, 027, 033,
245 0210, 0211, 0212, 0213, 0214, 05, 06, 07,
246 0220, 0221, 026, 0223, 0224, 0225, 0226, 04,
247 0230, 0231, 0232, 0233, 024, 025, 0236, 032,
248 040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
249 0247, 0250, 0133, 056, 074, 050, 053, 041,
250 046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
251 0260, 0261, 0135, 044, 052, 051, 073, 0136,
252 055, 057, 0262, 0263, 0264, 0265, 0266, 0267,
253 0270, 0271, 0174, 054, 045, 0137, 076, 077,
254 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
255 0302, 0140, 072, 043, 0100, 047, 075, 042,
256 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
257 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
258 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
259 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320,
260 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170,
261 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327,
262 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
263 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
264 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
265 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
266 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
267 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
268 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
269 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
270 060, 061, 062, 063, 064, 065, 066, 067,
271 070, 071, 0372, 0373, 0374, 0375, 0376, 0377
274 void
275 usage (int status)
277 if (status != 0)
278 fprintf (stderr, _("Try `%s --help' for more information.\n"),
279 program_name);
280 else
282 printf (_("Usage: %s [OPTION]...\n"), program_name);
283 printf (_("\
284 Copy a file, converting and formatting according to the options.\n\
286 bs=BYTES force ibs=BYTES and obs=BYTES\n\
287 cbs=BYTES convert BYTES bytes at a time\n\
288 conv=KEYWORDS convert the file as per the comma separated keyword list\n\
289 count=BLOCKS copy only BLOCKS input blocks\n\
290 ibs=BYTES read BYTES bytes at a time\n\
291 if=FILE read from FILE instead of stdin\n\
292 obs=BYTES write BYTES bytes at a time\n\
293 of=FILE write to FILE instead of stdout\n\
294 seek=BLOCKS skip BLOCKS obs-sized blocks at start of output\n\
295 skip=BLOCKS skip BLOCKS ibs-sized blocks at start of input\n\
296 --help display this help and exit\n\
297 --version output version information and exit\n\
299 BYTES may be followed by the following multiplicative suffixes:\n\
300 xM M, c 1, w 2, b 512, kD 1000, k 1024, MD 1,000,000, M 1,048,576,\n\
301 GD 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y.\n\
302 Each KEYWORD may be:\n\
304 ascii from EBCDIC to ASCII\n\
305 ebcdic from ASCII to EBCDIC\n\
306 ibm from ASCII to alternated EBCDIC\n\
307 block pad newline-terminated records with spaces to cbs-size\n\
308 unblock replace trailing spaces in cbs-size records with newline\n\
309 lcase change upper case to lower case\n\
310 notrunc do not truncate the output file\n\
311 ucase change lower case to upper case\n\
312 swab swap every pair of input bytes\n\
313 noerror continue after read errors\n\
314 sync pad every input block with NULs to ibs-size\n\
315 "));
316 puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
317 close_stdout ();
319 exit (status);
322 static void
323 translate_charset (const unsigned char *new_trans)
325 int i;
327 for (i = 0; i < 256; i++)
328 trans_table[i] = new_trans[trans_table[i]];
329 translation_needed = 1;
332 /* Return the number of 1 bits in `i'. */
334 static int
335 bit_count (register unsigned int i)
337 register int set_bits;
339 for (set_bits = 0; i != 0; set_bits++)
340 i &= i - 1;
341 return set_bits;
344 static void
345 print_stats (void)
347 char buf[2][LONGEST_HUMAN_READABLE + 1];
348 fprintf (stderr, _("%s+%s records in\n"),
349 human_readable (r_full, buf[0], 1, 1),
350 human_readable (r_partial, buf[1], 1, 1));
351 fprintf (stderr, _("%s+%s records out\n"),
352 human_readable (w_full, buf[0], 1, 1),
353 human_readable (w_partial, buf[1], 1, 1));
354 if (r_truncate > 0)
356 fprintf (stderr, "%s %s\n",
357 human_readable (r_truncate, buf[0], 1, 1),
358 (r_truncate == 1
359 ? _("truncated record")
360 : _("truncated records")));
364 static void
365 cleanup (void)
367 print_stats ();
368 if (close (STDIN_FILENO) < 0)
369 error (1, errno, "%s", input_file);
370 if (close (STDOUT_FILENO) < 0)
371 error (1, errno, "%s", output_file);
374 static inline void
375 quit (int code)
377 cleanup ();
378 exit (code);
381 static RETSIGTYPE
382 interrupt_handler (int sig)
384 #ifdef SA_INTERRUPT
385 struct sigaction sigact;
387 sigact.sa_handler = SIG_DFL;
388 sigemptyset (&sigact.sa_mask);
389 sigact.sa_flags = 0;
390 sigaction (sig, &sigact, NULL);
391 #else /* !SA_INTERRUPT */
392 signal (sig, SIG_DFL);
393 #endif /* SA_INTERRUPT */
394 cleanup ();
395 kill (getpid (), sig);
398 static RETSIGTYPE
399 siginfo_handler (int sig)
401 print_stats ();
404 /* Encapsulate portability mess of establishing signal handlers. */
406 static void
407 install_handler (int sig_num, RETSIGTYPE (*sig_handler) (int sig))
409 #ifdef _POSIX_VERSION
410 struct sigaction sigact;
411 sigaction (sig_num, NULL, &sigact);
412 if (sigact.sa_handler != SIG_IGN)
414 sigact.sa_handler = sig_handler;
415 sigemptyset (&sigact.sa_mask);
416 sigact.sa_flags = 0;
417 sigaction (sig_num, &sigact, NULL);
419 #else
420 if (signal (sig_num, SIG_IGN) != SIG_IGN)
421 signal (sig_num, sig_handler);
422 #endif
425 /* Open a file to a particular file descriptor. This is like standard
426 `open', except it always returns DESIRED_FD if successful. */
427 static int
428 open_fd (int desired_fd, char const *filename, int options, mode_t mode)
430 int fd;
431 close (desired_fd);
432 fd = open (filename, options, mode);
433 if (fd < 0)
434 return -1;
436 if (fd != desired_fd)
438 if (dup2 (fd, desired_fd) != desired_fd)
439 desired_fd = -1;
440 if (close (fd) != 0)
441 return -1;
444 return desired_fd;
447 /* Write, then empty, the output buffer `obuf'. */
449 static void
450 write_output (void)
452 int nwritten = full_write (STDOUT_FILENO, obuf, output_blocksize);
453 if (nwritten != output_blocksize)
455 error (0, errno, "%s", output_file);
456 if (nwritten > 0)
457 w_partial++;
458 quit (1);
460 else
461 w_full++;
462 oc = 0;
465 /* Interpret one "conv=..." option. */
467 static void
468 parse_conversion (char *str)
470 char *new;
471 int i;
475 new = strchr (str, ',');
476 if (new != NULL)
477 *new++ = '\0';
478 for (i = 0; conversions[i].convname != NULL; i++)
479 if (STREQ (conversions[i].convname, str))
481 conversions_mask |= conversions[i].conversion;
482 break;
484 if (conversions[i].convname == NULL)
486 error (0, 0, _("%s: invalid conversion"), str);
487 usage (1);
489 str = new;
490 } while (new != NULL);
493 /* Return the value of STR, interpreted as a non-negative decimal integer,
494 optionally multiplied by various values.
495 Assign nonzero to *INVALID if STR does not represent a number in
496 this format. */
498 static uintmax_t
499 parse_integer (char *str, int *invalid)
501 uintmax_t n;
502 enum strtol_error e = xstrtoumax (str, &str, 10, &n, "bcEGkMPTwYZ0");
504 if (e == LONGINT_INVALID_SUFFIX_CHAR && *str == 'x')
506 uintmax_t multiplier = parse_integer (str + 1, invalid);
508 if (multiplier != 0 && n * multiplier / multiplier != n)
510 *invalid = 1;
511 return 0;
514 n *= multiplier;
516 else if (e != LONGINT_OK)
518 *invalid = 1;
519 return 0;
522 return n;
525 static void
526 scanargs (int argc, char **argv)
528 int i;
530 --argc;
531 ++argv;
533 for (i = optind; i < argc; i++)
535 char *name, *val;
537 name = argv[i];
538 val = strchr (name, '=');
539 if (val == NULL)
541 error (0, 0, _("unrecognized option `%s'"), name);
542 usage (1);
544 *val++ = '\0';
546 if (STREQ (name, "if"))
547 input_file = val;
548 else if (STREQ (name, "of"))
549 output_file = val;
550 else if (STREQ (name, "conv"))
551 parse_conversion (val);
552 else
554 int invalid = 0;
555 uintmax_t n = parse_integer (val, &invalid);
557 if (STREQ (name, "ibs"))
559 input_blocksize = n;
560 invalid |= input_blocksize != n || input_blocksize == 0;
561 conversions_mask |= C_TWOBUFS;
563 else if (STREQ (name, "obs"))
565 output_blocksize = n;
566 invalid |= output_blocksize != n || output_blocksize == 0;
567 conversions_mask |= C_TWOBUFS;
569 else if (STREQ (name, "bs"))
571 output_blocksize = input_blocksize = n;
572 invalid |= output_blocksize != n || output_blocksize == 0;
574 else if (STREQ (name, "cbs"))
576 conversion_blocksize = n;
577 invalid |= (conversion_blocksize != n
578 || conversion_blocksize == 0);
580 else if (STREQ (name, "skip"))
581 skip_records = n;
582 else if (STREQ (name, "seek"))
583 seek_record = n;
584 else if (STREQ (name, "count"))
585 max_records = n;
586 else
588 error (0, 0, _("unrecognized option `%s=%s'"), name, val);
589 usage (1);
592 if (invalid)
593 error (1, 0, _("invalid number `%s'"), val);
597 /* If bs= was given, both `input_blocksize' and `output_blocksize' will
598 have been set to positive values. If either has not been set,
599 bs= was not given, so make sure two buffers are used. */
600 if (input_blocksize == 0 || output_blocksize == 0)
601 conversions_mask |= C_TWOBUFS;
602 if (input_blocksize == 0)
603 input_blocksize = DEFAULT_BLOCKSIZE;
604 if (output_blocksize == 0)
605 output_blocksize = DEFAULT_BLOCKSIZE;
606 if (conversion_blocksize == 0)
607 conversions_mask &= ~(C_BLOCK | C_UNBLOCK);
610 /* Fix up translation table. */
612 static void
613 apply_translations (void)
615 int i;
617 #define MX(a) (bit_count (conversions_mask & (a)))
618 if ((MX (C_ASCII | C_EBCDIC | C_IBM) > 1)
619 || (MX (C_BLOCK | C_UNBLOCK) > 1)
620 || (MX (C_LCASE | C_UCASE) > 1)
621 || (MX (C_UNBLOCK | C_SYNC) > 1))
623 error (1, 0, _("\
624 only one conv in {ascii,ebcdic,ibm}, {lcase,ucase}, {block,unblock}, {unblock,sync}"));
626 #undef MX
628 if (conversions_mask & C_ASCII)
629 translate_charset (ebcdic_to_ascii);
631 if (conversions_mask & C_UCASE)
633 for (i = 0; i < 256; i++)
634 if (ISLOWER (trans_table[i]))
635 trans_table[i] = TOUPPER (trans_table[i]);
636 translation_needed = 1;
638 else if (conversions_mask & C_LCASE)
640 for (i = 0; i < 256; i++)
641 if (ISUPPER (trans_table[i]))
642 trans_table[i] = TOLOWER (trans_table[i]);
643 translation_needed = 1;
646 if (conversions_mask & C_EBCDIC)
648 translate_charset (ascii_to_ebcdic);
649 newline_character = ascii_to_ebcdic['\n'];
650 space_character = ascii_to_ebcdic[' '];
652 else if (conversions_mask & C_IBM)
654 translate_charset (ascii_to_ibm);
655 newline_character = ascii_to_ibm['\n'];
656 space_character = ascii_to_ibm[' '];
660 /* Apply the character-set translations specified by the user
661 to the NREAD bytes in BUF. */
663 static void
664 translate_buffer (unsigned char *buf, int nread)
666 register unsigned char *cp;
667 register int i;
669 for (i = nread, cp = buf; i; i--, cp++)
670 *cp = trans_table[*cp];
673 /* If nonnzero, the last char from the previous call to `swab_buffer'
674 is saved in `saved_char'. */
675 static int char_is_saved = 0;
677 /* Odd char from previous call. */
678 static unsigned char saved_char;
680 /* Swap NREAD bytes in BUF, plus possibly an initial char from the
681 previous call. If NREAD is odd, save the last char for the
682 next call. Return the new start of the BUF buffer. */
684 static unsigned char *
685 swab_buffer (unsigned char *buf, int *nread)
687 unsigned char *bufstart = buf;
688 register unsigned char *cp;
689 register int i;
691 /* Is a char left from last time? */
692 if (char_is_saved)
694 *--bufstart = saved_char;
695 (*nread)++;
696 char_is_saved = 0;
699 if (*nread & 1)
701 /* An odd number of chars are in the buffer. */
702 saved_char = bufstart[--*nread];
703 char_is_saved = 1;
706 /* Do the byte-swapping by moving every second character two
707 positions toward the end, working from the end of the buffer
708 toward the beginning. This way we only move half of the data. */
710 cp = bufstart + *nread; /* Start one char past the last. */
711 for (i = *nread / 2; i; i--, cp -= 2)
712 *cp = *(cp - 2);
714 return ++bufstart;
717 /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
718 which is open with read permission for FILE. Store up to BLOCKSIZE
719 bytes of the data at a time in BUF, if necessary. */
721 static void
722 skip (int fdesc, char *file, uintmax_t records, size_t blocksize,
723 unsigned char *buf)
725 off_t o;
727 /* Try lseek and if an error indicates it was an inappropriate
728 operation, fall back on using read. */
729 o = records * blocksize;
730 if (o / blocksize != records
731 || lseek (fdesc, o, SEEK_SET) == -1)
733 while (records-- > 0)
735 int nread;
737 nread = safe_read (fdesc, buf, blocksize);
738 if (nread < 0)
740 error (0, errno, "%s", file);
741 quit (1);
743 /* POSIX doesn't say what to do when dd detects it has been
744 asked to skip past EOF, so I assume it's non-fatal.
745 FIXME: maybe give a warning. */
746 if (nread == 0)
747 break;
752 /* Copy NREAD bytes of BUF, with no conversions. */
754 static void
755 copy_simple (unsigned char *buf, int nread)
757 int nfree; /* Number of unused bytes in `obuf'. */
758 unsigned char *start = buf; /* First uncopied char in BUF. */
762 nfree = output_blocksize - oc;
763 if (nfree > nread)
764 nfree = nread;
766 memcpy ((char *) (obuf + oc), (char *) start, nfree);
768 nread -= nfree; /* Update the number of bytes left to copy. */
769 start += nfree;
770 oc += nfree;
771 if (oc >= output_blocksize)
772 write_output ();
774 while (nread > 0);
777 /* Copy NREAD bytes of BUF, doing conv=block
778 (pad newline-terminated records to `conversion_blocksize',
779 replacing the newline with trailing spaces). */
781 static void
782 copy_with_block (unsigned char *buf, int nread)
784 register int i;
786 for (i = nread; i; i--, buf++)
788 if (*buf == newline_character)
790 if (col < conversion_blocksize)
792 size_t j;
793 for (j = col; j < conversion_blocksize; j++)
794 output_char (space_character);
796 col = 0;
798 else
800 if (col == conversion_blocksize)
801 r_truncate++;
802 else if (col < conversion_blocksize)
803 output_char (*buf);
804 col++;
809 /* Copy NREAD bytes of BUF, doing conv=unblock
810 (replace trailing spaces in `conversion_blocksize'-sized records
811 with a newline). */
813 static void
814 copy_with_unblock (unsigned char *buf, int nread)
816 register int i;
817 register unsigned char c;
818 static int pending_spaces = 0;
820 for (i = 0; i < nread; i++)
822 c = buf[i];
824 if (col++ >= conversion_blocksize)
826 col = pending_spaces = 0; /* Wipe out any pending spaces. */
827 i--; /* Push the char back; get it later. */
828 output_char (newline_character);
830 else if (c == space_character)
831 pending_spaces++;
832 else
834 /* `c' is the character after a run of spaces that were not
835 at the end of the conversion buffer. Output them. */
836 while (pending_spaces)
838 output_char (space_character);
839 --pending_spaces;
841 output_char (c);
846 /* The main loop. */
848 static int
849 dd_copy (void)
851 unsigned char *ibuf, *bufstart; /* Input buffer. */
852 unsigned char *real_buf; /* real buffer address before alignment */
853 unsigned char *real_obuf;
854 int nread; /* Bytes read in the current block. */
855 int exit_status = 0;
856 size_t page_size = getpagesize ();
858 /* Leave at least one extra byte at the beginning and end of `ibuf'
859 for conv=swab, but keep the buffer address even. But some peculiar
860 device drivers work only with word-aligned buffers, so leave an
861 extra two bytes. */
863 /* Some devices require alignment on a sector or page boundary
864 (e.g. character disk devices). Align the input buffer to a
865 page boundary to cover all bases. Note that due to the swab
866 algorithm, we must have at least one byte in the page before
867 the input buffer; thus we allocate 2 pages of slop in the
868 real buffer. 8k above the blocksize shouldn't bother anyone.
870 The page alignment is necessary on any linux system that supports
871 either the SGI raw I/O patch or Steven Tweedies raw I/O patch.
872 It is necessary when accessing raw (i.e. character special) disk
873 devices on Unixware or other SVR4-derived system. */
875 real_buf = (unsigned char *) xmalloc (input_blocksize
876 + 2 * SWAB_ALIGN_OFFSET
877 + 2 * page_size - 1);
878 ibuf = real_buf;
879 ibuf += SWAB_ALIGN_OFFSET; /* allow space for swab */
881 ibuf = PTR_ALIGN (ibuf, page_size);
883 if (conversions_mask & C_TWOBUFS)
885 /* Page-align the output buffer, too. */
886 real_obuf = (unsigned char *) xmalloc (output_blocksize + page_size - 1);
887 obuf = PTR_ALIGN (real_obuf, page_size);
889 else
891 real_obuf = NULL;
892 obuf = ibuf;
895 if (skip_records != 0)
896 skip (STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf);
898 if (seek_record != 0)
900 /* FIXME: this loses for
901 % ./dd if=dd seek=1 |:
902 ./dd: standard output: Bad file number
903 0+0 records in
904 0+0 records out
907 skip (STDOUT_FILENO, output_file, seek_record, output_blocksize,
908 obuf);
911 if (max_records == 0)
912 quit (exit_status);
914 while (1)
916 if (r_partial + r_full >= max_records)
917 break;
919 /* Zero the buffer before reading, so that if we get a read error,
920 whatever data we are able to read is followed by zeros.
921 This minimizes data loss. */
922 if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
923 memset ((char *) ibuf, 0, input_blocksize);
925 nread = safe_read (STDIN_FILENO, ibuf, input_blocksize);
927 if (nread == 0)
928 break; /* EOF. */
930 if (nread < 0)
932 error (0, errno, "%s", input_file);
933 if (conversions_mask & C_NOERROR)
935 print_stats ();
936 /* Seek past the bad block if possible. */
937 lseek (STDIN_FILENO, (off_t) input_blocksize, SEEK_CUR);
938 if (conversions_mask & C_SYNC)
939 /* Replace the missing input with null bytes and
940 proceed normally. */
941 nread = 0;
942 else
943 continue;
945 else
947 /* Write any partial block. */
948 exit_status = 2;
949 break;
953 if (nread < input_blocksize)
955 r_partial++;
956 if (conversions_mask & C_SYNC)
958 if (!(conversions_mask & C_NOERROR))
959 /* If C_NOERROR, we zeroed the block before reading. */
960 memset ((char *) (ibuf + nread), 0, input_blocksize - nread);
961 nread = input_blocksize;
964 else
965 r_full++;
967 if (ibuf == obuf) /* If not C_TWOBUFS. */
969 int nwritten = full_write (STDOUT_FILENO, obuf, nread);
970 if (nwritten < 0)
972 error (0, errno, "%s", output_file);
973 quit (1);
975 else if (nread == input_blocksize)
976 w_full++;
977 else
978 w_partial++;
979 continue;
982 /* Do any translations on the whole buffer at once. */
984 if (translation_needed)
985 translate_buffer (ibuf, nread);
987 if (conversions_mask & C_SWAB)
988 bufstart = swab_buffer (ibuf, &nread);
989 else
990 bufstart = ibuf;
992 if (conversions_mask & C_BLOCK)
993 copy_with_block (bufstart, nread);
994 else if (conversions_mask & C_UNBLOCK)
995 copy_with_unblock (bufstart, nread);
996 else
997 copy_simple (bufstart, nread);
1000 /* If we have a char left as a result of conv=swab, output it. */
1001 if (char_is_saved)
1003 if (conversions_mask & C_BLOCK)
1004 copy_with_block (&saved_char, 1);
1005 else if (conversions_mask & C_UNBLOCK)
1006 copy_with_unblock (&saved_char, 1);
1007 else
1008 output_char (saved_char);
1011 if ((conversions_mask & C_BLOCK) && col > 0)
1013 /* If the final input line didn't end with a '\n', pad
1014 the output block to `conversion_blocksize' chars. */
1015 size_t i;
1016 for (i = col; i < conversion_blocksize; i++)
1017 output_char (space_character);
1020 if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
1021 /* Add a final '\n' if there are exactly `conversion_blocksize'
1022 characters in the final record. */
1023 output_char (newline_character);
1025 /* Write out the last block. */
1026 if (oc != 0)
1028 int nwritten = full_write (STDOUT_FILENO, obuf, oc);
1029 if (nwritten > 0)
1030 w_partial++;
1031 if (nwritten < 0)
1033 error (0, errno, "%s", output_file);
1034 quit (1);
1038 free (real_buf);
1039 if (real_obuf)
1040 free (real_obuf);
1042 return exit_status;
1046 main (int argc, char **argv)
1048 int i;
1049 int exit_status;
1051 program_name = argv[0];
1052 setlocale (LC_ALL, "");
1053 bindtextdomain (PACKAGE, LOCALEDIR);
1054 textdomain (PACKAGE);
1056 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
1057 AUTHORS, usage);
1059 /* Initialize translation table to identity translation. */
1060 for (i = 0; i < 256; i++)
1061 trans_table[i] = i;
1063 /* Decode arguments. */
1064 scanargs (argc, argv);
1066 apply_translations ();
1068 if (input_file != NULL)
1070 if (open_fd (STDIN_FILENO, input_file, O_RDONLY, 0) < 0)
1071 error (1, errno, "%s", input_file);
1073 else
1074 input_file = _("standard input");
1076 if (output_file != NULL)
1078 mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1079 int opts
1080 = (O_CREAT
1081 | (seek_record || (conversions_mask & C_NOTRUNC) ? 0 : O_TRUNC));
1083 /* Open the output file with *read* access only if we might
1084 need to read to satisfy a `seek=' request. If we can't read
1085 the file, go ahead with write-only access; it might work. */
1086 if ((! seek_record
1087 || open_fd (STDOUT_FILENO, output_file, O_RDWR | opts, perms) < 0)
1088 && open_fd (STDOUT_FILENO, output_file, O_WRONLY | opts, perms) < 0)
1089 error (1, errno, "%s", output_file);
1090 #if HAVE_FTRUNCATE
1091 if (seek_record != 0 && !(conversions_mask & C_NOTRUNC))
1093 off_t o = seek_record * output_blocksize;
1094 if (o / output_blocksize != seek_record)
1095 error (1, 0, _("file offset out of range"));
1096 if (ftruncate (STDOUT_FILENO, o) < 0)
1097 error (0, errno, "%s", output_file);
1099 #endif
1101 else
1103 output_file = _("standard output");
1106 install_handler (SIGINT, interrupt_handler);
1107 install_handler (SIGQUIT, interrupt_handler);
1108 install_handler (SIGPIPE, interrupt_handler);
1109 install_handler (SIGINFO, siginfo_handler);
1111 exit_status = dd_copy ();
1113 quit (exit_status);