1 /* dd -- convert a file while copying it.
2 Copyright (C) 85, 90, 91, 95, 96, 97, 1998 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)
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. */
23 #define SWAB_ALIGN_OFFSET 2
26 # include <inttypes.h>
28 #include <sys/types.h>
38 # define SIGINFO SIGUSR1
41 #define max(a, b) ((a) > (b) ? (a) : (b))
42 #define output_char(c) \
44 obuf[oc++] = (c); if (oc >= output_blocksize) write_output (); \
47 /* Default input and output blocksize. */
48 #define DEFAULT_BLOCKSIZE 512
50 /* Conversions bit masks. */
59 #define C_NOERROR 0400
60 #define C_NOTRUNC 01000
62 /* Use separate input and output buffers, and combine partial input blocks. */
63 #define C_TWOBUFS 04000
68 static RETSIGTYPE interrupt_handler
PARAMS ((int));
69 static int bit_count
PARAMS ((register unsigned int i
));
70 static uintmax_t parse_integer
PARAMS ((char *str
, int *));
71 static void apply_translations
PARAMS ((void));
72 static void copy
PARAMS ((void));
73 static void copy_simple
PARAMS ((unsigned char *buf
, int nread
));
74 static void copy_with_block
PARAMS ((unsigned char *buf
, int nread
));
75 static void copy_with_unblock
PARAMS ((unsigned char *buf
, int nread
));
76 static void parse_conversion
PARAMS ((char *str
));
77 static void translate_charset
PARAMS ((const unsigned char *new_trans
));
78 static void quit
PARAMS ((int code
));
79 static void scanargs
PARAMS ((int argc
, char **argv
));
80 static void skip
PARAMS ((int fdesc
, char *file
, uintmax_t records
,
81 size_t blocksize
, unsigned char *buf
));
82 static void usage
PARAMS ((int status
));
83 static void write_output
PARAMS ((void));
85 /* The name this program was run with. */
88 /* The name of the input file, or NULL for the standard input. */
89 static char *input_file
= NULL
;
91 /* The input file descriptor. */
92 static int input_fd
= 0;
94 /* The name of the output file, or NULL for the standard output. */
95 static char *output_file
= NULL
;
97 /* The output file descriptor. */
98 static int output_fd
= 1;
100 /* The number of bytes in which atomic reads are done. */
101 static size_t input_blocksize
= 0;
103 /* The number of bytes in which atomic writes are done. */
104 static size_t output_blocksize
= 0;
106 /* Conversion buffer size, in bytes. 0 prevents conversions. */
107 static size_t conversion_blocksize
= 0;
109 /* Skip this many records of `input_blocksize' bytes before input. */
110 static uintmax_t skip_records
= 0;
112 /* Skip this many records of `output_blocksize' bytes before output. */
113 static uintmax_t seek_record
= 0;
115 /* Copy only this many records. The default is effectively infinity. */
116 static uintmax_t max_records
= (uintmax_t) -1;
118 /* Bit vector of conversions to apply. */
119 static int conversions_mask
= 0;
121 /* If nonzero, filter characters through the translation table. */
122 static int translation_needed
= 0;
124 /* Number of partial blocks written. */
125 static uintmax_t w_partial
= 0;
127 /* Number of full blocks written. */
128 static uintmax_t w_full
= 0;
130 /* Number of partial blocks read. */
131 static uintmax_t r_partial
= 0;
133 /* Number of full blocks read. */
134 static uintmax_t r_full
= 0;
136 /* Records truncated by conv=block. */
137 static uintmax_t r_truncate
= 0;
139 /* Output representation of newline and space characters.
140 They change if we're converting to EBCDIC. */
141 static unsigned char newline_character
= '\n';
142 static unsigned char space_character
= ' ';
150 static struct conversion conversions
[] =
152 {"ascii", C_ASCII
| C_TWOBUFS
}, /* EBCDIC to ASCII. */
153 {"ebcdic", C_EBCDIC
| C_TWOBUFS
}, /* ASCII to EBCDIC. */
154 {"ibm", C_IBM
| C_TWOBUFS
}, /* Slightly different ASCII to EBCDIC. */
155 {"block", C_BLOCK
| C_TWOBUFS
}, /* Variable to fixed length records. */
156 {"unblock", C_UNBLOCK
| C_TWOBUFS
}, /* Fixed to variable length records. */
157 {"lcase", C_LCASE
| C_TWOBUFS
}, /* Translate upper to lower case. */
158 {"ucase", C_UCASE
| C_TWOBUFS
}, /* Translate lower to upper case. */
159 {"swab", C_SWAB
| C_TWOBUFS
}, /* Swap bytes of input. */
160 {"noerror", C_NOERROR
}, /* Ignore i/o errors. */
161 {"notrunc", C_NOTRUNC
}, /* Do not truncate output file. */
162 {"sync", C_SYNC
}, /* Pad input records to ibs with NULs. */
166 /* Translation table formed by applying successive transformations. */
167 static unsigned char trans_table
[256];
169 static unsigned char const ascii_to_ebcdic
[] =
171 0, 01, 02, 03, 067, 055, 056, 057,
172 026, 05, 045, 013, 014, 015, 016, 017,
173 020, 021, 022, 023, 074, 075, 062, 046,
174 030, 031, 077, 047, 034, 035, 036, 037,
175 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175,
176 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
177 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
178 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
179 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
180 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
181 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
182 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155,
183 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
184 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
185 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
186 0247, 0250, 0251, 0300, 0152, 0320, 0241, 07,
187 040, 041, 042, 043, 044, 025, 06, 027,
188 050, 051, 052, 053, 054, 011, 012, 033,
189 060, 061, 032, 063, 064, 065, 066, 010,
190 070, 071, 072, 073, 04, 024, 076, 0341,
191 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
192 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
193 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
194 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
195 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
196 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
197 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
198 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
199 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
200 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
201 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
202 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
205 static unsigned char const ascii_to_ibm
[] =
207 0, 01, 02, 03, 067, 055, 056, 057,
208 026, 05, 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 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
212 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
213 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
214 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
215 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
216 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
217 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
218 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
219 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
220 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
221 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
222 0247, 0250, 0251, 0300, 0117, 0320, 0241, 07,
223 040, 041, 042, 043, 044, 025, 06, 027,
224 050, 051, 052, 053, 054, 011, 012, 033,
225 060, 061, 032, 063, 064, 065, 066, 010,
226 070, 071, 072, 073, 04, 024, 076, 0341,
227 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
228 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
229 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
230 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
231 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
232 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
233 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
234 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
235 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
236 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
237 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
238 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
241 static unsigned char const ebcdic_to_ascii
[] =
243 0, 01, 02, 03, 0234, 011, 0206, 0177,
244 0227, 0215, 0216, 013, 014, 015, 016, 017,
245 020, 021, 022, 023, 0235, 0205, 010, 0207,
246 030, 031, 0222, 0217, 034, 035, 036, 037,
247 0200, 0201, 0202, 0203, 0204, 012, 027, 033,
248 0210, 0211, 0212, 0213, 0214, 05, 06, 07,
249 0220, 0221, 026, 0223, 0224, 0225, 0226, 04,
250 0230, 0231, 0232, 0233, 024, 025, 0236, 032,
251 040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
252 0247, 0250, 0133, 056, 074, 050, 053, 041,
253 046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
254 0260, 0261, 0135, 044, 052, 051, 073, 0136,
255 055, 057, 0262, 0263, 0264, 0265, 0266, 0267,
256 0270, 0271, 0174, 054, 045, 0137, 076, 077,
257 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
258 0302, 0140, 072, 043, 0100, 047, 075, 042,
259 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
260 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
261 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
262 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320,
263 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170,
264 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327,
265 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
266 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
267 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
268 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
269 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
270 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
271 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
272 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
273 060, 061, 062, 063, 064, 065, 066, 067,
274 070, 071, 0372, 0373, 0374, 0375, 0376, 0377
277 /* If nonzero, display usage information and exit. */
278 static int show_help
;
280 /* If nonzero, print the version on standard output and exit. */
281 static int show_version
;
283 static struct option
const long_options
[] =
285 {"help", no_argument
, &show_help
, 1},
286 {"version", no_argument
, &show_version
, 1},
293 char buf
[2][LONGEST_HUMAN_READABLE
+ 1];
294 fprintf (stderr
, _("%s+%s records in\n"),
295 human_readable (r_full
, buf
[0], 1, 1, 0),
296 human_readable (r_partial
, buf
[1], 1, 1, 0));
297 fprintf (stderr
, _("%s+%s records out\n"),
298 human_readable (w_full
, buf
[0], 1, 1, 0),
299 human_readable (w_partial
, buf
[1], 1, 1, 0));
301 fprintf (stderr
, "%s %s\n",
302 human_readable (r_truncate
, buf
[0], 1, 1, 0),
304 ? _("truncated record")
305 : _("truncated records")));
309 siginfo_handler (int sig
)
314 /* Encapsulate portability mess of establishing signal handlers. */
317 install_handler (int sig_num
, RETSIGTYPE (*sig_handler
) (int sig
))
319 #ifdef _POSIX_VERSION
320 struct sigaction sigact
;
321 sigaction (sig_num
, NULL
, &sigact
);
322 if (sigact
.sa_handler
!= SIG_IGN
)
324 sigact
.sa_handler
= sig_handler
;
325 sigemptyset (&sigact
.sa_mask
);
327 sigaction (sig_num
, &sigact
, NULL
);
330 if (signal (sig_num
, SIG_IGN
) != SIG_IGN
)
331 signal (sig_num
, sig_handler
);
336 main (int argc
, char **argv
)
340 program_name
= argv
[0];
341 setlocale (LC_ALL
, "");
342 bindtextdomain (PACKAGE
, LOCALEDIR
);
343 textdomain (PACKAGE
);
345 /* Initialize translation table to identity translation. */
346 for (i
= 0; i
< 256; i
++)
349 /* Decode arguments. */
350 scanargs (argc
, argv
);
354 printf ("dd (%s) %s\n", GNU_PACKAGE
, VERSION
);
362 apply_translations ();
364 if (input_file
!= NULL
)
366 input_fd
= open (input_file
, O_RDONLY
);
368 error (1, errno
, "%s", input_file
);
371 input_file
= _("standard input");
373 if (input_fd
== output_fd
)
374 error (1, 0, _("%s is closed"), (input_fd
== 0
375 ? _("standard input")
376 : _("standard output")));
378 if (output_file
!= NULL
)
380 int omode
= O_RDWR
| O_CREAT
;
382 if (seek_record
== 0 && !(conversions_mask
& C_NOTRUNC
))
384 output_fd
= open (output_file
, omode
, 0666);
386 error (1, errno
, "%s", output_file
);
387 #ifdef HAVE_FTRUNCATE
388 if (seek_record
!= 0 && !(conversions_mask
& C_NOTRUNC
))
390 off_t o
= seek_record
* output_blocksize
;
391 if (o
/ output_blocksize
!= seek_record
)
392 error (1, 0, _("file offset out of range"));
393 if (ftruncate (output_fd
, o
) < 0)
394 error (0, errno
, "%s", output_file
);
400 output_file
= _("standard output");
403 install_handler (SIGINT
, interrupt_handler
);
404 install_handler (SIGQUIT
, interrupt_handler
);
405 install_handler (SIGPIPE
, interrupt_handler
);
406 install_handler (SIGINFO
, siginfo_handler
);
411 /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
412 which is open with read permission for FILE. Store up to BLOCKSIZE
413 bytes of the data at a time in BUF, if necessary. */
416 skip (int fdesc
, char *file
, uintmax_t records
, size_t blocksize
,
422 /* Use fstat instead of checking for errno == ESPIPE because
423 lseek doesn't work on some special files but doesn't return an
425 /* FIXME: can this really happen? What system? */
426 if (fstat (fdesc
, &stats
))
428 error (0, errno
, "%s", file
);
432 /* Try lseek and if an error indicates it was an inappropriate
433 operation, fall back on using read. */
434 o
= records
* blocksize
;
435 if (o
/ blocksize
!= records
436 || lseek (fdesc
, o
, SEEK_SET
) == -1)
438 while (records
-- > 0)
442 nread
= safe_read (fdesc
, buf
, blocksize
);
445 error (0, errno
, "%s", file
);
448 /* POSIX doesn't say what to do when dd detects it has been
449 asked to skip past EOF, so I assume it's non-fatal.
450 FIXME: maybe give a warning. */
457 /* Apply the character-set translations specified by the user
458 to the NREAD bytes in BUF. */
461 translate_buffer (unsigned char *buf
, int nread
)
463 register unsigned char *cp
;
466 for (i
= nread
, cp
= buf
; i
; i
--, cp
++)
467 *cp
= trans_table
[*cp
];
470 /* If nonnzero, the last char from the previous call to `swab_buffer'
471 is saved in `saved_char'. */
472 static int char_is_saved
= 0;
474 /* Odd char from previous call. */
475 static unsigned char saved_char
;
477 /* Swap NREAD bytes in BUF, plus possibly an initial char from the
478 previous call. If NREAD is odd, save the last char for the
479 next call. Return the new start of the BUF buffer. */
481 static unsigned char *
482 swab_buffer (unsigned char *buf
, int *nread
)
484 unsigned char *bufstart
= buf
;
485 register unsigned char *cp
;
488 /* Is a char left from last time? */
491 *--bufstart
= saved_char
;
498 /* An odd number of chars are in the buffer. */
499 saved_char
= bufstart
[--*nread
];
503 /* Do the byte-swapping by moving every second character two
504 positions toward the end, working from the end of the buffer
505 toward the beginning. This way we only move half of the data. */
507 cp
= bufstart
+ *nread
; /* Start one char past the last. */
508 for (i
= *nread
/ 2; i
; i
--, cp
-= 2)
515 static unsigned char *obuf
;
517 /* Current index into `obuf'. */
518 static size_t oc
= 0;
520 /* Index into current line, for `conv=block' and `conv=unblock'. */
521 static size_t col
= 0;
528 unsigned char *ibuf
, *bufstart
; /* Input buffer. */
529 int nread
; /* Bytes read in the current block. */
532 /* Leave at least one extra byte at the beginning and end of `ibuf'
533 for conv=swab, but keep the buffer address even. But some peculiar
534 device drivers work only with word-aligned buffers, so leave an
537 ibuf
= (unsigned char *) xmalloc (input_blocksize
+ 2 * SWAB_ALIGN_OFFSET
);
538 ibuf
+= SWAB_ALIGN_OFFSET
;
540 if (conversions_mask
& C_TWOBUFS
)
541 obuf
= (unsigned char *) xmalloc (output_blocksize
);
545 if (skip_records
!= 0)
546 skip (input_fd
, input_file
, skip_records
, input_blocksize
, ibuf
);
548 if (seek_record
!= 0)
550 /* FIXME: this loses for
551 % ./dd if=dd seek=1 |:
552 ./dd: a1 standard output: Bad file number
557 skip (output_fd
, output_file
, seek_record
, output_blocksize
, obuf
);
560 if (max_records
== 0)
565 if (r_partial
+ r_full
>= max_records
)
568 /* Zero the buffer before reading, so that if we get a read error,
569 whatever data we are able to read is followed by zeros.
570 This minimizes data loss. */
571 if ((conversions_mask
& C_SYNC
) && (conversions_mask
& C_NOERROR
))
572 memset ((char *) ibuf
, 0, input_blocksize
);
574 nread
= safe_read (input_fd
, ibuf
, input_blocksize
);
581 error (0, errno
, "%s", input_file
);
582 if (conversions_mask
& C_NOERROR
)
585 /* Seek past the bad block if possible. */
586 lseek (input_fd
, (off_t
) input_blocksize
, SEEK_CUR
);
587 if (conversions_mask
& C_SYNC
)
588 /* Replace the missing input with null bytes and
596 /* Write any partial block. */
602 if (nread
< input_blocksize
)
605 if (conversions_mask
& C_SYNC
)
607 if (!(conversions_mask
& C_NOERROR
))
608 /* If C_NOERROR, we zeroed the block before reading. */
609 memset ((char *) (ibuf
+ nread
), 0, input_blocksize
- nread
);
610 nread
= input_blocksize
;
616 if (ibuf
== obuf
) /* If not C_TWOBUFS. */
618 int nwritten
= full_write (output_fd
, obuf
, nread
);
621 error (0, errno
, "%s", output_file
);
624 else if (nread
== input_blocksize
)
631 /* Do any translations on the whole buffer at once. */
633 if (translation_needed
)
634 translate_buffer (ibuf
, nread
);
636 if (conversions_mask
& C_SWAB
)
637 bufstart
= swab_buffer (ibuf
, &nread
);
641 if (conversions_mask
& C_BLOCK
)
642 copy_with_block (bufstart
, nread
);
643 else if (conversions_mask
& C_UNBLOCK
)
644 copy_with_unblock (bufstart
, nread
);
646 copy_simple (bufstart
, nread
);
649 /* If we have a char left as a result of conv=swab, output it. */
652 if (conversions_mask
& C_BLOCK
)
653 copy_with_block (&saved_char
, 1);
654 else if (conversions_mask
& C_UNBLOCK
)
655 copy_with_unblock (&saved_char
, 1);
657 output_char (saved_char
);
660 if ((conversions_mask
& C_BLOCK
) && col
> 0)
662 /* If the final input line didn't end with a '\n', pad
663 the output block to `conversion_blocksize' chars. */
665 for (i
= col
; i
< conversion_blocksize
; i
++)
666 output_char (space_character
);
669 if ((conversions_mask
& C_UNBLOCK
) && col
== conversion_blocksize
)
670 /* Add a final '\n' if there are exactly `conversion_blocksize'
671 characters in the final record. */
672 output_char (newline_character
);
674 /* Write out the last block. */
677 int nwritten
= full_write (output_fd
, obuf
, oc
);
682 error (0, errno
, "%s", output_file
);
687 free (ibuf
- SWAB_ALIGN_OFFSET
);
694 /* Copy NREAD bytes of BUF, with no conversions. */
697 copy_simple (unsigned char *buf
, int nread
)
699 int nfree
; /* Number of unused bytes in `obuf'. */
700 unsigned char *start
= buf
; /* First uncopied char in BUF. */
704 nfree
= output_blocksize
- oc
;
708 memcpy ((char *) (obuf
+ oc
), (char *) start
, nfree
);
710 nread
-= nfree
; /* Update the number of bytes left to copy. */
713 if (oc
>= output_blocksize
)
719 /* Copy NREAD bytes of BUF, doing conv=block
720 (pad newline-terminated records to `conversion_blocksize',
721 replacing the newline with trailing spaces). */
724 copy_with_block (unsigned char *buf
, int nread
)
728 for (i
= nread
; i
; i
--, buf
++)
730 if (*buf
== newline_character
)
732 if (col
< conversion_blocksize
)
735 for (j
= col
; j
< conversion_blocksize
; j
++)
736 output_char (space_character
);
742 if (col
== conversion_blocksize
)
744 else if (col
< conversion_blocksize
)
751 /* Copy NREAD bytes of BUF, doing conv=unblock
752 (replace trailing spaces in `conversion_blocksize'-sized records
756 copy_with_unblock (unsigned char *buf
, int nread
)
759 register unsigned char c
;
760 static int pending_spaces
= 0;
762 for (i
= 0; i
< nread
; i
++)
766 if (col
++ >= conversion_blocksize
)
768 col
= pending_spaces
= 0; /* Wipe out any pending spaces. */
769 i
--; /* Push the char back; get it later. */
770 output_char (newline_character
);
772 else if (c
== space_character
)
776 /* `c' is the character after a run of spaces that were not
777 at the end of the conversion buffer. Output them. */
778 while (pending_spaces
)
780 output_char (space_character
);
788 /* Write, then empty, the output buffer `obuf'. */
793 int nwritten
= full_write (output_fd
, obuf
, output_blocksize
);
794 if (nwritten
!= output_blocksize
)
796 error (0, errno
, "%s", output_file
);
807 scanargs (int argc
, char **argv
)
812 while ((c
= getopt_long (argc
, argv
, "", long_options
, NULL
)) != -1)
824 for (i
= optind
; i
< argc
; i
++)
829 val
= strchr (name
, '=');
832 error (0, 0, _("unrecognized option `%s'"), name
);
837 if (STREQ (name
, "if"))
839 else if (STREQ (name
, "of"))
841 else if (STREQ (name
, "conv"))
842 parse_conversion (val
);
846 uintmax_t n
= parse_integer (val
, &invalid
);
848 if (STREQ (name
, "ibs"))
851 invalid
|= input_blocksize
!= n
|| input_blocksize
== 0;
852 conversions_mask
|= C_TWOBUFS
;
854 else if (STREQ (name
, "obs"))
856 output_blocksize
= n
;
857 invalid
|= output_blocksize
!= n
|| output_blocksize
== 0;
858 conversions_mask
|= C_TWOBUFS
;
860 else if (STREQ (name
, "bs"))
862 output_blocksize
= input_blocksize
= n
;
863 invalid
|= output_blocksize
!= n
|| output_blocksize
== 0;
865 else if (STREQ (name
, "cbs"))
867 conversion_blocksize
= n
;
868 invalid
|= (conversion_blocksize
!= n
869 || conversion_blocksize
== 0);
871 else if (STREQ (name
, "skip"))
873 else if (STREQ (name
, "seek"))
875 else if (STREQ (name
, "count"))
879 error (0, 0, _("unrecognized option `%s=%s'"), name
, val
);
884 error (1, 0, _("invalid number `%s'"), val
);
888 /* If bs= was given, both `input_blocksize' and `output_blocksize' will
889 have been set to positive values. If either has not been set,
890 bs= was not given, so make sure two buffers are used. */
891 if (input_blocksize
== 0 || output_blocksize
== 0)
892 conversions_mask
|= C_TWOBUFS
;
893 if (input_blocksize
== 0)
894 input_blocksize
= DEFAULT_BLOCKSIZE
;
895 if (output_blocksize
== 0)
896 output_blocksize
= DEFAULT_BLOCKSIZE
;
897 if (conversion_blocksize
== 0)
898 conversions_mask
&= ~(C_BLOCK
| C_UNBLOCK
);
901 /* Return the value of STR, interpreted as a non-negative decimal integer,
902 optionally multiplied by various values.
903 Assign nonzero to *INVALID if STR does not represent a number in
906 /* FIXME: use xstrtou?[lq] */
909 parse_integer (char *str
, int *invalid
)
911 register uintmax_t n
= 0;
912 register char *p
= str
;
916 uintmax_t n10
= n
* 10;
917 int digit
= *p
- '0';
918 if (! (n10
/ 10 == n
&& n10
<= n10
+ digit
))
929 uintmax_t multiplier
;
947 multiplier
= parse_integer (p
, invalid
);
957 if (multiplier
!= 0 && n
* multiplier
/ multiplier
!= n
)
967 /* Interpret one "conv=..." option. */
970 parse_conversion (char *str
)
977 new = strchr (str
, ',');
980 for (i
= 0; conversions
[i
].convname
!= NULL
; i
++)
981 if (STREQ (conversions
[i
].convname
, str
))
983 conversions_mask
|= conversions
[i
].conversion
;
986 if (conversions
[i
].convname
== NULL
)
988 error (0, 0, _("%s: invalid conversion"), str
);
992 } while (new != NULL
);
995 /* Fix up translation table. */
998 apply_translations (void)
1002 #define MX(a) (bit_count (conversions_mask & (a)))
1003 if ((MX (C_ASCII
| C_EBCDIC
| C_IBM
) > 1)
1004 || (MX (C_BLOCK
| C_UNBLOCK
) > 1)
1005 || (MX (C_LCASE
| C_UCASE
) > 1)
1006 || (MX (C_UNBLOCK
| C_SYNC
) > 1))
1009 only one conv in {ascii,ebcdic,ibm}, {lcase,ucase}, {block,unblock}, {unblock,sync}"));
1013 if (conversions_mask
& C_ASCII
)
1014 translate_charset (ebcdic_to_ascii
);
1016 if (conversions_mask
& C_UCASE
)
1018 for (i
= 0; i
< 256; i
++)
1019 if (ISLOWER (trans_table
[i
]))
1020 trans_table
[i
] = toupper (trans_table
[i
]);
1021 translation_needed
= 1;
1023 else if (conversions_mask
& C_LCASE
)
1025 for (i
= 0; i
< 256; i
++)
1026 if (ISUPPER (trans_table
[i
]))
1027 trans_table
[i
] = tolower (trans_table
[i
]);
1028 translation_needed
= 1;
1031 if (conversions_mask
& C_EBCDIC
)
1033 translate_charset (ascii_to_ebcdic
);
1034 newline_character
= ascii_to_ebcdic
['\n'];
1035 space_character
= ascii_to_ebcdic
[' '];
1037 else if (conversions_mask
& C_IBM
)
1039 translate_charset (ascii_to_ibm
);
1040 newline_character
= ascii_to_ibm
['\n'];
1041 space_character
= ascii_to_ibm
[' '];
1046 translate_charset (const unsigned char *new_trans
)
1050 for (i
= 0; i
< 256; i
++)
1051 trans_table
[i
] = new_trans
[trans_table
[i
]];
1052 translation_needed
= 1;
1055 /* Return the number of 1 bits in `i'. */
1058 bit_count (register unsigned int i
)
1060 register int set_bits
;
1062 for (set_bits
= 0; i
!= 0; set_bits
++)
1071 if (close (input_fd
) < 0)
1072 error (1, errno
, "%s", input_file
);
1073 if (close (output_fd
) < 0)
1074 error (1, errno
, "%s", output_file
);
1085 interrupt_handler (int sig
)
1088 struct sigaction sigact
;
1090 sigact
.sa_handler
= SIG_DFL
;
1091 sigemptyset (&sigact
.sa_mask
);
1092 sigact
.sa_flags
= 0;
1093 sigaction (sig
, &sigact
, NULL
);
1094 #else /* !SA_INTERRUPT */
1095 signal (sig
, SIG_DFL
);
1096 #endif /* SA_INTERRUPT */
1098 kill (getpid (), sig
);
1105 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
1109 printf (_("Usage: %s [OPTION]...\n"), program_name
);
1111 Copy a file, converting and formatting according to the options.\n\
1113 bs=BYTES force ibs=BYTES and obs=BYTES\n\
1114 cbs=BYTES convert BYTES bytes at a time\n\
1115 conv=KEYWORDS convert the file as per the comma separated keyword list\n\
1116 count=BLOCKS copy only BLOCKS input blocks\n\
1117 ibs=BYTES read BYTES bytes at a time\n\
1118 if=FILE read from FILE instead of stdin\n\
1119 obs=BYTES write BYTES bytes at a time\n\
1120 of=FILE write to FILE instead of stdout\n\
1121 seek=BLOCKS skip BLOCKS obs-sized blocks at start of output\n\
1122 skip=BLOCKS skip BLOCKS ibs-sized blocks at start of input\n\
1123 --help display this help and exit\n\
1124 --version output version information and exit\n\
1126 BYTES may be suffixed: by xM for multiplication by M, by c for x1,\n\
1127 by w for x2, by b for x512, by k for x1024. Each KEYWORD may be:\n\
1129 ascii from EBCDIC to ASCII\n\
1130 ebcdic from ASCII to EBCDIC\n\
1131 ibm from ASCII to alternated EBCDIC\n\
1132 block pad newline-terminated records with spaces to cbs-size\n\
1133 unblock replace trailing spaces in cbs-size records with newline\n\
1134 lcase change upper case to lower case\n\
1135 notrunc do not truncate the output file\n\
1136 ucase change lower case to upper case\n\
1137 swab swap every pair of input bytes\n\
1138 noerror continue after read errors\n\
1139 sync pad every input block with NULs to ibs-size\n\
1141 puts (_("\nReport bugs to <fileutils-bugs@gnu.org>."));