Sanitize environment.
[coreutils.git] / src / dd.c
bloba4cd1dff0fe503e002cabfa29e6e96255b53b95c
1 /* dd -- convert a file while copying it.
2 Copyright (C) 85, 90, 91, 1995-2004 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 #include <sys/types.h>
26 #include <signal.h>
27 #include <getopt.h>
29 #include "system.h"
30 #include "error.h"
31 #include "full-write.h"
32 #include "getpagesize.h"
33 #include "human.h"
34 #include "inttostr.h"
35 #include "long-options.h"
36 #include "quote.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", "Stuart Kemp"
45 #ifndef SIGINFO
46 # define SIGINFO SIGUSR1
47 #endif
49 #ifndef S_TYPEISSHM
50 # define S_TYPEISSHM(Stat_ptr) 0
51 #endif
53 #if ! HAVE_FDATASYNC
54 # define fdatasync(fd) (errno = ENOSYS, -1)
55 #endif
57 #define max(a, b) ((a) > (b) ? (a) : (b))
58 #define output_char(c) \
59 do \
60 { \
61 obuf[oc++] = (c); \
62 if (oc >= output_blocksize) \
63 write_output (); \
64 } \
65 while (0)
67 /* Default input and output blocksize. */
68 #define DEFAULT_BLOCKSIZE 512
70 /* Maximum blocksize. Keep it smaller than SIZE_MAX, so that we can
71 allocate buffers that size. Keep it smaller than SSIZE_MAX, for
72 the benefit of system calls like "read". And keep it smaller than
73 OFF_T_MAX, for the benefit of the large-offset seek code. */
74 #define MAX_BLOCKSIZE MIN (SIZE_MAX, MIN (SSIZE_MAX, OFF_T_MAX))
76 /* Conversions bit masks. */
77 enum
79 C_ASCII = 01,
81 C_EBCDIC = 02,
82 C_IBM = 04,
83 C_BLOCK = 010,
84 C_UNBLOCK = 020,
85 C_LCASE = 040,
86 C_UCASE = 0100,
87 C_SWAB = 0200,
88 C_NOERROR = 0400,
89 C_NOTRUNC = 01000,
90 C_SYNC = 02000,
92 /* Use separate input and output buffers, and combine partial
93 input blocks. */
94 C_TWOBUFS = 04000,
96 C_NOCREAT = 010000,
97 C_EXCL = 020000,
98 C_FDATASYNC = 040000,
99 C_FSYNC = 0100000
102 /* Status bit masks. */
103 enum
105 STATUS_NOXFER = 01
108 /* The name this program was run with. */
109 char *program_name;
111 /* The name of the input file, or NULL for the standard input. */
112 static char const *input_file = NULL;
114 /* The name of the output file, or NULL for the standard output. */
115 static char const *output_file = NULL;
117 /* The number of bytes in which atomic reads are done. */
118 static size_t input_blocksize = 0;
120 /* The number of bytes in which atomic writes are done. */
121 static size_t output_blocksize = 0;
123 /* Conversion buffer size, in bytes. 0 prevents conversions. */
124 static size_t conversion_blocksize = 0;
126 /* Skip this many records of `input_blocksize' bytes before input. */
127 static uintmax_t skip_records = 0;
129 /* Skip this many records of `output_blocksize' bytes before output. */
130 static uintmax_t seek_records = 0;
132 /* Copy only this many records. The default is effectively infinity. */
133 static uintmax_t max_records = (uintmax_t) -1;
135 /* Bit vector of conversions to apply. */
136 static int conversions_mask = 0;
138 /* Open flags for the input and output files. */
139 static int input_flags = 0;
140 static int output_flags = 0;
142 /* Status flags for what is printed to stderr. */
143 static int status_flags = 0;
145 /* If nonzero, filter characters through the translation table. */
146 static bool translation_needed = false;
148 /* Number of partial blocks written. */
149 static uintmax_t w_partial = 0;
151 /* Number of full blocks written. */
152 static uintmax_t w_full = 0;
154 /* Number of partial blocks read. */
155 static uintmax_t r_partial = 0;
157 /* Number of full blocks read. */
158 static uintmax_t r_full = 0;
160 /* Number of bytes written. */
161 static uintmax_t w_bytes = 0;
163 /* Time that dd started. */
164 static struct timespec start_time;
166 /* True if input is seekable. */
167 static bool input_seekable;
169 /* Error number corresponding to initial attempt to lseek input.
170 If ESPIPE, do not issue any more diagnostics about it. */
171 static int input_seek_errno;
173 /* File offset of the input, in bytes, along with a flag recording
174 whether it overflowed. The offset is valid only if the input is
175 seekable and if the offset has not overflowed. */
176 static uintmax_t input_offset;
177 static bool input_offset_overflow;
179 /* Records truncated by conv=block. */
180 static uintmax_t r_truncate = 0;
182 /* Output representation of newline and space characters.
183 They change if we're converting to EBCDIC. */
184 static char newline_character = '\n';
185 static char space_character = ' ';
187 /* Output buffer. */
188 static char *obuf;
190 /* Current index into `obuf'. */
191 static size_t oc = 0;
193 /* Index into current line, for `conv=block' and `conv=unblock'. */
194 static size_t col = 0;
196 /* A longest symbol in the struct symbol_values tables below. */
197 #define LONGEST_SYMBOL "fdatasync"
199 /* A symbol and the corresponding integer value. */
200 struct symbol_value
202 char symbol[sizeof LONGEST_SYMBOL];
203 int value;
206 /* Conversion symbols, for conv="...". */
207 static struct symbol_value const conversions[] =
209 {"ascii", C_ASCII | C_TWOBUFS}, /* EBCDIC to ASCII. */
210 {"ebcdic", C_EBCDIC | C_TWOBUFS}, /* ASCII to EBCDIC. */
211 {"ibm", C_IBM | C_TWOBUFS}, /* Slightly different ASCII to EBCDIC. */
212 {"block", C_BLOCK | C_TWOBUFS}, /* Variable to fixed length records. */
213 {"unblock", C_UNBLOCK | C_TWOBUFS}, /* Fixed to variable length records. */
214 {"lcase", C_LCASE | C_TWOBUFS}, /* Translate upper to lower case. */
215 {"ucase", C_UCASE | C_TWOBUFS}, /* Translate lower to upper case. */
216 {"swab", C_SWAB | C_TWOBUFS}, /* Swap bytes of input. */
217 {"noerror", C_NOERROR}, /* Ignore i/o errors. */
218 {"nocreat", C_NOCREAT}, /* Do not create output file. */
219 {"excl", C_EXCL}, /* Fail if the output file already exists. */
220 {"notrunc", C_NOTRUNC}, /* Do not truncate output file. */
221 {"sync", C_SYNC}, /* Pad input records to ibs with NULs. */
222 {"fdatasync", C_FDATASYNC}, /* Synchronize output data before finishing. */
223 {"fsync", C_FSYNC}, /* Also synchronize output metadata. */
224 {"", 0}
227 /* Flags, for iflag="..." and oflag="...". */
228 static struct symbol_value const flags[] =
230 {"append", O_APPEND},
231 {"direct", O_DIRECT},
232 {"dsync", O_DSYNC},
233 {"noctty", O_NOCTTY},
234 {"nofollow", O_NOFOLLOW},
235 {"nonblock", O_NONBLOCK},
236 {"sync", O_SYNC},
237 {"", 0}
240 /* Status, for status="...". */
241 static struct symbol_value const statuses[] =
243 {"noxfer", STATUS_NOXFER},
244 {"", 0}
247 /* Translation table formed by applying successive transformations. */
248 static unsigned char trans_table[256];
250 static char const ascii_to_ebcdic[] =
252 '\000', '\001', '\002', '\003', '\067', '\055', '\056', '\057',
253 '\026', '\005', '\045', '\013', '\014', '\015', '\016', '\017',
254 '\020', '\021', '\022', '\023', '\074', '\075', '\062', '\046',
255 '\030', '\031', '\077', '\047', '\034', '\035', '\036', '\037',
256 '\100', '\117', '\177', '\173', '\133', '\154', '\120', '\175',
257 '\115', '\135', '\134', '\116', '\153', '\140', '\113', '\141',
258 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
259 '\370', '\371', '\172', '\136', '\114', '\176', '\156', '\157',
260 '\174', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
261 '\310', '\311', '\321', '\322', '\323', '\324', '\325', '\326',
262 '\327', '\330', '\331', '\342', '\343', '\344', '\345', '\346',
263 '\347', '\350', '\351', '\112', '\340', '\132', '\137', '\155',
264 '\171', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
265 '\210', '\211', '\221', '\222', '\223', '\224', '\225', '\226',
266 '\227', '\230', '\231', '\242', '\243', '\244', '\245', '\246',
267 '\247', '\250', '\251', '\300', '\152', '\320', '\241', '\007',
268 '\040', '\041', '\042', '\043', '\044', '\025', '\006', '\027',
269 '\050', '\051', '\052', '\053', '\054', '\011', '\012', '\033',
270 '\060', '\061', '\032', '\063', '\064', '\065', '\066', '\010',
271 '\070', '\071', '\072', '\073', '\004', '\024', '\076', '\341',
272 '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110',
273 '\111', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
274 '\130', '\131', '\142', '\143', '\144', '\145', '\146', '\147',
275 '\150', '\151', '\160', '\161', '\162', '\163', '\164', '\165',
276 '\166', '\167', '\170', '\200', '\212', '\213', '\214', '\215',
277 '\216', '\217', '\220', '\232', '\233', '\234', '\235', '\236',
278 '\237', '\240', '\252', '\253', '\254', '\255', '\256', '\257',
279 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
280 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
281 '\312', '\313', '\314', '\315', '\316', '\317', '\332', '\333',
282 '\334', '\335', '\336', '\337', '\352', '\353', '\354', '\355',
283 '\356', '\357', '\372', '\373', '\374', '\375', '\376', '\377'
286 static char const ascii_to_ibm[] =
288 '\000', '\001', '\002', '\003', '\067', '\055', '\056', '\057',
289 '\026', '\005', '\045', '\013', '\014', '\015', '\016', '\017',
290 '\020', '\021', '\022', '\023', '\074', '\075', '\062', '\046',
291 '\030', '\031', '\077', '\047', '\034', '\035', '\036', '\037',
292 '\100', '\132', '\177', '\173', '\133', '\154', '\120', '\175',
293 '\115', '\135', '\134', '\116', '\153', '\140', '\113', '\141',
294 '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
295 '\370', '\371', '\172', '\136', '\114', '\176', '\156', '\157',
296 '\174', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
297 '\310', '\311', '\321', '\322', '\323', '\324', '\325', '\326',
298 '\327', '\330', '\331', '\342', '\343', '\344', '\345', '\346',
299 '\347', '\350', '\351', '\255', '\340', '\275', '\137', '\155',
300 '\171', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
301 '\210', '\211', '\221', '\222', '\223', '\224', '\225', '\226',
302 '\227', '\230', '\231', '\242', '\243', '\244', '\245', '\246',
303 '\247', '\250', '\251', '\300', '\117', '\320', '\241', '\007',
304 '\040', '\041', '\042', '\043', '\044', '\025', '\006', '\027',
305 '\050', '\051', '\052', '\053', '\054', '\011', '\012', '\033',
306 '\060', '\061', '\032', '\063', '\064', '\065', '\066', '\010',
307 '\070', '\071', '\072', '\073', '\004', '\024', '\076', '\341',
308 '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110',
309 '\111', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
310 '\130', '\131', '\142', '\143', '\144', '\145', '\146', '\147',
311 '\150', '\151', '\160', '\161', '\162', '\163', '\164', '\165',
312 '\166', '\167', '\170', '\200', '\212', '\213', '\214', '\215',
313 '\216', '\217', '\220', '\232', '\233', '\234', '\235', '\236',
314 '\237', '\240', '\252', '\253', '\254', '\255', '\256', '\257',
315 '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
316 '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
317 '\312', '\313', '\314', '\315', '\316', '\317', '\332', '\333',
318 '\334', '\335', '\336', '\337', '\352', '\353', '\354', '\355',
319 '\356', '\357', '\372', '\373', '\374', '\375', '\376', '\377'
322 static char const ebcdic_to_ascii[] =
324 '\000', '\001', '\002', '\003', '\234', '\011', '\206', '\177',
325 '\227', '\215', '\216', '\013', '\014', '\015', '\016', '\017',
326 '\020', '\021', '\022', '\023', '\235', '\205', '\010', '\207',
327 '\030', '\031', '\222', '\217', '\034', '\035', '\036', '\037',
328 '\200', '\201', '\202', '\203', '\204', '\012', '\027', '\033',
329 '\210', '\211', '\212', '\213', '\214', '\005', '\006', '\007',
330 '\220', '\221', '\026', '\223', '\224', '\225', '\226', '\004',
331 '\230', '\231', '\232', '\233', '\024', '\025', '\236', '\032',
332 '\040', '\240', '\241', '\242', '\243', '\244', '\245', '\246',
333 '\247', '\250', '\133', '\056', '\074', '\050', '\053', '\041',
334 '\046', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
335 '\260', '\261', '\135', '\044', '\052', '\051', '\073', '\136',
336 '\055', '\057', '\262', '\263', '\264', '\265', '\266', '\267',
337 '\270', '\271', '\174', '\054', '\045', '\137', '\076', '\077',
338 '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301',
339 '\302', '\140', '\072', '\043', '\100', '\047', '\075', '\042',
340 '\303', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
341 '\150', '\151', '\304', '\305', '\306', '\307', '\310', '\311',
342 '\312', '\152', '\153', '\154', '\155', '\156', '\157', '\160',
343 '\161', '\162', '\313', '\314', '\315', '\316', '\317', '\320',
344 '\321', '\176', '\163', '\164', '\165', '\166', '\167', '\170',
345 '\171', '\172', '\322', '\323', '\324', '\325', '\326', '\327',
346 '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
347 '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
348 '\173', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
349 '\110', '\111', '\350', '\351', '\352', '\353', '\354', '\355',
350 '\175', '\112', '\113', '\114', '\115', '\116', '\117', '\120',
351 '\121', '\122', '\356', '\357', '\360', '\361', '\362', '\363',
352 '\134', '\237', '\123', '\124', '\125', '\126', '\127', '\130',
353 '\131', '\132', '\364', '\365', '\366', '\367', '\370', '\371',
354 '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
355 '\070', '\071', '\372', '\373', '\374', '\375', '\376', '\377'
358 void
359 usage (int status)
361 if (status != EXIT_SUCCESS)
362 fprintf (stderr, _("Try `%s --help' for more information.\n"),
363 program_name);
364 else
366 printf (_("\
367 Usage: %s [OPERAND]...\n\
368 or: %s OPTION\n\
370 program_name, program_name);
371 fputs (_("\
372 Copy a file, converting and formatting according to the operands.\n\
374 bs=BYTES force ibs=BYTES and obs=BYTES\n\
375 cbs=BYTES convert BYTES bytes at a time\n\
376 conv=CONVS convert the file as per the comma separated symbol list\n\
377 count=BLOCKS copy only BLOCKS input blocks\n\
378 ibs=BYTES read BYTES bytes at a time\n\
379 "), stdout);
380 fputs (_("\
381 if=FILE read from FILE instead of stdin\n\
382 iflag=FLAGS read as per the comma separated symbol list\n\
383 obs=BYTES write BYTES bytes at a time\n\
384 of=FILE write to FILE instead of stdout\n\
385 oflag=FLAGS write as per the comma separated symbol list\n\
386 seek=BLOCKS skip BLOCKS obs-sized blocks at start of output\n\
387 skip=BLOCKS skip BLOCKS ibs-sized blocks at start of input\n\
388 status=noxfer suppress transfer statistics\n\
389 "), stdout);
390 fputs (_("\
392 BLOCKS and BYTES may be followed by the following multiplicative suffixes:\n\
393 xM M, c 1, w 2, b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\
394 GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\
396 Each CONV symbol may be:\n\
398 "), stdout);
399 fputs (_("\
400 ascii from EBCDIC to ASCII\n\
401 ebcdic from ASCII to EBCDIC\n\
402 ibm from ASCII to alternate EBCDIC\n\
403 block pad newline-terminated records with spaces to cbs-size\n\
404 unblock replace trailing spaces in cbs-size records with newline\n\
405 lcase change upper case to lower case\n\
406 "), stdout);
407 fputs (_("\
408 nocreat do not create the output file\n\
409 excl fail if the output file already exists\n\
410 notrunc do not truncate the output file\n\
411 ucase change lower case to upper case\n\
412 swab swap every pair of input bytes\n\
413 noerror continue after read errors\n\
414 sync pad every input block with NULs to ibs-size; when used\n\
415 with block or unblock, pad with spaces rather than NULs\n\
416 fdatasync physically write output file data before finishing\n\
417 fsync likewise, but also write metadata\n\
418 "), stdout);
419 fputs (_("\
421 Each FLAG symbol may be:\n\
423 append append mode (makes sense only for output)\n\
424 "), stdout);
425 if (O_DIRECT)
426 fputs (_(" direct use direct I/O for data\n"), stdout);
427 if (O_DSYNC)
428 fputs (_(" dsync use synchronized I/O for data\n"), stdout);
429 if (O_SYNC)
430 fputs (_(" sync likewise, but also for metadata\n"), stdout);
431 if (O_NONBLOCK)
432 fputs (_(" nonblock use non-blocking I/O\n"), stdout);
433 if (O_NOFOLLOW)
434 fputs (_(" nofollow do not follow symlinks\n"), stdout);
435 if (O_NOCTTY)
436 fputs (_(" noctty do not assign controlling terminal from file\n"),
437 stdout);
438 fputs (_("\
440 Sending a SIGUSR1 signal to a running `dd' process makes it\n\
441 print I/O statistics to standard error, then to resume copying.\n\
443 $ dd if=/dev/zero of=/dev/null& pid=$!\n\
444 $ kill -USR1 $pid; sleep 1; kill $pid\n\
445 18335302+0 records in\n\
446 18335302+0 records out\n\
447 9387674624 bytes (9.4 GB) copied, 34.6279 seconds, 271 MB/s\n\
449 Options are:\n\
451 "), stdout);
452 fputs (HELP_OPTION_DESCRIPTION, stdout);
453 fputs (VERSION_OPTION_DESCRIPTION, stdout);
454 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
456 exit (status);
459 static void
460 translate_charset (char const *new_trans)
462 int i;
464 for (i = 0; i < 256; i++)
465 trans_table[i] = new_trans[trans_table[i]];
466 translation_needed = true;
469 /* Return true if I has more than one bit set. I must be nonnegative. */
471 static inline bool
472 multiple_bits_set (int i)
474 return (i & (i - 1)) != 0;
477 static void
478 print_stats (void)
480 char buf[2][MAX (INT_BUFSIZE_BOUND (uintmax_t), LONGEST_HUMAN_READABLE + 1)];
481 struct timespec now;
482 int human_opts =
483 (human_autoscale | human_round_to_nearest
484 | human_space_before_unit | human_SI | human_B);
485 uintmax_t start_sec = start_time.tv_sec;
486 enum { BILLION = 1000000000 };
487 double BILLIONe0 = BILLION;
488 double delta_s;
489 char const *bytes_per_second;
491 gettime (&now);
492 fprintf (stderr, _("%s+%s records in\n"),
493 umaxtostr (r_full, buf[0]), umaxtostr (r_partial, buf[1]));
494 fprintf (stderr, _("%s+%s records out\n"),
495 umaxtostr (w_full, buf[0]), umaxtostr (w_partial, buf[1]));
496 if (r_truncate > 0)
498 fprintf (stderr, "%s %s\n",
499 umaxtostr (r_truncate, buf[0]),
500 (r_truncate == 1
501 ? _("truncated record")
502 : _("truncated records")));
505 if (status_flags & STATUS_NOXFER)
506 return;
508 /* Use integer arithmetic to compute the transfer rate if possible,
509 since that makes it easy to use SI abbreviations; otherwise, fall
510 back on floating-point without abbreviations. */
512 fprintf (stderr,
513 ngettext ("%s byte (%s) copied",
514 "%s bytes (%s) copied", w_bytes == 1),
515 umaxtostr (w_bytes, buf[0]),
516 human_readable (w_bytes, buf[1], human_opts, 1, 1));
518 if ((start_time.tv_sec < now.tv_sec
519 || (start_time.tv_sec == now.tv_sec
520 && start_time.tv_nsec < now.tv_nsec))
521 && now.tv_sec - start_sec < UINTMAX_MAX / BILLION)
523 uintmax_t delta_ns = (BILLION * (now.tv_sec - start_sec)
524 + now.tv_nsec - start_time.tv_nsec);
525 delta_s = delta_ns / BILLIONe0;
526 bytes_per_second = human_readable (w_bytes, buf[1], human_opts,
527 BILLION, delta_ns);
529 else
531 delta_s = now.tv_sec;
532 delta_s -= start_time.tv_sec;
533 delta_s += (now.tv_nsec - start_time.tv_nsec) / BILLIONe0;
534 if (0 < delta_s)
535 sprintf (buf[1], "%gB", w_bytes / delta_s);
536 else
537 sprintf (buf[1], "%s B", _("Infinity"));
538 bytes_per_second = buf[1];
541 fprintf (stderr,
542 ngettext (", %g second, %s/s\n",
543 ", %g seconds, %s/s\n", delta_s == 1),
544 delta_s, bytes_per_second);
547 static void
548 cleanup (void)
550 if (close (STDIN_FILENO) < 0)
551 error (EXIT_FAILURE, errno,
552 _("closing input file %s"), quote (input_file));
553 if (close (STDOUT_FILENO) < 0)
554 error (EXIT_FAILURE, errno,
555 _("closing output file %s"), quote (output_file));
556 print_stats ();
559 static inline void
560 quit (int code)
562 cleanup ();
563 exit (code);
566 static RETSIGTYPE
567 interrupt_handler (int sig)
569 #ifdef SA_NOCLDSTOP
570 struct sigaction sigact;
572 sigact.sa_handler = SIG_DFL;
573 sigemptyset (&sigact.sa_mask);
574 sigact.sa_flags = 0;
575 sigaction (sig, &sigact, NULL);
576 #else
577 signal (sig, SIG_DFL);
578 #endif
579 cleanup ();
580 raise (sig);
583 static RETSIGTYPE
584 siginfo_handler (int sig ATTRIBUTE_UNUSED)
586 print_stats ();
589 /* Encapsulate portability mess of establishing signal handlers. */
591 static void
592 install_handler (int sig_num, RETSIGTYPE (*sig_handler) (int sig))
594 #ifdef SA_NOCLDSTOP
595 struct sigaction sigact;
596 sigaction (sig_num, NULL, &sigact);
597 if (sigact.sa_handler != SIG_IGN)
599 sigact.sa_handler = sig_handler;
600 sigemptyset (&sigact.sa_mask);
601 sigact.sa_flags = 0;
602 sigaction (sig_num, &sigact, NULL);
604 #else
605 if (signal (sig_num, SIG_IGN) != SIG_IGN)
606 signal (sig_num, sig_handler);
607 #endif
610 /* Open a file to a particular file descriptor. This is like standard
611 `open', except it always returns DESIRED_FD if successful. */
612 static int
613 open_fd (int desired_fd, char const *filename, int options, mode_t mode)
615 int fd;
616 close (desired_fd);
617 fd = open (filename, options, mode);
618 if (fd < 0)
619 return -1;
621 if (fd != desired_fd)
623 if (dup2 (fd, desired_fd) != desired_fd)
624 desired_fd = -1;
625 if (close (fd) != 0)
626 return -1;
629 return desired_fd;
632 /* Write, then empty, the output buffer `obuf'. */
634 static void
635 write_output (void)
637 size_t nwritten = full_write (STDOUT_FILENO, obuf, output_blocksize);
638 w_bytes += nwritten;
639 if (nwritten != output_blocksize)
641 error (0, errno, _("writing to %s"), quote (output_file));
642 if (nwritten != 0)
643 w_partial++;
644 quit (EXIT_FAILURE);
646 else
647 w_full++;
648 oc = 0;
651 /* Interpret one "conv=..." or similar operand STR according to the
652 symbols in TABLE, returning the flags specified. If the operand
653 cannot be parsed, use ERROR_MSGID to generate a diagnostic.
654 As a by product, this function replaces each `,' in STR with a NUL byte. */
656 static int
657 parse_symbols (char *str, struct symbol_value const *table,
658 char const *error_msgid)
660 int value = 0;
664 struct symbol_value const *entry;
665 char *new = strchr (str, ',');
666 if (new != NULL)
667 *new++ = '\0';
668 for (entry = table; ; entry++)
670 if (! entry->symbol[0])
672 error (0, 0, _(error_msgid), quote (str));
673 usage (EXIT_FAILURE);
675 if (STREQ (entry->symbol, str))
677 if (! entry->value)
678 error (EXIT_FAILURE, 0, _(error_msgid), quote (str));
679 value |= entry->value;
680 break;
683 str = new;
685 while (str);
687 return value;
690 /* Return the value of STR, interpreted as a non-negative decimal integer,
691 optionally multiplied by various values.
692 Set *INVALID if STR does not represent a number in this format. */
694 static uintmax_t
695 parse_integer (const char *str, bool *invalid)
697 uintmax_t n;
698 char *suffix;
699 enum strtol_error e = xstrtoumax (str, &suffix, 10, &n, "bcEGkKMPTwYZ0");
701 if (e == LONGINT_INVALID_SUFFIX_CHAR && *suffix == 'x')
703 uintmax_t multiplier = parse_integer (suffix + 1, invalid);
705 if (multiplier != 0 && n * multiplier / multiplier != n)
707 *invalid = true;
708 return 0;
711 n *= multiplier;
713 else if (e != LONGINT_OK)
715 *invalid = true;
716 return 0;
719 return n;
722 static void
723 scanargs (int argc, char **argv)
725 int i;
727 for (i = optind; i < argc; i++)
729 char *name, *val;
731 name = argv[i];
732 val = strchr (name, '=');
733 if (val == NULL)
735 error (0, 0, _("unrecognized operand %s"), quote (name));
736 usage (EXIT_FAILURE);
738 *val++ = '\0';
740 if (STREQ (name, "if"))
741 input_file = val;
742 else if (STREQ (name, "of"))
743 output_file = val;
744 else if (STREQ (name, "conv"))
745 conversions_mask |= parse_symbols (val, conversions,
746 N_("invalid conversion: %s"));
747 else if (STREQ (name, "iflag"))
748 input_flags |= parse_symbols (val, flags,
749 N_("invalid input flag: %s"));
750 else if (STREQ (name, "oflag"))
751 output_flags |= parse_symbols (val, flags,
752 N_("invalid output flag: %s"));
753 else if (STREQ (name, "status"))
754 status_flags |= parse_symbols (val, statuses,
755 N_("invalid status flag: %s"));
756 else
758 bool invalid = false;
759 uintmax_t n = parse_integer (val, &invalid);
761 if (STREQ (name, "ibs"))
763 invalid |= ! (0 < n && n <= MAX_BLOCKSIZE);
764 input_blocksize = n;
765 conversions_mask |= C_TWOBUFS;
767 else if (STREQ (name, "obs"))
769 invalid |= ! (0 < n && n <= MAX_BLOCKSIZE);
770 output_blocksize = n;
771 conversions_mask |= C_TWOBUFS;
773 else if (STREQ (name, "bs"))
775 invalid |= ! (0 < n && n <= MAX_BLOCKSIZE);
776 output_blocksize = input_blocksize = n;
778 else if (STREQ (name, "cbs"))
780 conversion_blocksize = n;
781 invalid |= (conversion_blocksize != n
782 || conversion_blocksize == 0);
784 else if (STREQ (name, "skip"))
785 skip_records = n;
786 else if (STREQ (name, "seek"))
787 seek_records = n;
788 else if (STREQ (name, "count"))
789 max_records = n;
790 else
792 error (0, 0, _("unrecognized operand %s=%s"),
793 quote_n (0, name), quote_n (1, val));
794 usage (EXIT_FAILURE);
797 if (invalid)
798 error (EXIT_FAILURE, 0, _("invalid number %s"), quote (val));
802 /* If bs= was given, both `input_blocksize' and `output_blocksize' will
803 have been set to positive values. If either has not been set,
804 bs= was not given, so make sure two buffers are used. */
805 if (input_blocksize == 0 || output_blocksize == 0)
806 conversions_mask |= C_TWOBUFS;
807 if (input_blocksize == 0)
808 input_blocksize = DEFAULT_BLOCKSIZE;
809 if (output_blocksize == 0)
810 output_blocksize = DEFAULT_BLOCKSIZE;
811 if (conversion_blocksize == 0)
812 conversions_mask &= ~(C_BLOCK | C_UNBLOCK);
814 if (input_flags & (O_DSYNC | O_SYNC))
815 input_flags |= O_RSYNC;
817 if (multiple_bits_set (conversions_mask & (C_ASCII | C_EBCDIC | C_IBM)))
818 error (EXIT_FAILURE, 0, _("cannot combine any two of {ascii,ebcdic,ibm}"));
819 if (multiple_bits_set (conversions_mask & (C_BLOCK | C_UNBLOCK)))
820 error (EXIT_FAILURE, 0, _("cannot combine block and unblock"));
821 if (multiple_bits_set (conversions_mask & (C_LCASE | C_UCASE)))
822 error (EXIT_FAILURE, 0, _("cannot combine lcase and ucase"));
823 if (multiple_bits_set (conversions_mask & (C_EXCL | C_NOCREAT)))
824 error (EXIT_FAILURE, 0, _("cannot combine excl and nocreat"));
827 /* Fix up translation table. */
829 static void
830 apply_translations (void)
832 int i;
834 if (conversions_mask & C_ASCII)
835 translate_charset (ebcdic_to_ascii);
837 if (conversions_mask & C_UCASE)
839 for (i = 0; i < 256; i++)
840 if (ISLOWER (trans_table[i]))
841 trans_table[i] = TOUPPER (trans_table[i]);
842 translation_needed = true;
844 else if (conversions_mask & C_LCASE)
846 for (i = 0; i < 256; i++)
847 if (ISUPPER (trans_table[i]))
848 trans_table[i] = TOLOWER (trans_table[i]);
849 translation_needed = true;
852 if (conversions_mask & C_EBCDIC)
854 translate_charset (ascii_to_ebcdic);
855 newline_character = ascii_to_ebcdic['\n'];
856 space_character = ascii_to_ebcdic[' '];
858 else if (conversions_mask & C_IBM)
860 translate_charset (ascii_to_ibm);
861 newline_character = ascii_to_ibm['\n'];
862 space_character = ascii_to_ibm[' '];
866 /* Apply the character-set translations specified by the user
867 to the NREAD bytes in BUF. */
869 static void
870 translate_buffer (char *buf, size_t nread)
872 char *cp;
873 size_t i;
875 for (i = nread, cp = buf; i; i--, cp++)
876 *cp = trans_table[to_uchar (*cp)];
879 /* If true, the last char from the previous call to `swab_buffer'
880 is saved in `saved_char'. */
881 static bool char_is_saved = false;
883 /* Odd char from previous call. */
884 static char saved_char;
886 /* Swap NREAD bytes in BUF, plus possibly an initial char from the
887 previous call. If NREAD is odd, save the last char for the
888 next call. Return the new start of the BUF buffer. */
890 static char *
891 swab_buffer (char *buf, size_t *nread)
893 char *bufstart = buf;
894 register char *cp;
895 size_t i;
897 /* Is a char left from last time? */
898 if (char_is_saved)
900 *--bufstart = saved_char;
901 (*nread)++;
902 char_is_saved = false;
905 if (*nread & 1)
907 /* An odd number of chars are in the buffer. */
908 saved_char = bufstart[--*nread];
909 char_is_saved = true;
912 /* Do the byte-swapping by moving every second character two
913 positions toward the end, working from the end of the buffer
914 toward the beginning. This way we only move half of the data. */
916 cp = bufstart + *nread; /* Start one char past the last. */
917 for (i = *nread / 2; i; i--, cp -= 2)
918 *cp = *(cp - 2);
920 return ++bufstart;
923 /* Add OFFSET to the input offset, setting the overflow flag if
924 necessary. */
926 static void
927 advance_input_offset (uintmax_t offset)
929 input_offset += offset;
930 if (input_offset < offset)
931 input_offset_overflow = true;
934 /* This is a wrapper for lseek. It detects and warns about a kernel
935 bug that makes lseek a no-op for tape devices, even though the kernel
936 lseek return value suggests that the function succeeded.
938 The parameters are the same as those of the lseek function, but
939 with the addition of FILENAME, the name of the file associated with
940 descriptor FDESC. The file name is used solely in the warning that's
941 printed when the bug is detected. Return the same value that lseek
942 would have returned, but when the lseek bug is detected, return -1
943 to indicate that lseek failed.
945 The offending behavior has been confirmed with an Exabyte SCSI tape
946 drive accessed via /dev/nst0 on both Linux-2.2.17 and Linux-2.4.16. */
948 #ifdef __linux__
950 # include <sys/mtio.h>
952 # define MT_SAME_POSITION(P, Q) \
953 ((P).mt_resid == (Q).mt_resid \
954 && (P).mt_fileno == (Q).mt_fileno \
955 && (P).mt_blkno == (Q).mt_blkno)
957 static off_t
958 skip_via_lseek (char const *filename, int fdesc, off_t offset, int whence)
960 struct mtget s1;
961 struct mtget s2;
962 bool got_original_tape_position = (ioctl (fdesc, MTIOCGET, &s1) == 0);
963 /* known bad device type */
964 /* && s.mt_type == MT_ISSCSI2 */
966 off_t new_position = lseek (fdesc, offset, whence);
967 if (0 <= new_position
968 && got_original_tape_position
969 && ioctl (fdesc, MTIOCGET, &s2) == 0
970 && MT_SAME_POSITION (s1, s2))
972 error (0, 0, _("warning: working around lseek kernel bug for file (%s)\n\
973 of mt_type=0x%0lx -- see <sys/mtio.h> for the list of types"),
974 filename, s2.mt_type);
975 errno = 0;
976 new_position = -1;
979 return new_position;
981 #else
982 # define skip_via_lseek(Filename, Fd, Offset, Whence) lseek (Fd, Offset, Whence)
983 #endif
985 /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
986 which is open with read permission for FILE. Store up to BLOCKSIZE
987 bytes of the data at a time in BUF, if necessary. RECORDS must be
988 nonzero. If fdesc is STDIN_FILENO, advance the input offset. */
990 static void
991 skip (int fdesc, char const *file, uintmax_t records, size_t blocksize,
992 char *buf)
994 off_t offset = records * blocksize;
996 /* Try lseek and if an error indicates it was an inappropriate operation --
997 or if the the file offset is not representable as an off_t --
998 fall back on using read. */
1000 errno = 0;
1001 if ((uintmax_t) offset / blocksize == records
1002 && 0 <= skip_via_lseek (file, fdesc, offset, SEEK_CUR))
1004 if (fdesc == STDIN_FILENO)
1005 advance_input_offset (offset);
1007 else
1009 int lseek_errno = errno;
1010 while (records--)
1012 size_t nread = safe_read (fdesc, buf, blocksize);
1013 if (nread == SAFE_READ_ERROR)
1015 if (fdesc == STDIN_FILENO)
1017 error (0, errno, _("reading %s"), quote (file));
1018 if (conversions_mask & C_NOERROR)
1020 print_stats ();
1021 continue;
1024 else
1025 error (0, lseek_errno, _("%s: cannot seek"), quote (file));
1026 quit (EXIT_FAILURE);
1028 /* POSIX doesn't say what to do when dd detects it has been
1029 asked to skip past EOF, so I assume it's non-fatal.
1030 FIXME: maybe give a warning. */
1031 if (nread == 0)
1032 break;
1033 if (fdesc == STDIN_FILENO)
1034 advance_input_offset (nread);
1039 /* Advance the input by NBYTES if possible, after a read error.
1040 The input file offset may or may not have advanced after the failed
1041 read; adjust it to point just after the bad record regardless.
1042 Return true if successful, or if the input is already known to not
1043 be seekable. */
1045 static bool
1046 advance_input_after_read_error (size_t nbytes)
1048 if (! input_seekable)
1050 if (input_seek_errno == ESPIPE)
1051 return true;
1052 errno = input_seek_errno;
1054 else
1056 off_t offset;
1057 advance_input_offset (nbytes);
1058 input_offset_overflow |= (OFF_T_MAX < input_offset);
1059 if (input_offset_overflow)
1061 error (0, 0, _("offset overflow while reading file %s"),
1062 quote (input_file));
1063 return false;
1065 offset = lseek (STDIN_FILENO, 0, SEEK_CUR);
1066 if (0 <= offset)
1068 off_t diff;
1069 if (offset == input_offset)
1070 return true;
1071 diff = input_offset - offset;
1072 if (! (0 <= diff && diff <= nbytes))
1073 error (0, 0, _("warning: screwy file offset after failed read"));
1074 if (0 <= skip_via_lseek (input_file, STDIN_FILENO, diff, SEEK_CUR))
1075 return true;
1076 if (errno == 0)
1077 error (0, 0, _("cannot work around kernel bug after all"));
1081 error (0, errno, _("%s: cannot seek"), quote (input_file));
1082 return false;
1085 /* Copy NREAD bytes of BUF, with no conversions. */
1087 static void
1088 copy_simple (char const *buf, size_t nread)
1090 const char *start = buf; /* First uncopied char in BUF. */
1094 size_t nfree = MIN (nread, output_blocksize - oc);
1096 memcpy (obuf + oc, start, nfree);
1098 nread -= nfree; /* Update the number of bytes left to copy. */
1099 start += nfree;
1100 oc += nfree;
1101 if (oc >= output_blocksize)
1102 write_output ();
1104 while (nread != 0);
1107 /* Copy NREAD bytes of BUF, doing conv=block
1108 (pad newline-terminated records to `conversion_blocksize',
1109 replacing the newline with trailing spaces). */
1111 static void
1112 copy_with_block (char const *buf, size_t nread)
1114 size_t i;
1116 for (i = nread; i; i--, buf++)
1118 if (*buf == newline_character)
1120 if (col < conversion_blocksize)
1122 size_t j;
1123 for (j = col; j < conversion_blocksize; j++)
1124 output_char (space_character);
1126 col = 0;
1128 else
1130 if (col == conversion_blocksize)
1131 r_truncate++;
1132 else if (col < conversion_blocksize)
1133 output_char (*buf);
1134 col++;
1139 /* Copy NREAD bytes of BUF, doing conv=unblock
1140 (replace trailing spaces in `conversion_blocksize'-sized records
1141 with a newline). */
1143 static void
1144 copy_with_unblock (char const *buf, size_t nread)
1146 size_t i;
1147 char c;
1148 static size_t pending_spaces = 0;
1150 for (i = 0; i < nread; i++)
1152 c = buf[i];
1154 if (col++ >= conversion_blocksize)
1156 col = pending_spaces = 0; /* Wipe out any pending spaces. */
1157 i--; /* Push the char back; get it later. */
1158 output_char (newline_character);
1160 else if (c == space_character)
1161 pending_spaces++;
1162 else
1164 /* `c' is the character after a run of spaces that were not
1165 at the end of the conversion buffer. Output them. */
1166 while (pending_spaces)
1168 output_char (space_character);
1169 --pending_spaces;
1171 output_char (c);
1176 /* Set the file descriptor flags for FD that correspond to the nonzero bits
1177 in ADD_FLAGS. The file's name is NAME. */
1179 static void
1180 set_fd_flags (int fd, int add_flags, char const *name)
1182 if (add_flags)
1184 int old_flags = fcntl (fd, F_GETFL);
1185 int new_flags = old_flags | add_flags;
1186 if (old_flags < 0
1187 || (new_flags != old_flags && fcntl (fd, F_SETFL, new_flags) == -1))
1188 error (EXIT_FAILURE, errno, _("setting flags for %s"), quote (name));
1192 /* The main loop. */
1194 static int
1195 dd_copy (void)
1197 char *ibuf, *bufstart; /* Input buffer. */
1198 char *real_buf; /* real buffer address before alignment */
1199 char *real_obuf;
1200 size_t nread; /* Bytes read in the current block. */
1202 /* If nonzero, then the previously read block was partial and
1203 PARTREAD was its size. */
1204 size_t partread = 0;
1206 int exit_status = EXIT_SUCCESS;
1207 size_t page_size = getpagesize ();
1208 size_t n_bytes_read;
1210 /* Leave at least one extra byte at the beginning and end of `ibuf'
1211 for conv=swab, but keep the buffer address even. But some peculiar
1212 device drivers work only with word-aligned buffers, so leave an
1213 extra two bytes. */
1215 /* Some devices require alignment on a sector or page boundary
1216 (e.g. character disk devices). Align the input buffer to a
1217 page boundary to cover all bases. Note that due to the swab
1218 algorithm, we must have at least one byte in the page before
1219 the input buffer; thus we allocate 2 pages of slop in the
1220 real buffer. 8k above the blocksize shouldn't bother anyone.
1222 The page alignment is necessary on any linux system that supports
1223 either the SGI raw I/O patch or Steven Tweedies raw I/O patch.
1224 It is necessary when accessing raw (i.e. character special) disk
1225 devices on Unixware or other SVR4-derived system. */
1227 real_buf = xmalloc (input_blocksize
1228 + 2 * SWAB_ALIGN_OFFSET
1229 + 2 * page_size - 1);
1230 ibuf = real_buf;
1231 ibuf += SWAB_ALIGN_OFFSET; /* allow space for swab */
1233 ibuf = ptr_align (ibuf, page_size);
1235 if (conversions_mask & C_TWOBUFS)
1237 /* Page-align the output buffer, too. */
1238 real_obuf = xmalloc (output_blocksize + page_size - 1);
1239 obuf = ptr_align (real_obuf, page_size);
1241 else
1243 real_obuf = NULL;
1244 obuf = ibuf;
1247 if (skip_records != 0)
1248 skip (STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf);
1250 if (seek_records != 0)
1251 skip (STDOUT_FILENO, output_file, seek_records, output_blocksize, obuf);
1253 if (max_records == 0)
1254 return exit_status;
1256 while (1)
1258 if (r_partial + r_full >= max_records)
1259 break;
1261 /* Zero the buffer before reading, so that if we get a read error,
1262 whatever data we are able to read is followed by zeros.
1263 This minimizes data loss. */
1264 if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
1265 memset (ibuf,
1266 (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
1267 input_blocksize);
1269 nread = safe_read (STDIN_FILENO, ibuf, input_blocksize);
1271 if (nread == 0)
1272 break; /* EOF. */
1274 if (nread == SAFE_READ_ERROR)
1276 error (0, errno, _("reading %s"), quote (input_file));
1277 if (conversions_mask & C_NOERROR)
1279 print_stats ();
1280 /* Seek past the bad block if possible. */
1281 if (!advance_input_after_read_error (input_blocksize - partread))
1283 exit_status = EXIT_FAILURE;
1285 /* Suppress duplicate diagnostics. */
1286 input_seekable = false;
1287 input_seek_errno = ESPIPE;
1289 if ((conversions_mask & C_SYNC) && !partread)
1290 /* Replace the missing input with null bytes and
1291 proceed normally. */
1292 nread = 0;
1293 else
1294 continue;
1296 else
1298 /* Write any partial block. */
1299 exit_status = EXIT_FAILURE;
1300 break;
1304 n_bytes_read = nread;
1305 advance_input_offset (nread);
1307 if (n_bytes_read < input_blocksize)
1309 r_partial++;
1310 partread = n_bytes_read;
1311 if (conversions_mask & C_SYNC)
1313 if (!(conversions_mask & C_NOERROR))
1314 /* If C_NOERROR, we zeroed the block before reading. */
1315 memset (ibuf + n_bytes_read,
1316 (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
1317 input_blocksize - n_bytes_read);
1318 n_bytes_read = input_blocksize;
1321 else
1323 r_full++;
1324 partread = 0;
1327 if (ibuf == obuf) /* If not C_TWOBUFS. */
1329 size_t nwritten = full_write (STDOUT_FILENO, obuf, n_bytes_read);
1330 w_bytes += nwritten;
1331 if (nwritten != n_bytes_read)
1333 error (0, errno, _("writing %s"), quote (output_file));
1334 return EXIT_FAILURE;
1336 else if (n_bytes_read == input_blocksize)
1337 w_full++;
1338 else
1339 w_partial++;
1340 continue;
1343 /* Do any translations on the whole buffer at once. */
1345 if (translation_needed)
1346 translate_buffer (ibuf, n_bytes_read);
1348 if (conversions_mask & C_SWAB)
1349 bufstart = swab_buffer (ibuf, &n_bytes_read);
1350 else
1351 bufstart = ibuf;
1353 if (conversions_mask & C_BLOCK)
1354 copy_with_block (bufstart, n_bytes_read);
1355 else if (conversions_mask & C_UNBLOCK)
1356 copy_with_unblock (bufstart, n_bytes_read);
1357 else
1358 copy_simple (bufstart, n_bytes_read);
1361 /* If we have a char left as a result of conv=swab, output it. */
1362 if (char_is_saved)
1364 if (conversions_mask & C_BLOCK)
1365 copy_with_block (&saved_char, 1);
1366 else if (conversions_mask & C_UNBLOCK)
1367 copy_with_unblock (&saved_char, 1);
1368 else
1369 output_char (saved_char);
1372 if ((conversions_mask & C_BLOCK) && col > 0)
1374 /* If the final input line didn't end with a '\n', pad
1375 the output block to `conversion_blocksize' chars. */
1376 size_t i;
1377 for (i = col; i < conversion_blocksize; i++)
1378 output_char (space_character);
1381 if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
1382 /* Add a final '\n' if there are exactly `conversion_blocksize'
1383 characters in the final record. */
1384 output_char (newline_character);
1386 /* Write out the last block. */
1387 if (oc != 0)
1389 size_t nwritten = full_write (STDOUT_FILENO, obuf, oc);
1390 w_bytes += nwritten;
1391 if (nwritten != 0)
1392 w_partial++;
1393 if (nwritten != oc)
1395 error (0, errno, _("writing %s"), quote (output_file));
1396 return EXIT_FAILURE;
1400 free (real_buf);
1401 if (real_obuf)
1402 free (real_obuf);
1404 if ((conversions_mask & C_FDATASYNC) && fdatasync (STDOUT_FILENO) != 0)
1406 if (errno != ENOSYS && errno != EINVAL)
1408 error (0, errno, _("fdatasync failed for %s"), quote (output_file));
1409 exit_status = EXIT_FAILURE;
1411 conversions_mask |= C_FSYNC;
1414 if (conversions_mask & C_FSYNC)
1415 while (fsync (STDOUT_FILENO) != 0)
1416 if (errno != EINTR)
1418 error (0, errno, _("fsync failed for %s"), quote (output_file));
1419 return EXIT_FAILURE;
1422 return exit_status;
1425 /* This is gross, but necessary, because of the way close_stdout
1426 works and because this program closes STDOUT_FILENO directly. */
1427 static void (*closeout_func) (void) = close_stdout;
1429 static void
1430 close_stdout_wrapper (void)
1432 if (closeout_func)
1433 (*closeout_func) ();
1437 main (int argc, char **argv)
1439 int i;
1440 int exit_status;
1441 off_t offset;
1443 initialize_main (&argc, &argv);
1444 program_name = argv[0];
1445 setlocale (LC_ALL, "");
1446 bindtextdomain (PACKAGE, LOCALEDIR);
1447 textdomain (PACKAGE);
1449 /* Arrange to close stdout if parse_long_options exits. */
1450 atexit (close_stdout_wrapper);
1452 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
1453 usage, AUTHORS, (char const *) NULL);
1454 if (getopt_long (argc, argv, "", NULL, NULL) != -1)
1455 usage (EXIT_FAILURE);
1457 /* Don't close stdout on exit from here on. */
1458 closeout_func = NULL;
1460 /* Initialize translation table to identity translation. */
1461 for (i = 0; i < 256; i++)
1462 trans_table[i] = i;
1464 /* Decode arguments. */
1465 scanargs (argc, argv);
1467 apply_translations ();
1469 if (input_file == NULL)
1471 input_file = _("standard input");
1472 set_fd_flags (STDIN_FILENO, input_flags, input_file);
1474 else
1476 if (open_fd (STDIN_FILENO, input_file, O_RDONLY | input_flags, 0) < 0)
1477 error (EXIT_FAILURE, errno, _("opening %s"), quote (input_file));
1480 offset = lseek (STDIN_FILENO, 0, SEEK_CUR);
1481 input_seekable = (0 <= offset);
1482 input_offset = offset;
1483 input_seek_errno = errno;
1485 if (output_file == NULL)
1487 output_file = _("standard output");
1488 set_fd_flags (STDOUT_FILENO, output_flags, output_file);
1490 else
1492 mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1493 int opts
1494 = (output_flags
1495 | (conversions_mask & C_NOCREAT ? 0 : O_CREAT)
1496 | (conversions_mask & C_EXCL ? O_EXCL : 0)
1497 | (seek_records || (conversions_mask & C_NOTRUNC) ? 0 : O_TRUNC));
1499 /* Open the output file with *read* access only if we might
1500 need to read to satisfy a `seek=' request. If we can't read
1501 the file, go ahead with write-only access; it might work. */
1502 if ((! seek_records
1503 || open_fd (STDOUT_FILENO, output_file, O_RDWR | opts, perms) < 0)
1504 && open_fd (STDOUT_FILENO, output_file, O_WRONLY | opts, perms) < 0)
1505 error (EXIT_FAILURE, errno, _("opening %s"), quote (output_file));
1507 #if HAVE_FTRUNCATE
1508 if (seek_records != 0 && !(conversions_mask & C_NOTRUNC))
1510 struct stat stdout_stat;
1511 off_t o = seek_records * output_blocksize;
1512 if ((uintmax_t) o / output_blocksize != seek_records)
1513 error (EXIT_FAILURE, 0, _("file offset out of range"));
1515 if (fstat (STDOUT_FILENO, &stdout_stat) != 0)
1516 error (EXIT_FAILURE, errno, _("cannot fstat %s"),
1517 quote (output_file));
1519 /* Complain only when ftruncate fails on a regular file, a
1520 directory, or a shared memory object, as
1521 POSIX 1003.1-2004 specifies ftruncate's behavior only for these
1522 file types. For example, do not complain when Linux 2.4
1523 ftruncate fails on /dev/fd0. */
1524 if (ftruncate (STDOUT_FILENO, o) != 0
1525 && (S_ISREG (stdout_stat.st_mode)
1526 || S_ISDIR (stdout_stat.st_mode)
1527 || S_TYPEISSHM (&stdout_stat)))
1529 char buf[INT_BUFSIZE_BOUND (off_t)];
1530 error (EXIT_FAILURE, errno,
1531 _("advancing past %s bytes in output file %s"),
1532 offtostr (o, buf), quote (output_file));
1535 #endif
1538 install_handler (SIGINT, interrupt_handler);
1539 install_handler (SIGQUIT, interrupt_handler);
1540 install_handler (SIGPIPE, interrupt_handler);
1541 install_handler (SIGINFO, siginfo_handler);
1543 gettime (&start_time);
1545 exit_status = dd_copy ();
1547 quit (exit_status);