(dd_copy): Mark two diagnostics for translations.
[platform/upstream/coreutils.git] / src / dd.c
1 /* dd -- convert a file while copying it.
2    Copyright (C) 85, 90, 91, 1995-2004 Free Software Foundation, Inc.
3
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.
8
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.
13
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.  */
17
18 /* Written by Paul Rubin, David MacKenzie, and Stuart Kemp. */
19
20 #include <config.h>
21 #include <stdio.h>
22
23 #define SWAB_ALIGN_OFFSET 2
24
25 #include <sys/types.h>
26 #include <signal.h>
27 #include <getopt.h>
28
29 #include "system.h"
30 #include "error.h"
31 #include "full-write.h"
32 #include "getpagesize.h"
33 #include "inttostr.h"
34 #include "long-options.h"
35 #include "quote.h"
36 #include "safe-read.h"
37 #include "xstrtol.h"
38
39 /* The official name of this program (e.g., no `g' prefix).  */
40 #define PROGRAM_NAME "dd"
41
42 #define AUTHORS "Paul Rubin", "David MacKenzie", "Stuart Kemp"
43
44 #ifndef SIGINFO
45 # define SIGINFO SIGUSR1
46 #endif
47
48 #ifndef S_TYPEISSHM
49 # define S_TYPEISSHM(Stat_ptr) 0
50 #endif
51
52 #if ! HAVE_FDATASYNC
53 # define fdatasync(fd) (errno = ENOSYS, -1)
54 #endif
55
56 #define ROUND_UP_OFFSET(X, M) ((M) - 1 - (((X) + (M) - 1) % (M)))
57 #define PTR_ALIGN(Ptr, M) ((Ptr) \
58                            + ROUND_UP_OFFSET ((char *)(Ptr) - (char *)0, (M)))
59
60 #define max(a, b) ((a) > (b) ? (a) : (b))
61 #define output_char(c)                          \
62   do                                            \
63     {                                           \
64       obuf[oc++] = (c);                         \
65       if (oc >= output_blocksize)               \
66         write_output ();                        \
67     }                                           \
68   while (0)
69
70 /* Default input and output blocksize. */
71 #define DEFAULT_BLOCKSIZE 512
72
73 /* Conversions bit masks. */
74 #define C_ASCII 01
75 #define C_EBCDIC 02
76 #define C_IBM 04
77 #define C_BLOCK 010
78 #define C_UNBLOCK 020
79 #define C_LCASE 040
80 #define C_UCASE 0100
81 #define C_SWAB 0200
82 #define C_NOERROR 0400
83 #define C_NOTRUNC 01000
84 #define C_SYNC 02000
85 /* Use separate input and output buffers, and combine partial input blocks. */
86 #define C_TWOBUFS 04000
87 #define C_NOCREAT 010000
88 #define C_EXCL 020000
89 #define C_FDATASYNC 040000
90 #define C_FSYNC 0100000
91
92 /* The name this program was run with. */
93 char *program_name;
94
95 /* The name of the input file, or NULL for the standard input. */
96 static char const *input_file = NULL;
97
98 /* The name of the output file, or NULL for the standard output. */
99 static char const *output_file = NULL;
100
101 /* The number of bytes in which atomic reads are done. */
102 static size_t input_blocksize = 0;
103
104 /* The number of bytes in which atomic writes are done. */
105 static size_t output_blocksize = 0;
106
107 /* Conversion buffer size, in bytes.  0 prevents conversions. */
108 static size_t conversion_blocksize = 0;
109
110 /* Skip this many records of `input_blocksize' bytes before input. */
111 static uintmax_t skip_records = 0;
112
113 /* Skip this many records of `output_blocksize' bytes before output. */
114 static uintmax_t seek_records = 0;
115
116 /* Copy only this many records.  The default is effectively infinity.  */
117 static uintmax_t max_records = (uintmax_t) -1;
118
119 /* Bit vector of conversions to apply. */
120 static int conversions_mask = 0;
121
122 /* Open flags for the input and output files.  */
123 static int input_flags = 0;
124 static int output_flags = 0;
125
126 /* If nonzero, filter characters through the translation table.  */
127 static int translation_needed = 0;
128
129 /* Number of partial blocks written. */
130 static uintmax_t w_partial = 0;
131
132 /* Number of full blocks written. */
133 static uintmax_t w_full = 0;
134
135 /* Number of partial blocks read. */
136 static uintmax_t r_partial = 0;
137
138 /* Number of full blocks read. */
139 static uintmax_t r_full = 0;
140
141 /* Records truncated by conv=block. */
142 static uintmax_t r_truncate = 0;
143
144 /* Output representation of newline and space characters.
145    They change if we're converting to EBCDIC.  */
146 static char newline_character = '\n';
147 static char space_character = ' ';
148
149 /* Output buffer. */
150 static char *obuf;
151
152 /* Current index into `obuf'. */
153 static size_t oc = 0;
154
155 /* Index into current line, for `conv=block' and `conv=unblock'.  */
156 static size_t col = 0;
157
158 /* A longest symbol in the struct symbol_values tables below.  */
159 #define LONGEST_SYMBOL "fdatasync"
160
161 /* A symbol and the corresponding integer value.  */
162 struct symbol_value
163 {
164   char symbol[sizeof LONGEST_SYMBOL];
165   int value;
166 };
167
168 /* Conversion symbols, for conv="...".  */
169 static struct symbol_value const conversions[] =
170 {
171   {"ascii", C_ASCII | C_TWOBUFS},       /* EBCDIC to ASCII. */
172   {"ebcdic", C_EBCDIC | C_TWOBUFS},     /* ASCII to EBCDIC. */
173   {"ibm", C_IBM | C_TWOBUFS},   /* Slightly different ASCII to EBCDIC. */
174   {"block", C_BLOCK | C_TWOBUFS},       /* Variable to fixed length records. */
175   {"unblock", C_UNBLOCK | C_TWOBUFS},   /* Fixed to variable length records. */
176   {"lcase", C_LCASE | C_TWOBUFS},       /* Translate upper to lower case. */
177   {"ucase", C_UCASE | C_TWOBUFS},       /* Translate lower to upper case. */
178   {"swab", C_SWAB | C_TWOBUFS}, /* Swap bytes of input. */
179   {"noerror", C_NOERROR},       /* Ignore i/o errors. */
180   {"nocreat", C_NOCREAT},       /* Do not create output file.  */
181   {"excl", C_EXCL},             /* Fail if the output file already exists.  */
182   {"notrunc", C_NOTRUNC},       /* Do not truncate output file. */
183   {"sync", C_SYNC},             /* Pad input records to ibs with NULs. */
184   {"fdatasync", C_FDATASYNC},   /* Synchronize output data before finishing.  */
185   {"fsync", C_FSYNC},           /* Also synchronize output metadata.  */
186   {"", 0}
187 };
188
189 /* Flags, for iflag="..." and oflag="...".  */
190 static struct symbol_value const flags[] =
191 {
192   {"append",    O_APPEND},
193   {"direct",    O_DIRECT},
194   {"dsync",     O_DSYNC},
195   {"noctty",    O_NOCTTY},
196   {"nofollow",  O_NOFOLLOW},
197   {"nonblock",  O_NONBLOCK},
198   {"sync",      O_SYNC},
199   {"",          0}
200 };
201
202 /* Translation table formed by applying successive transformations. */
203 static unsigned char trans_table[256];
204
205 static char const ascii_to_ebcdic[] =
206 {
207   '\000', '\001', '\002', '\003', '\067', '\055', '\056', '\057',
208   '\026', '\005', '\045', '\013', '\014', '\015', '\016', '\017',
209   '\020', '\021', '\022', '\023', '\074', '\075', '\062', '\046',
210   '\030', '\031', '\077', '\047', '\034', '\035', '\036', '\037',
211   '\100', '\117', '\177', '\173', '\133', '\154', '\120', '\175',
212   '\115', '\135', '\134', '\116', '\153', '\140', '\113', '\141',
213   '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
214   '\370', '\371', '\172', '\136', '\114', '\176', '\156', '\157',
215   '\174', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
216   '\310', '\311', '\321', '\322', '\323', '\324', '\325', '\326',
217   '\327', '\330', '\331', '\342', '\343', '\344', '\345', '\346',
218   '\347', '\350', '\351', '\112', '\340', '\132', '\137', '\155',
219   '\171', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
220   '\210', '\211', '\221', '\222', '\223', '\224', '\225', '\226',
221   '\227', '\230', '\231', '\242', '\243', '\244', '\245', '\246',
222   '\247', '\250', '\251', '\300', '\152', '\320', '\241', '\007',
223   '\040', '\041', '\042', '\043', '\044', '\025', '\006', '\027',
224   '\050', '\051', '\052', '\053', '\054', '\011', '\012', '\033',
225   '\060', '\061', '\032', '\063', '\064', '\065', '\066', '\010',
226   '\070', '\071', '\072', '\073', '\004', '\024', '\076', '\341',
227   '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110',
228   '\111', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
229   '\130', '\131', '\142', '\143', '\144', '\145', '\146', '\147',
230   '\150', '\151', '\160', '\161', '\162', '\163', '\164', '\165',
231   '\166', '\167', '\170', '\200', '\212', '\213', '\214', '\215',
232   '\216', '\217', '\220', '\232', '\233', '\234', '\235', '\236',
233   '\237', '\240', '\252', '\253', '\254', '\255', '\256', '\257',
234   '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
235   '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
236   '\312', '\313', '\314', '\315', '\316', '\317', '\332', '\333',
237   '\334', '\335', '\336', '\337', '\352', '\353', '\354', '\355',
238   '\356', '\357', '\372', '\373', '\374', '\375', '\376', '\377'
239 };
240
241 static char const ascii_to_ibm[] =
242 {
243   '\000', '\001', '\002', '\003', '\067', '\055', '\056', '\057',
244   '\026', '\005', '\045', '\013', '\014', '\015', '\016', '\017',
245   '\020', '\021', '\022', '\023', '\074', '\075', '\062', '\046',
246   '\030', '\031', '\077', '\047', '\034', '\035', '\036', '\037',
247   '\100', '\132', '\177', '\173', '\133', '\154', '\120', '\175',
248   '\115', '\135', '\134', '\116', '\153', '\140', '\113', '\141',
249   '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
250   '\370', '\371', '\172', '\136', '\114', '\176', '\156', '\157',
251   '\174', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
252   '\310', '\311', '\321', '\322', '\323', '\324', '\325', '\326',
253   '\327', '\330', '\331', '\342', '\343', '\344', '\345', '\346',
254   '\347', '\350', '\351', '\255', '\340', '\275', '\137', '\155',
255   '\171', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
256   '\210', '\211', '\221', '\222', '\223', '\224', '\225', '\226',
257   '\227', '\230', '\231', '\242', '\243', '\244', '\245', '\246',
258   '\247', '\250', '\251', '\300', '\117', '\320', '\241', '\007',
259   '\040', '\041', '\042', '\043', '\044', '\025', '\006', '\027',
260   '\050', '\051', '\052', '\053', '\054', '\011', '\012', '\033',
261   '\060', '\061', '\032', '\063', '\064', '\065', '\066', '\010',
262   '\070', '\071', '\072', '\073', '\004', '\024', '\076', '\341',
263   '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110',
264   '\111', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
265   '\130', '\131', '\142', '\143', '\144', '\145', '\146', '\147',
266   '\150', '\151', '\160', '\161', '\162', '\163', '\164', '\165',
267   '\166', '\167', '\170', '\200', '\212', '\213', '\214', '\215',
268   '\216', '\217', '\220', '\232', '\233', '\234', '\235', '\236',
269   '\237', '\240', '\252', '\253', '\254', '\255', '\256', '\257',
270   '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
271   '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
272   '\312', '\313', '\314', '\315', '\316', '\317', '\332', '\333',
273   '\334', '\335', '\336', '\337', '\352', '\353', '\354', '\355',
274   '\356', '\357', '\372', '\373', '\374', '\375', '\376', '\377'
275 };
276
277 static char const ebcdic_to_ascii[] =
278 {
279   '\000', '\001', '\002', '\003', '\234', '\011', '\206', '\177',
280   '\227', '\215', '\216', '\013', '\014', '\015', '\016', '\017',
281   '\020', '\021', '\022', '\023', '\235', '\205', '\010', '\207',
282   '\030', '\031', '\222', '\217', '\034', '\035', '\036', '\037',
283   '\200', '\201', '\202', '\203', '\204', '\012', '\027', '\033',
284   '\210', '\211', '\212', '\213', '\214', '\005', '\006', '\007',
285   '\220', '\221', '\026', '\223', '\224', '\225', '\226', '\004',
286   '\230', '\231', '\232', '\233', '\024', '\025', '\236', '\032',
287   '\040', '\240', '\241', '\242', '\243', '\244', '\245', '\246',
288   '\247', '\250', '\133', '\056', '\074', '\050', '\053', '\041',
289   '\046', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
290   '\260', '\261', '\135', '\044', '\052', '\051', '\073', '\136',
291   '\055', '\057', '\262', '\263', '\264', '\265', '\266', '\267',
292   '\270', '\271', '\174', '\054', '\045', '\137', '\076', '\077',
293   '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301',
294   '\302', '\140', '\072', '\043', '\100', '\047', '\075', '\042',
295   '\303', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
296   '\150', '\151', '\304', '\305', '\306', '\307', '\310', '\311',
297   '\312', '\152', '\153', '\154', '\155', '\156', '\157', '\160',
298   '\161', '\162', '\313', '\314', '\315', '\316', '\317', '\320',
299   '\321', '\176', '\163', '\164', '\165', '\166', '\167', '\170',
300   '\171', '\172', '\322', '\323', '\324', '\325', '\326', '\327',
301   '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
302   '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
303   '\173', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
304   '\110', '\111', '\350', '\351', '\352', '\353', '\354', '\355',
305   '\175', '\112', '\113', '\114', '\115', '\116', '\117', '\120',
306   '\121', '\122', '\356', '\357', '\360', '\361', '\362', '\363',
307   '\134', '\237', '\123', '\124', '\125', '\126', '\127', '\130',
308   '\131', '\132', '\364', '\365', '\366', '\367', '\370', '\371',
309   '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
310   '\070', '\071', '\372', '\373', '\374', '\375', '\376', '\377'
311 };
312
313 void
314 usage (int status)
315 {
316   if (status != EXIT_SUCCESS)
317     fprintf (stderr, _("Try `%s --help' for more information.\n"),
318              program_name);
319   else
320     {
321       printf (_("Usage: %s [OPTION]...\n"), program_name);
322       fputs (_("\
323 Copy a file, converting and formatting according to the options.\n\
324 \n\
325   bs=BYTES        force ibs=BYTES and obs=BYTES\n\
326   cbs=BYTES       convert BYTES bytes at a time\n\
327   conv=CONVS      convert the file as per the comma separated symbol list\n\
328   count=BLOCKS    copy only BLOCKS input blocks\n\
329   ibs=BYTES       read BYTES bytes at a time\n\
330 "), stdout);
331       fputs (_("\
332   if=FILE         read from FILE instead of stdin\n\
333   iflag=FLAGS     read as per the comma separated symbol list\n\
334   obs=BYTES       write BYTES bytes at a time\n\
335   of=FILE         write to FILE instead of stdout\n\
336   oflag=FLAGS     write as per the comma separated symbol list\n\
337   seek=BLOCKS     skip BLOCKS obs-sized blocks at start of output\n\
338   skip=BLOCKS     skip BLOCKS ibs-sized blocks at start of input\n\
339 "), stdout);
340       fputs (HELP_OPTION_DESCRIPTION, stdout);
341       fputs (VERSION_OPTION_DESCRIPTION, stdout);
342       fputs (_("\
343 \n\
344 BLOCKS and BYTES may be followed by the following multiplicative suffixes:\n\
345 xM M, c 1, w 2, b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\
346 GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\
347 \n\
348 Each CONV symbol may be:\n\
349 \n\
350 "), stdout);
351       fputs (_("\
352   ascii     from EBCDIC to ASCII\n\
353   ebcdic    from ASCII to EBCDIC\n\
354   ibm       from ASCII to alternated EBCDIC\n\
355   block     pad newline-terminated records with spaces to cbs-size\n\
356   unblock   replace trailing spaces in cbs-size records with newline\n\
357   lcase     change upper case to lower case\n\
358 "), stdout);
359       fputs (_("\
360   nocreat   do not create the output file\n\
361   excl      fail if the output file already exists\n\
362   notrunc   do not truncate the output file\n\
363   ucase     change lower case to upper case\n\
364   swab      swap every pair of input bytes\n\
365   noerror   continue after read errors\n\
366   sync      pad every input block with NULs to ibs-size; when used\n\
367               with block or unblock, pad with spaces rather than NULs\n\
368   fdatasync physically write output file data before finishing\n\
369   fsync     likewise, but also write metadata\n\
370 "), stdout);
371       fputs (_("\
372 \n\
373 Each FLAG symbol may be:\n\
374 \n\
375   append    append mode (makes sense only for output)\n\
376 "), stdout);
377       if (O_DIRECT)
378         fputs (_("  direct    use direct I/O for data\n"), stdout);
379       if (O_DSYNC)
380         fputs (_("  dsync     use synchronized I/O for data\n"), stdout);
381       if (O_SYNC)
382         fputs (_("  sync      likewise, but also for metadata\n"), stdout);
383       if (O_NONBLOCK)
384         fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
385       if (O_NOFOLLOW)
386         fputs (_("  nofollow  do not follow symlinks\n"), stdout);
387       if (O_NOCTTY)
388         fputs (_("  noctty    do not assign controlling terminal from file\n"),
389                stdout);
390       fputs (_("\
391 \n\
392 Note that sending a SIGUSR1 signal to a running `dd' process makes it\n\
393 print to standard error the number of records read and written so far,\n\
394 then to resume copying.\n\
395 \n\
396   $ dd if=/dev/zero of=/dev/null& pid=$!\n\
397   $ kill -USR1 $pid; sleep 1; kill $pid\n\
398   10899206+0 records in\n\
399   10899206+0 records out\n\
400 "), stdout);
401       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
402     }
403   exit (status);
404 }
405
406 static void
407 translate_charset (char const *new_trans)
408 {
409   int i;
410
411   for (i = 0; i < 256; i++)
412     trans_table[i] = new_trans[trans_table[i]];
413   translation_needed = 1;
414 }
415
416 /* Return the number of 1 bits in `i'. */
417
418 static int
419 bit_count (register int i)
420 {
421   register int set_bits;
422
423   for (set_bits = 0; i != 0; set_bits++)
424     i &= i - 1;
425   return set_bits;
426 }
427
428 static void
429 print_stats (void)
430 {
431   char buf[2][INT_BUFSIZE_BOUND (uintmax_t)];
432   fprintf (stderr, _("%s+%s records in\n"),
433            umaxtostr (r_full, buf[0]), umaxtostr (r_partial, buf[1]));
434   fprintf (stderr, _("%s+%s records out\n"),
435            umaxtostr (w_full, buf[0]), umaxtostr (w_partial, buf[1]));
436   if (r_truncate > 0)
437     {
438       fprintf (stderr, "%s %s\n",
439                umaxtostr (r_truncate, buf[0]),
440                (r_truncate == 1
441                 ? _("truncated record")
442                 : _("truncated records")));
443     }
444 }
445
446 static void
447 cleanup (void)
448 {
449   print_stats ();
450   if (close (STDIN_FILENO) < 0)
451     error (EXIT_FAILURE, errno,
452            _("closing input file %s"), quote (input_file));
453   if (close (STDOUT_FILENO) < 0)
454     error (EXIT_FAILURE, errno,
455            _("closing output file %s"), quote (output_file));
456 }
457
458 static inline void
459 quit (int code)
460 {
461   cleanup ();
462   exit (code);
463 }
464
465 static RETSIGTYPE
466 interrupt_handler (int sig)
467 {
468 #ifdef SA_NOCLDSTOP
469   struct sigaction sigact;
470
471   sigact.sa_handler = SIG_DFL;
472   sigemptyset (&sigact.sa_mask);
473   sigact.sa_flags = 0;
474   sigaction (sig, &sigact, NULL);
475 #else
476   signal (sig, SIG_DFL);
477 #endif
478   cleanup ();
479   raise (sig);
480 }
481
482 static RETSIGTYPE
483 siginfo_handler (int sig ATTRIBUTE_UNUSED)
484 {
485   print_stats ();
486 }
487
488 /* Encapsulate portability mess of establishing signal handlers.  */
489
490 static void
491 install_handler (int sig_num, RETSIGTYPE (*sig_handler) (int sig))
492 {
493 #ifdef SA_NOCLDSTOP
494   struct sigaction sigact;
495   sigaction (sig_num, NULL, &sigact);
496   if (sigact.sa_handler != SIG_IGN)
497     {
498       sigact.sa_handler = sig_handler;
499       sigemptyset (&sigact.sa_mask);
500       sigact.sa_flags = 0;
501       sigaction (sig_num, &sigact, NULL);
502     }
503 #else
504   if (signal (sig_num, SIG_IGN) != SIG_IGN)
505     signal (sig_num, sig_handler);
506 #endif
507 }
508
509 /* Open a file to a particular file descriptor.  This is like standard
510    `open', except it always returns DESIRED_FD if successful.  */
511 static int
512 open_fd (int desired_fd, char const *filename, int options, mode_t mode)
513 {
514   int fd;
515   close (desired_fd);
516   fd = open (filename, options, mode);
517   if (fd < 0)
518     return -1;
519
520   if (fd != desired_fd)
521     {
522       if (dup2 (fd, desired_fd) != desired_fd)
523         desired_fd = -1;
524       if (close (fd) != 0)
525         return -1;
526     }
527
528   return desired_fd;
529 }
530
531 /* Write, then empty, the output buffer `obuf'. */
532
533 static void
534 write_output (void)
535 {
536   size_t nwritten = full_write (STDOUT_FILENO, obuf, output_blocksize);
537   if (nwritten != output_blocksize)
538     {
539       error (0, errno, _("writing to %s"), quote (output_file));
540       if (nwritten != 0)
541         w_partial++;
542       quit (EXIT_FAILURE);
543     }
544   else
545     w_full++;
546   oc = 0;
547 }
548
549 /* Diagnostics for invalid iflag="..." and oflag="..." symbols.  */
550 static char const iflag_error_msgid[] = N_("invalid input flag: %s");
551 static char const oflag_error_msgid[] = N_("invalid output flag: %s");
552
553 /* Interpret one "conv=..." or similar option STR according to the
554    symbols in TABLE, returning the flags specified.  If the option
555    cannot be parsed, use ERROR_MSGID to generate a diagnostic.
556    As a by product, this function replaces each `,' in STR with a NUL byte.  */
557
558 static int
559 parse_symbols (char *str, struct symbol_value const *table,
560                char const *error_msgid)
561 {
562   int value = 0;
563
564   do
565     {
566       struct symbol_value const *entry;
567       char *new = strchr (str, ',');
568       if (new != NULL)
569         *new++ = '\0';
570       for (entry = table; ; entry++)
571         {
572           if (! entry->symbol[0])
573             {
574               error (0, 0, _(error_msgid), quote (str));
575               usage (EXIT_FAILURE);
576             }
577           if (STREQ (entry->symbol, str))
578             {
579               if (! entry->value)
580                 error (EXIT_FAILURE, 0, _(error_msgid), quote (str));
581               value |= entry->value;
582               break;
583             }
584         }
585       str = new;
586     }
587   while (str);
588
589   return value;
590 }
591
592 /* Return the value of STR, interpreted as a non-negative decimal integer,
593    optionally multiplied by various values.
594    Assign nonzero to *INVALID if STR does not represent a number in
595    this format. */
596
597 static uintmax_t
598 parse_integer (const char *str, int *invalid)
599 {
600   uintmax_t n;
601   char *suffix;
602   enum strtol_error e = xstrtoumax (str, &suffix, 10, &n, "bcEGkKMPTwYZ0");
603
604   if (e == LONGINT_INVALID_SUFFIX_CHAR && *suffix == 'x')
605     {
606       uintmax_t multiplier = parse_integer (suffix + 1, invalid);
607
608       if (multiplier != 0 && n * multiplier / multiplier != n)
609         {
610           *invalid = 1;
611           return 0;
612         }
613
614       n *= multiplier;
615     }
616   else if (e != LONGINT_OK)
617     {
618       *invalid = 1;
619       return 0;
620     }
621
622   return n;
623 }
624
625 static void
626 scanargs (int argc, char **argv)
627 {
628   int i;
629
630   --argc;
631   ++argv;
632
633   for (i = optind; i < argc; i++)
634     {
635       char *name, *val;
636
637       name = argv[i];
638       val = strchr (name, '=');
639       if (val == NULL)
640         {
641           error (0, 0, _("unrecognized option %s"), quote (name));
642           usage (EXIT_FAILURE);
643         }
644       *val++ = '\0';
645
646       if (STREQ (name, "if"))
647         input_file = val;
648       else if (STREQ (name, "of"))
649         output_file = val;
650       else if (STREQ (name, "conv"))
651         conversions_mask |= parse_symbols (val, conversions,
652                                            N_("invalid conversion: %s"));
653       else if (STREQ (name, "iflag"))
654         input_flags |= parse_symbols (val, flags, iflag_error_msgid);
655       else if (STREQ (name, "oflag"))
656         output_flags |= parse_symbols (val, flags, oflag_error_msgid);
657       else
658         {
659           int invalid = 0;
660           uintmax_t n = parse_integer (val, &invalid);
661
662           if (STREQ (name, "ibs"))
663             {
664               /* Ensure that each blocksize is <= SSIZE_MAX.  */
665               invalid |= SSIZE_MAX < n;
666               input_blocksize = n;
667               invalid |= input_blocksize != n || input_blocksize == 0;
668               conversions_mask |= C_TWOBUFS;
669             }
670           else if (STREQ (name, "obs"))
671             {
672               /* Ensure that each blocksize is <= SSIZE_MAX.  */
673               invalid |= SSIZE_MAX < n;
674               output_blocksize = n;
675               invalid |= output_blocksize != n || output_blocksize == 0;
676               conversions_mask |= C_TWOBUFS;
677             }
678           else if (STREQ (name, "bs"))
679             {
680               /* Ensure that each blocksize is <= SSIZE_MAX.  */
681               invalid |= SSIZE_MAX < n;
682               output_blocksize = input_blocksize = n;
683               invalid |= output_blocksize != n || output_blocksize == 0;
684             }
685           else if (STREQ (name, "cbs"))
686             {
687               conversion_blocksize = n;
688               invalid |= (conversion_blocksize != n
689                           || conversion_blocksize == 0);
690             }
691           else if (STREQ (name, "skip"))
692             skip_records = n;
693           else if (STREQ (name, "seek"))
694             seek_records = n;
695           else if (STREQ (name, "count"))
696             max_records = n;
697           else
698             {
699               error (0, 0, _("unrecognized option %s=%s"),
700                      quote_n (0, name), quote_n (1, val));
701               usage (EXIT_FAILURE);
702             }
703
704           if (invalid)
705             error (EXIT_FAILURE, 0, _("invalid number %s"), quote (val));
706         }
707     }
708
709   /* If bs= was given, both `input_blocksize' and `output_blocksize' will
710      have been set to positive values.  If either has not been set,
711      bs= was not given, so make sure two buffers are used. */
712   if (input_blocksize == 0 || output_blocksize == 0)
713     conversions_mask |= C_TWOBUFS;
714   if (input_blocksize == 0)
715     input_blocksize = DEFAULT_BLOCKSIZE;
716   if (output_blocksize == 0)
717     output_blocksize = DEFAULT_BLOCKSIZE;
718   if (conversion_blocksize == 0)
719     conversions_mask &= ~(C_BLOCK | C_UNBLOCK);
720
721   if (input_flags & (O_DSYNC | O_SYNC))
722     input_flags |= O_RSYNC;
723
724   if ((conversions_mask & (C_EXCL | C_NOCREAT)) == (C_EXCL | C_NOCREAT))
725     error (EXIT_FAILURE, 0, _("cannot combine excl and nocreat"));
726 }
727
728 /* Fix up translation table. */
729
730 static void
731 apply_translations (void)
732 {
733   int i;
734
735 #define MX(a) (bit_count (conversions_mask & (a)))
736   if ((MX (C_ASCII | C_EBCDIC | C_IBM) > 1)
737       || (MX (C_BLOCK | C_UNBLOCK) > 1)
738       || (MX (C_LCASE | C_UCASE) > 1))
739     {
740       error (EXIT_FAILURE, 0, _("\
741         only one conv in {ascii,ebcdic,ibm}, {lcase,ucase}, {block,unblock}"));
742     }
743 #undef MX
744
745   if (conversions_mask & C_ASCII)
746     translate_charset (ebcdic_to_ascii);
747
748   if (conversions_mask & C_UCASE)
749     {
750       for (i = 0; i < 256; i++)
751         if (ISLOWER (trans_table[i]))
752           trans_table[i] = TOUPPER (trans_table[i]);
753       translation_needed = 1;
754     }
755   else if (conversions_mask & C_LCASE)
756     {
757       for (i = 0; i < 256; i++)
758         if (ISUPPER (trans_table[i]))
759           trans_table[i] = TOLOWER (trans_table[i]);
760       translation_needed = 1;
761     }
762
763   if (conversions_mask & C_EBCDIC)
764     {
765       translate_charset (ascii_to_ebcdic);
766       newline_character = ascii_to_ebcdic['\n'];
767       space_character = ascii_to_ebcdic[' '];
768     }
769   else if (conversions_mask & C_IBM)
770     {
771       translate_charset (ascii_to_ibm);
772       newline_character = ascii_to_ibm['\n'];
773       space_character = ascii_to_ibm[' '];
774     }
775 }
776
777 /* Apply the character-set translations specified by the user
778    to the NREAD bytes in BUF.  */
779
780 static void
781 translate_buffer (char *buf, size_t nread)
782 {
783   char *cp;
784   size_t i;
785
786   for (i = nread, cp = buf; i; i--, cp++)
787     *cp = trans_table[(unsigned char) *cp];
788 }
789
790 /* If nonnzero, the last char from the previous call to `swab_buffer'
791    is saved in `saved_char'.  */
792 static int char_is_saved = 0;
793
794 /* Odd char from previous call.  */
795 static char saved_char;
796
797 /* Swap NREAD bytes in BUF, plus possibly an initial char from the
798    previous call.  If NREAD is odd, save the last char for the
799    next call.   Return the new start of the BUF buffer.  */
800
801 static char *
802 swab_buffer (char *buf, size_t *nread)
803 {
804   char *bufstart = buf;
805   register char *cp;
806   register int i;
807
808   /* Is a char left from last time?  */
809   if (char_is_saved)
810     {
811       *--bufstart = saved_char;
812       (*nread)++;
813       char_is_saved = 0;
814     }
815
816   if (*nread & 1)
817     {
818       /* An odd number of chars are in the buffer.  */
819       saved_char = bufstart[--*nread];
820       char_is_saved = 1;
821     }
822
823   /* Do the byte-swapping by moving every second character two
824      positions toward the end, working from the end of the buffer
825      toward the beginning.  This way we only move half of the data.  */
826
827   cp = bufstart + *nread;       /* Start one char past the last.  */
828   for (i = *nread / 2; i; i--, cp -= 2)
829     *cp = *(cp - 2);
830
831   return ++bufstart;
832 }
833
834 /* This is a wrapper for lseek.  It detects and warns about a kernel
835    bug that makes lseek a no-op for tape devices, even though the kernel
836    lseek return value suggests that the function succeeded.
837
838    The parameters are the same as those of the lseek function, but
839    with the addition of FILENAME, the name of the file associated with
840    descriptor FDESC.  The file name is used solely in the warning that's
841    printed when the bug is detected.  Return the same value that lseek
842    would have returned, but when the lseek bug is detected, return -1
843    to indicate that lseek failed.
844
845    The offending behavior has been confirmed with an Exabyte SCSI tape
846    drive accessed via /dev/nst0 on both Linux-2.2.17 and Linux-2.4.16.  */
847
848 #ifdef __linux__
849
850 # include <sys/mtio.h>
851
852 # define MT_SAME_POSITION(P, Q) \
853    ((P).mt_resid == (Q).mt_resid \
854     && (P).mt_fileno == (Q).mt_fileno \
855     && (P).mt_blkno == (Q).mt_blkno)
856
857 static off_t
858 skip_via_lseek (char const *filename, int fdesc, off_t offset, int whence)
859 {
860   struct mtget s1;
861   struct mtget s2;
862   off_t new_position;
863   int got_original_tape_position;
864
865   got_original_tape_position = (ioctl (fdesc, MTIOCGET, &s1) == 0);
866   /* known bad device type */
867   /* && s.mt_type == MT_ISSCSI2 */
868
869   new_position = lseek (fdesc, offset, whence);
870   if (0 <= new_position
871       && got_original_tape_position
872       && ioctl (fdesc, MTIOCGET, &s2) == 0
873       && MT_SAME_POSITION (s1, s2))
874     {
875       error (0, 0, _("warning: working around lseek kernel bug for file (%s)\n\
876   of mt_type=0x%0lx -- see <sys/mtio.h> for the list of types"),
877              filename, s2.mt_type);
878       new_position = -1;
879     }
880
881   return new_position;
882 }
883 #else
884 # define skip_via_lseek(Filename, Fd, Offset, Whence) lseek (Fd, Offset, Whence)
885 #endif
886
887 /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
888    which is open with read permission for FILE.  Store up to BLOCKSIZE
889    bytes of the data at a time in BUF, if necessary.  RECORDS must be
890    nonzero.  */
891
892 static void
893 skip (int fdesc, char const *file, uintmax_t records, size_t blocksize,
894       char *buf)
895 {
896   off_t offset = records * blocksize;
897
898   /* Try lseek and if an error indicates it was an inappropriate operation --
899      or if the the file offset is not representable as an off_t --
900      fall back on using read.  */
901
902   if ((uintmax_t) offset / blocksize != records
903       || skip_via_lseek (file, fdesc, offset, SEEK_CUR) < 0)
904     {
905       while (records--)
906         {
907           size_t nread = safe_read (fdesc, buf, blocksize);
908           if (nread == SAFE_READ_ERROR)
909             {
910               error (0, errno, _("reading %s"), quote (file));
911               quit (EXIT_FAILURE);
912             }
913           /* POSIX doesn't say what to do when dd detects it has been
914              asked to skip past EOF, so I assume it's non-fatal.
915              FIXME: maybe give a warning.  */
916           if (nread == 0)
917             break;
918         }
919     }
920 }
921
922 /* Copy NREAD bytes of BUF, with no conversions.  */
923
924 static void
925 copy_simple (char const *buf, int nread)
926 {
927   int nfree;                    /* Number of unused bytes in `obuf'.  */
928   const char *start = buf;      /* First uncopied char in BUF.  */
929
930   do
931     {
932       nfree = output_blocksize - oc;
933       if (nfree > nread)
934         nfree = nread;
935
936       memcpy (obuf + oc, start, nfree);
937
938       nread -= nfree;           /* Update the number of bytes left to copy. */
939       start += nfree;
940       oc += nfree;
941       if (oc >= output_blocksize)
942         write_output ();
943     }
944   while (nread > 0);
945 }
946
947 /* Copy NREAD bytes of BUF, doing conv=block
948    (pad newline-terminated records to `conversion_blocksize',
949    replacing the newline with trailing spaces).  */
950
951 static void
952 copy_with_block (char const *buf, size_t nread)
953 {
954   size_t i;
955
956   for (i = nread; i; i--, buf++)
957     {
958       if (*buf == newline_character)
959         {
960           if (col < conversion_blocksize)
961             {
962               size_t j;
963               for (j = col; j < conversion_blocksize; j++)
964                 output_char (space_character);
965             }
966           col = 0;
967         }
968       else
969         {
970           if (col == conversion_blocksize)
971             r_truncate++;
972           else if (col < conversion_blocksize)
973             output_char (*buf);
974           col++;
975         }
976     }
977 }
978
979 /* Copy NREAD bytes of BUF, doing conv=unblock
980    (replace trailing spaces in `conversion_blocksize'-sized records
981    with a newline).  */
982
983 static void
984 copy_with_unblock (char const *buf, size_t nread)
985 {
986   size_t i;
987   char c;
988   static int pending_spaces = 0;
989
990   for (i = 0; i < nread; i++)
991     {
992       c = buf[i];
993
994       if (col++ >= conversion_blocksize)
995         {
996           col = pending_spaces = 0; /* Wipe out any pending spaces.  */
997           i--;                  /* Push the char back; get it later. */
998           output_char (newline_character);
999         }
1000       else if (c == space_character)
1001         pending_spaces++;
1002       else
1003         {
1004           /* `c' is the character after a run of spaces that were not
1005              at the end of the conversion buffer.  Output them.  */
1006           while (pending_spaces)
1007             {
1008               output_char (space_character);
1009               --pending_spaces;
1010             }
1011           output_char (c);
1012         }
1013     }
1014 }
1015
1016 /* Set the file descriptor flags for FD that correspond to the nonzero bits
1017    in FLAGS.  The file's name is NAME.  */
1018
1019 static void
1020 set_fd_flags (int fd, int add_flags, char const *name)
1021 {
1022   if (add_flags)
1023     {
1024       int old_flags = fcntl (fd, F_GETFL);
1025       int new_flags = old_flags < 0 ? add_flags : (old_flags | add_flags);
1026       if (old_flags < 0
1027           || (new_flags != old_flags && fcntl (fd, F_SETFL, new_flags) == -1))
1028         error (EXIT_FAILURE, errno, _("setting flags for %s"), quote (name));
1029     }
1030 }
1031
1032 /* The main loop.  */
1033
1034 static int
1035 dd_copy (void)
1036 {
1037   char *ibuf, *bufstart;        /* Input buffer. */
1038   char *real_buf;               /* real buffer address before alignment */
1039   char *real_obuf;
1040   size_t nread;                 /* Bytes read in the current block. */
1041   int exit_status = EXIT_SUCCESS;
1042   size_t page_size = getpagesize ();
1043   size_t n_bytes_read;
1044
1045   /* Leave at least one extra byte at the beginning and end of `ibuf'
1046      for conv=swab, but keep the buffer address even.  But some peculiar
1047      device drivers work only with word-aligned buffers, so leave an
1048      extra two bytes.  */
1049
1050   /* Some devices require alignment on a sector or page boundary
1051      (e.g. character disk devices).  Align the input buffer to a
1052      page boundary to cover all bases.  Note that due to the swab
1053      algorithm, we must have at least one byte in the page before
1054      the input buffer;  thus we allocate 2 pages of slop in the
1055      real buffer.  8k above the blocksize shouldn't bother anyone.
1056
1057      The page alignment is necessary on any linux system that supports
1058      either the SGI raw I/O patch or Steven Tweedies raw I/O patch.
1059      It is necessary when accessing raw (i.e. character special) disk
1060      devices on Unixware or other SVR4-derived system.  */
1061
1062   real_buf = xmalloc (input_blocksize
1063                       + 2 * SWAB_ALIGN_OFFSET
1064                       + 2 * page_size - 1);
1065   ibuf = real_buf;
1066   ibuf += SWAB_ALIGN_OFFSET;    /* allow space for swab */
1067
1068   ibuf = PTR_ALIGN (ibuf, page_size);
1069
1070   if (conversions_mask & C_TWOBUFS)
1071     {
1072       /* Page-align the output buffer, too.  */
1073       real_obuf = xmalloc (output_blocksize + page_size - 1);
1074       obuf = PTR_ALIGN (real_obuf, page_size);
1075     }
1076   else
1077     {
1078       real_obuf = NULL;
1079       obuf = ibuf;
1080     }
1081
1082   if (skip_records != 0)
1083     skip (STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf);
1084
1085   if (seek_records != 0)
1086     {
1087       /* FIXME: this loses for
1088          % ./dd if=dd seek=1 |:
1089          ./dd: standard output: Bad file descriptor
1090          0+0 records in
1091          0+0 records out
1092          */
1093
1094       skip (STDOUT_FILENO, output_file, seek_records, output_blocksize, obuf);
1095     }
1096
1097   if (max_records == 0)
1098     return exit_status;
1099
1100   while (1)
1101     {
1102       if (r_partial + r_full >= max_records)
1103         break;
1104
1105       /* Zero the buffer before reading, so that if we get a read error,
1106          whatever data we are able to read is followed by zeros.
1107          This minimizes data loss. */
1108       if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
1109         memset (ibuf,
1110                 (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
1111                 input_blocksize);
1112
1113       nread = safe_read (STDIN_FILENO, ibuf, input_blocksize);
1114
1115       if (nread == 0)
1116         break;                  /* EOF.  */
1117
1118       if (nread == SAFE_READ_ERROR)
1119         {
1120           error (0, errno, _("reading %s"), quote (input_file));
1121           if (conversions_mask & C_NOERROR)
1122             {
1123               print_stats ();
1124               /* Seek past the bad block if possible. */
1125               lseek (STDIN_FILENO, (off_t) input_blocksize, SEEK_CUR);
1126               if (conversions_mask & C_SYNC)
1127                 /* Replace the missing input with null bytes and
1128                    proceed normally.  */
1129                 nread = 0;
1130               else
1131                 continue;
1132             }
1133           else
1134             {
1135               /* Write any partial block. */
1136               exit_status = EXIT_FAILURE;
1137               break;
1138             }
1139         }
1140
1141       n_bytes_read = nread;
1142
1143       if (n_bytes_read < input_blocksize)
1144         {
1145           r_partial++;
1146           if (conversions_mask & C_SYNC)
1147             {
1148               if (!(conversions_mask & C_NOERROR))
1149                 /* If C_NOERROR, we zeroed the block before reading. */
1150                 memset (ibuf + n_bytes_read,
1151                         (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
1152                         input_blocksize - n_bytes_read);
1153               n_bytes_read = input_blocksize;
1154             }
1155         }
1156       else
1157         r_full++;
1158
1159       if (ibuf == obuf)         /* If not C_TWOBUFS. */
1160         {
1161           size_t nwritten = full_write (STDOUT_FILENO, obuf, n_bytes_read);
1162           if (nwritten != n_bytes_read)
1163             {
1164               error (0, errno, _("writing %s"), quote (output_file));
1165               return EXIT_FAILURE;
1166             }
1167           else if (n_bytes_read == input_blocksize)
1168             w_full++;
1169           else
1170             w_partial++;
1171           continue;
1172         }
1173
1174       /* Do any translations on the whole buffer at once.  */
1175
1176       if (translation_needed)
1177         translate_buffer (ibuf, n_bytes_read);
1178
1179       if (conversions_mask & C_SWAB)
1180         bufstart = swab_buffer (ibuf, &n_bytes_read);
1181       else
1182         bufstart = ibuf;
1183
1184       if (conversions_mask & C_BLOCK)
1185         copy_with_block (bufstart, n_bytes_read);
1186       else if (conversions_mask & C_UNBLOCK)
1187         copy_with_unblock (bufstart, n_bytes_read);
1188       else
1189         copy_simple (bufstart, n_bytes_read);
1190     }
1191
1192   /* If we have a char left as a result of conv=swab, output it.  */
1193   if (char_is_saved)
1194     {
1195       if (conversions_mask & C_BLOCK)
1196         copy_with_block (&saved_char, 1);
1197       else if (conversions_mask & C_UNBLOCK)
1198         copy_with_unblock (&saved_char, 1);
1199       else
1200         output_char (saved_char);
1201     }
1202
1203   if ((conversions_mask & C_BLOCK) && col > 0)
1204     {
1205       /* If the final input line didn't end with a '\n', pad
1206          the output block to `conversion_blocksize' chars.  */
1207       size_t i;
1208       for (i = col; i < conversion_blocksize; i++)
1209         output_char (space_character);
1210     }
1211
1212   if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
1213     /* Add a final '\n' if there are exactly `conversion_blocksize'
1214        characters in the final record. */
1215     output_char (newline_character);
1216
1217   /* Write out the last block. */
1218   if (oc != 0)
1219     {
1220       size_t nwritten = full_write (STDOUT_FILENO, obuf, oc);
1221       if (nwritten != 0)
1222         w_partial++;
1223       if (nwritten != oc)
1224         {
1225           error (0, errno, _("writing %s"), quote (output_file));
1226           return EXIT_FAILURE;
1227         }
1228     }
1229
1230   free (real_buf);
1231   if (real_obuf)
1232     free (real_obuf);
1233
1234   if ((conversions_mask & C_FDATASYNC) && fdatasync (STDOUT_FILENO) != 0)
1235     {
1236       if (errno != ENOSYS && errno != EINVAL)
1237         {
1238           error (0, errno, _("fdatasync failed for %s"), quote (output_file));
1239           exit_status = EXIT_FAILURE;
1240         }
1241       conversions_mask |= C_FSYNC;
1242     }
1243
1244   if (conversions_mask & C_FSYNC)
1245     while (fsync (STDOUT_FILENO) != 0)
1246       if (errno != EINTR)
1247         {
1248           error (0, errno, _("fsync failed for %s"), quote (output_file));
1249           return EXIT_FAILURE;
1250         }
1251
1252   return exit_status;
1253 }
1254
1255 /* This is gross, but necessary, because of the way close_stdout
1256    works and because this program closes STDOUT_FILENO directly.  */
1257 static void (*closeout_func) (void) = close_stdout;
1258
1259 static void
1260 close_stdout_wrapper (void)
1261 {
1262   if (closeout_func)
1263     (*closeout_func) ();
1264 }
1265
1266 int
1267 main (int argc, char **argv)
1268 {
1269   int i;
1270   int exit_status;
1271
1272   initialize_main (&argc, &argv);
1273   program_name = argv[0];
1274   setlocale (LC_ALL, "");
1275   bindtextdomain (PACKAGE, LOCALEDIR);
1276   textdomain (PACKAGE);
1277
1278   /* Arrange to close stdout if parse_long_options exits.  */
1279   atexit (close_stdout_wrapper);
1280
1281   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
1282                       usage, AUTHORS, (char const *) NULL);
1283
1284   /* Don't close stdout on exit from here on.  */
1285   closeout_func = NULL;
1286
1287   /* Initialize translation table to identity translation. */
1288   for (i = 0; i < 256; i++)
1289     trans_table[i] = i;
1290
1291   /* Decode arguments. */
1292   scanargs (argc, argv);
1293
1294   apply_translations ();
1295
1296   if (input_file == NULL)
1297     {
1298       input_file = _("standard input");
1299       set_fd_flags (STDIN_FILENO, input_flags, input_file);
1300     }
1301   else
1302     {
1303       if (open_fd (STDIN_FILENO, input_file, O_RDONLY | input_flags, 0) < 0)
1304         error (EXIT_FAILURE, errno, _("opening %s"), quote (input_file));
1305     }
1306
1307   if (output_file == NULL)
1308     {
1309       output_file = _("standard output");
1310       set_fd_flags (STDOUT_FILENO, output_flags, output_file);
1311     }
1312   else
1313     {
1314       mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
1315       int opts
1316         = (output_flags
1317            | (conversions_mask & C_NOCREAT ? 0 : O_CREAT)
1318            | (conversions_mask & C_EXCL ? O_EXCL : 0)
1319            | (seek_records || (conversions_mask & C_NOTRUNC) ? 0 : O_TRUNC));
1320
1321       /* Open the output file with *read* access only if we might
1322          need to read to satisfy a `seek=' request.  If we can't read
1323          the file, go ahead with write-only access; it might work.  */
1324       if ((! seek_records
1325            || open_fd (STDOUT_FILENO, output_file, O_RDWR | opts, perms) < 0)
1326           && open_fd (STDOUT_FILENO, output_file, O_WRONLY | opts, perms) < 0)
1327         error (EXIT_FAILURE, errno, _("opening %s"), quote (output_file));
1328
1329 #if HAVE_FTRUNCATE
1330       if (seek_records != 0 && !(conversions_mask & C_NOTRUNC))
1331         {
1332           struct stat stdout_stat;
1333           off_t o = seek_records * output_blocksize;
1334           if ((uintmax_t) o / output_blocksize != seek_records)
1335             error (EXIT_FAILURE, 0, _("file offset out of range"));
1336
1337           if (fstat (STDOUT_FILENO, &stdout_stat) != 0)
1338             error (EXIT_FAILURE, errno, _("cannot fstat %s"),
1339                    quote (output_file));
1340
1341           /* Complain only when ftruncate fails on a regular file, a
1342              directory, or a shared memory object, as
1343              POSIX 1003.1-2003 specifies ftruncate's behavior only for these
1344              file types.  For example, do not complain when Linux 2.4
1345              ftruncate fails on /dev/fd0.  */
1346           if (ftruncate (STDOUT_FILENO, o) != 0
1347               && (S_ISREG (stdout_stat.st_mode)
1348                   || S_ISDIR (stdout_stat.st_mode)
1349                   || S_TYPEISSHM (&stdout_stat)))
1350             {
1351               char buf[INT_BUFSIZE_BOUND (off_t)];
1352               error (EXIT_FAILURE, errno,
1353                      _("advancing past %s bytes in output file %s"),
1354                      offtostr (o, buf), quote (output_file));
1355             }
1356         }
1357 #endif
1358     }
1359
1360   install_handler (SIGINT, interrupt_handler);
1361   install_handler (SIGQUIT, interrupt_handler);
1362   install_handler (SIGPIPE, interrupt_handler);
1363   install_handler (SIGINFO, siginfo_handler);
1364
1365   exit_status = dd_copy ();
1366
1367   quit (exit_status);
1368 }