.
[coreutils.git] / src / dd.c
blob2c59bdaa2e8b1f29b3dfa26de64b934ed46f5efe
1 /* dd -- convert a file while copying it.
2 Copyright (C) 1985, 1990, 1991, 1995 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
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Written by Paul Rubin, David MacKenzie, and Stuart Kemp. */
20 /* Options:
22 Numbers can be followed by a multiplier:
23 b=512, c=1, k=1024, w=2, xm=number m
25 if=FILE Read from FILE instead of stdin.
26 of=FILE Write to FILE instead of stdout; don't
27 truncate FILE.
28 ibs=BYTES Read BYTES bytes at a time.
29 obs=BYTES Write BYTES bytes at a time.
30 bs=BYTES Override ibs and obs.
31 cbs=BYTES Convert BYTES bytes at a time.
32 skip=BLOCKS Skip BLOCKS ibs-sized blocks at
33 start of input.
34 seek=BLOCKS Skip BLOCKS obs-sized blocks at
35 start of output.
36 count=BLOCKS Copy only BLOCKS input blocks.
37 conv=CONVERSION[,CONVERSION...]
39 Conversions:
40 ascii Convert EBCDIC to ASCII.
41 ebcdic Convert ASCII to EBCDIC.
42 ibm Convert ASCII to alternate EBCDIC.
43 block Pad newline-terminated records to size of
44 cbs, replacing newline with trailing spaces.
45 unblock Replace trailing spaces in cbs-sized block
46 with newline.
47 lcase Change upper case characters to lower case.
48 ucase Change lower case characters to upper case.
49 swab Swap every pair of input bytes.
50 Unlike the Unix dd, this works when an odd
51 number of bytes are read.
52 noerror Continue after read errors.
53 sync Pad every input block to size of ibs with
54 trailing NULs. */
56 #include <config.h>
57 #include <stdio.h>
59 #define SWAB_ALIGN_OFFSET 2
61 #include <sys/types.h>
62 #include <signal.h>
63 #include <getopt.h>
65 #include "system.h"
66 #include "version.h"
67 #include "error.h"
69 #define equal(p, q) (strcmp ((p),(q)) == 0)
70 #define max(a, b) ((a) > (b) ? (a) : (b))
71 #define output_char(c) \
72 do { \
73 obuf[oc++] = (c); if (oc >= output_blocksize) write_output (); \
74 } while (0)
76 /* Default input and output blocksize. */
77 #define DEFAULT_BLOCKSIZE 512
79 /* Conversions bit masks. */
80 #define C_ASCII 01
81 #define C_EBCDIC 02
82 #define C_IBM 04
83 #define C_BLOCK 010
84 #define C_UNBLOCK 020
85 #define C_LCASE 040
86 #define C_UCASE 0100
87 #define C_SWAB 0200
88 #define C_NOERROR 0400
89 #define C_NOTRUNC 01000
90 #define C_SYNC 02000
91 /* Use separate input and output buffers, and combine partial input blocks. */
92 #define C_TWOBUFS 04000
94 char *xmalloc ();
95 int safe_read ();
96 int full_write ();
98 static RETSIGTYPE interrupt_handler __P ((int));
99 static int bit_count __P ((register unsigned int i));
100 static int parse_integer __P ((char *str));
101 static void apply_translations __P ((void));
102 static void copy __P ((void));
103 static void copy_simple __P ((unsigned char *buf, int nread));
104 static void copy_with_block __P ((unsigned char *buf, int nread));
105 static void copy_with_unblock __P ((unsigned char *buf, int nread));
106 static void parse_conversion __P ((char *str));
107 static void print_stats __P ((void));
108 static void translate_charset __P ((const unsigned char *new_trans));
109 static void quit __P ((int code));
110 static void scanargs __P ((int argc, char **argv));
111 static void skip __P ((int fdesc, char *file, long int records,
112 long int blocksize, unsigned char *buf));
113 static void usage __P ((int status));
114 static void write_output __P ((void));
116 /* The name this program was run with. */
117 char *program_name;
119 /* The name of the input file, or NULL for the standard input. */
120 static char *input_file = NULL;
122 /* The input file descriptor. */
123 static int input_fd = 0;
125 /* The name of the output file, or NULL for the standard output. */
126 static char *output_file = NULL;
128 /* The output file descriptor. */
129 static int output_fd = 1;
131 /* The number of bytes in which atomic reads are done. */
132 static long input_blocksize = -1;
134 /* The number of bytes in which atomic writes are done. */
135 static long output_blocksize = -1;
137 /* Conversion buffer size, in bytes. 0 prevents conversions. */
138 static long conversion_blocksize = 0;
140 /* Skip this many records of `input_blocksize' bytes before input. */
141 static long skip_records = 0;
143 /* Skip this many records of `output_blocksize' bytes before output. */
144 static long seek_record = 0;
146 /* Copy only this many records. <0 means no limit. */
147 static int max_records = -1;
149 /* Bit vector of conversions to apply. */
150 static int conversions_mask = 0;
152 /* If nonzero, filter characters through the translation table. */
153 static int translation_needed = 0;
155 /* Number of partial blocks written. */
156 static unsigned w_partial = 0;
158 /* Number of full blocks written. */
159 static unsigned w_full = 0;
161 /* Number of partial blocks read. */
162 static unsigned r_partial = 0;
164 /* Number of full blocks read. */
165 static unsigned r_full = 0;
167 /* Records truncated by conv=block. */
168 static unsigned r_truncate = 0;
170 /* Output representation of newline and space characters.
171 They change if we're converting to EBCDIC. */
172 static unsigned char newline_character = '\n';
173 static unsigned char space_character = ' ';
175 struct conversion
177 char *convname;
178 int conversion;
181 static struct conversion conversions[] =
183 {"ascii", C_ASCII | C_TWOBUFS}, /* EBCDIC to ASCII. */
184 {"ebcdic", C_EBCDIC | C_TWOBUFS}, /* ASCII to EBCDIC. */
185 {"ibm", C_IBM | C_TWOBUFS}, /* Slightly different ASCII to EBCDIC. */
186 {"block", C_BLOCK | C_TWOBUFS}, /* Variable to fixed length records. */
187 {"unblock", C_UNBLOCK | C_TWOBUFS}, /* Fixed to variable length records. */
188 {"lcase", C_LCASE | C_TWOBUFS}, /* Translate upper to lower case. */
189 {"ucase", C_UCASE | C_TWOBUFS}, /* Translate lower to upper case. */
190 {"swab", C_SWAB | C_TWOBUFS}, /* Swap bytes of input. */
191 {"noerror", C_NOERROR}, /* Ignore i/o errors. */
192 {"notrunc", C_NOTRUNC}, /* Do not truncate output file. */
193 {"sync", C_SYNC}, /* Pad input records to ibs with NULs. */
194 {NULL, 0}
197 /* Translation table formed by applying successive transformations. */
198 static unsigned char trans_table[256];
200 static unsigned char const ascii_to_ebcdic[] =
202 0, 01, 02, 03, 067, 055, 056, 057,
203 026, 05, 045, 013, 014, 015, 016, 017,
204 020, 021, 022, 023, 074, 075, 062, 046,
205 030, 031, 077, 047, 034, 035, 036, 037,
206 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175,
207 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
208 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
209 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
210 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
211 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
212 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
213 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155,
214 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
215 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
216 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
217 0247, 0250, 0251, 0300, 0152, 0320, 0241, 07,
218 040, 041, 042, 043, 044, 025, 06, 027,
219 050, 051, 052, 053, 054, 011, 012, 033,
220 060, 061, 032, 063, 064, 065, 066, 010,
221 070, 071, 072, 073, 04, 024, 076, 0341,
222 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
223 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
224 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
225 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
226 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
227 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
228 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
229 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
230 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
231 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
232 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
233 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
236 static unsigned char const ascii_to_ibm[] =
238 0, 01, 02, 03, 067, 055, 056, 057,
239 026, 05, 045, 013, 014, 015, 016, 017,
240 020, 021, 022, 023, 074, 075, 062, 046,
241 030, 031, 077, 047, 034, 035, 036, 037,
242 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175,
243 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141,
244 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
245 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157,
246 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
247 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326,
248 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346,
249 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155,
250 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
251 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226,
252 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246,
253 0247, 0250, 0251, 0300, 0117, 0320, 0241, 07,
254 040, 041, 042, 043, 044, 025, 06, 027,
255 050, 051, 052, 053, 054, 011, 012, 033,
256 060, 061, 032, 063, 064, 065, 066, 010,
257 070, 071, 072, 073, 04, 024, 076, 0341,
258 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110,
259 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
260 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147,
261 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165,
262 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215,
263 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236,
264 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257,
265 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
266 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
267 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333,
268 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355,
269 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377
272 static unsigned char const ebcdic_to_ascii[] =
274 0, 01, 02, 03, 0234, 011, 0206, 0177,
275 0227, 0215, 0216, 013, 014, 015, 016, 017,
276 020, 021, 022, 023, 0235, 0205, 010, 0207,
277 030, 031, 0222, 0217, 034, 035, 036, 037,
278 0200, 0201, 0202, 0203, 0204, 012, 027, 033,
279 0210, 0211, 0212, 0213, 0214, 05, 06, 07,
280 0220, 0221, 026, 0223, 0224, 0225, 0226, 04,
281 0230, 0231, 0232, 0233, 024, 025, 0236, 032,
282 040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
283 0247, 0250, 0133, 056, 074, 050, 053, 041,
284 046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
285 0260, 0261, 0135, 044, 052, 051, 073, 0136,
286 055, 057, 0262, 0263, 0264, 0265, 0266, 0267,
287 0270, 0271, 0174, 054, 045, 0137, 076, 077,
288 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
289 0302, 0140, 072, 043, 0100, 047, 075, 042,
290 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
291 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
292 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
293 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320,
294 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170,
295 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327,
296 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
297 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
298 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
299 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
300 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
301 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
302 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
303 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
304 060, 061, 062, 063, 064, 065, 066, 067,
305 070, 071, 0372, 0373, 0374, 0375, 0376, 0377
308 /* If nonzero, display usage information and exit. */
309 static int show_help;
311 /* If nonzero, print the version on standard output and exit. */
312 static int show_version;
314 static struct option const long_options[] =
316 {"help", no_argument, &show_help, 1},
317 {"version", no_argument, &show_version, 1},
318 {0, 0, 0, 0}
321 void
322 main (int argc, char **argv)
324 #ifdef _POSIX_VERSION
325 struct sigaction sigact;
326 #endif /* _POSIX_VERSION */
327 int i;
329 program_name = argv[0];
330 setlocale (LC_ALL, "");
331 bindtextdomain (PACKAGE, LOCALEDIR);
332 textdomain (PACKAGE);
334 /* Initialize translation table to identity translation. */
335 for (i = 0; i < 256; i++)
336 trans_table[i] = i;
338 /* Decode arguments. */
339 scanargs (argc, argv);
341 if (show_version)
343 printf ("dd - %s\n", version_string);
344 exit (0);
347 if (show_help)
348 usage (0);
350 apply_translations ();
352 if (input_file != NULL)
354 input_fd = open (input_file, O_RDONLY);
355 if (input_fd < 0)
356 error (1, errno, "%s", input_file);
358 else
359 input_file = _("standard input");
361 if (input_fd == output_fd)
362 error (1, 0, _("%s is closed"), (input_fd == 0
363 ? _("standard input")
364 : _("standard output")));
366 if (output_file != NULL)
368 int omode = O_RDWR | O_CREAT;
370 if (seek_record == 0 && !(conversions_mask & C_NOTRUNC))
371 omode |= O_TRUNC;
372 output_fd = open (output_file, omode, 0666);
373 if (output_fd < 0)
374 error (1, errno, "%s", output_file);
375 #ifdef HAVE_FTRUNCATE
376 if (seek_record > 0 && !(conversions_mask & C_NOTRUNC))
378 if (ftruncate (output_fd, seek_record * output_blocksize) < 0)
379 error (0, errno, "%s", output_file);
381 #endif
383 else
384 output_file = _("standard output");
386 #ifdef _POSIX_VERSION
387 sigaction (SIGINT, NULL, &sigact);
388 if (sigact.sa_handler != SIG_IGN)
390 sigact.sa_handler = interrupt_handler;
391 sigemptyset (&sigact.sa_mask);
392 sigact.sa_flags = 0;
393 sigaction (SIGINT, &sigact, NULL);
395 sigaction (SIGPIPE, NULL, &sigact);
396 if (sigact.sa_handler != SIG_IGN)
398 sigact.sa_handler = interrupt_handler;
399 sigemptyset (&sigact.sa_mask);
400 sigact.sa_flags = 0;
401 sigaction (SIGPIPE, &sigact, NULL);
403 #else /* !_POSIX_VERSION */
404 if (signal (SIGINT, SIG_IGN) != SIG_IGN)
405 signal (SIGINT, interrupt_handler);
406 if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
407 signal (SIGPIPE, interrupt_handler);
408 #endif /* !_POSIX_VERSION */
409 copy ();
412 /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
413 which is open with read permission for FILE. Store up to BLOCKSIZE
414 bytes of the data at a time in BUF, if necessary. */
416 static void
417 skip (int fdesc, char *file, long int records, long int blocksize,
418 unsigned char *buf)
420 struct stat stats;
422 /* Use fstat instead of checking for errno == ESPIPE because
423 lseek doesn't work on some special files but doesn't return an
424 error, either. */
425 /* FIXME: can this really happen? What system? */
426 if (fstat (fdesc, &stats))
428 error (0, errno, "%s", file);
429 quit (1);
432 /* FIXME: why use lseek only on regular files?
433 Better: try lseek and if an error indicates it was an inappropriate
434 operation, fall back on using read. */
435 if (S_ISREG (stats.st_mode))
437 if (lseek (fdesc, records * blocksize, SEEK_SET) < 0)
439 error (0, errno, "%s", file);
440 quit (1);
443 else
445 while (records-- > 0)
447 int nread;
449 nread = safe_read (fdesc, buf, blocksize);
450 if (nread < 0)
452 error (0, errno, "%s", file);
453 quit (1);
455 /* POSIX doesn't say what to do when dd detects it has been
456 asked to skip past EOF, so I assume it's non-fatal.
457 FIXME: maybe give a warning. */
458 if (nread == 0)
459 break;
464 /* Apply the character-set translations specified by the user
465 to the NREAD bytes in BUF. */
467 static void
468 translate_buffer (unsigned char *buf, int nread)
470 register unsigned char *cp;
471 register int i;
473 for (i = nread, cp = buf; i; i--, cp++)
474 *cp = trans_table[*cp];
477 /* If nonnzero, the last char from the previous call to `swab_buffer'
478 is saved in `saved_char'. */
479 static int char_is_saved = 0;
481 /* Odd char from previous call. */
482 static unsigned char saved_char;
484 /* Swap NREAD bytes in BUF, plus possibly an initial char from the
485 previous call. If NREAD is odd, save the last char for the
486 next call. Return the new start of the BUF buffer. */
488 static unsigned char *
489 swab_buffer (unsigned char *buf, int *nread)
491 unsigned char *bufstart = buf;
492 register unsigned char *cp;
493 register int i;
495 /* Is a char left from last time? */
496 if (char_is_saved)
498 *--bufstart = saved_char;
499 (*nread)++;
500 char_is_saved = 0;
503 if (*nread & 1)
505 /* An odd number of chars are in the buffer. */
506 saved_char = bufstart[--*nread];
507 char_is_saved = 1;
510 /* Do the byte-swapping by moving every second character two
511 positions toward the end, working from the end of the buffer
512 toward the beginning. This way we only move half of the data. */
514 cp = bufstart + *nread; /* Start one char past the last. */
515 for (i = *nread / 2; i; i--, cp -= 2)
516 *cp = *(cp - 2);
518 return ++bufstart;
521 /* Output buffer. */
522 static unsigned char *obuf;
524 /* Current index into `obuf'. */
525 static int oc = 0;
527 /* Index into current line, for `conv=block' and `conv=unblock'. */
528 static int col = 0;
530 /* The main loop. */
532 static void
533 copy (void)
535 unsigned char *ibuf, *bufstart; /* Input buffer. */
536 int nread; /* Bytes read in the current block. */
537 int exit_status = 0;
539 /* Leave at least one extra byte at the beginning and end of `ibuf'
540 for conv=swab, but keep the buffer address even. But some peculiar
541 device drivers work only with word-aligned buffers, so leave an
542 extra two bytes. */
544 ibuf = (unsigned char *) xmalloc (input_blocksize + 2 * SWAB_ALIGN_OFFSET);
545 ibuf += SWAB_ALIGN_OFFSET;
547 if (conversions_mask & C_TWOBUFS)
548 obuf = (unsigned char *) xmalloc (output_blocksize);
549 else
550 obuf = ibuf;
552 if (skip_records > 0)
553 skip (input_fd, input_file, skip_records, input_blocksize, ibuf);
555 if (seek_record > 0)
556 skip (output_fd, output_file, seek_record, output_blocksize, obuf);
558 if (max_records == 0)
559 quit (exit_status);
561 while (1)
563 if (max_records >= 0 && r_partial + r_full >= max_records)
564 break;
566 /* Zero the buffer before reading, so that if we get a read error,
567 whatever data we are able to read is followed by zeros.
568 This minimizes data loss. */
569 if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
570 memset ((char *) ibuf, 0, input_blocksize);
572 nread = safe_read (input_fd, ibuf, input_blocksize);
574 if (nread == 0)
575 break; /* EOF. */
577 if (nread < 0)
579 error (0, errno, "%s", input_file);
580 if (conversions_mask & C_NOERROR)
582 print_stats ();
583 /* Seek past the bad block if possible. */
584 lseek (input_fd, input_blocksize, SEEK_CUR);
585 if (conversions_mask & C_SYNC)
586 /* Replace the missing input with null bytes and
587 proceed normally. */
588 nread = 0;
589 else
590 continue;
592 else
594 /* Write any partial block. */
595 exit_status = 2;
596 break;
600 if (nread < input_blocksize)
602 r_partial++;
603 if (conversions_mask & C_SYNC)
605 if (!(conversions_mask & C_NOERROR))
606 /* If C_NOERROR, we zeroed the block before reading. */
607 memset ((char *) (ibuf + nread), 0, input_blocksize - nread);
608 nread = input_blocksize;
611 else
612 r_full++;
614 if (ibuf == obuf) /* If not C_TWOBUFS. */
616 int nwritten = full_write (output_fd, obuf, nread);
617 if (nwritten < 0)
619 error (0, errno, "%s", output_file);
620 quit (1);
622 else if (nread == input_blocksize)
623 w_full++;
624 else
625 w_partial++;
626 continue;
629 /* Do any translations on the whole buffer at once. */
631 if (translation_needed)
632 translate_buffer (ibuf, nread);
634 if (conversions_mask & C_SWAB)
635 bufstart = swab_buffer (ibuf, &nread);
636 else
637 bufstart = ibuf;
639 if (conversions_mask & C_BLOCK)
640 copy_with_block (bufstart, nread);
641 else if (conversions_mask & C_UNBLOCK)
642 copy_with_unblock (bufstart, nread);
643 else
644 copy_simple (bufstart, nread);
647 /* If we have a char left as a result of conv=swab, output it. */
648 if (char_is_saved)
650 if (conversions_mask & C_BLOCK)
651 copy_with_block (&saved_char, 1);
652 else if (conversions_mask & C_UNBLOCK)
653 copy_with_unblock (&saved_char, 1);
654 else
655 output_char (saved_char);
658 if ((conversions_mask & C_BLOCK) && col > 0)
660 /* If the final input line didn't end with a '\n', pad
661 the output block to `conversion_blocksize' chars. */
662 int pending_spaces = max (0, conversion_blocksize - col);
663 while (pending_spaces)
665 output_char (space_character);
666 --pending_spaces;
670 if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
671 /* Add a final '\n' if there are exactly `conversion_blocksize'
672 characters in the final record. */
673 output_char (newline_character);
675 /* Write out the last block. */
676 if (oc > 0)
678 int nwritten = full_write (output_fd, obuf, oc);
679 if (nwritten > 0)
680 w_partial++;
681 if (nwritten < 0)
683 error (0, errno, "%s", output_file);
684 quit (1);
688 free (ibuf - SWAB_ALIGN_OFFSET);
689 if (obuf != ibuf)
690 free (obuf);
692 quit (exit_status);
695 /* Copy NREAD bytes of BUF, with no conversions. */
697 static void
698 copy_simple (unsigned char *buf, int nread)
700 int nfree; /* Number of unused bytes in `obuf'. */
701 unsigned char *start = buf; /* First uncopied char in BUF. */
705 nfree = output_blocksize - oc;
706 if (nfree > nread)
707 nfree = nread;
709 memcpy ((char *) (obuf + oc), (char *) start, nfree);
711 nread -= nfree; /* Update the number of bytes left to copy. */
712 start += nfree;
713 oc += nfree;
714 if (oc >= output_blocksize)
715 write_output ();
717 while (nread > 0);
720 /* Copy NREAD bytes of BUF, doing conv=block
721 (pad newline-terminated records to `conversion_blocksize',
722 replacing the newline with trailing spaces). */
724 static void
725 copy_with_block (unsigned char *buf, int nread)
727 register int i;
729 for (i = nread; i; i--, buf++)
731 if (*buf == newline_character)
733 int pending_spaces = max (0, conversion_blocksize - col);
734 while (pending_spaces)
736 output_char (space_character);
737 --pending_spaces;
739 col = 0;
741 else
743 if (col == conversion_blocksize)
744 r_truncate++;
745 else if (col < conversion_blocksize)
746 output_char (*buf);
747 col++;
752 /* Copy NREAD bytes of BUF, doing conv=unblock
753 (replace trailing spaces in `conversion_blocksize'-sized records
754 with a newline). */
756 static void
757 copy_with_unblock (unsigned char *buf, int nread)
759 register int i;
760 register unsigned char c;
761 static int pending_spaces = 0;
763 for (i = 0; i < nread; i++)
765 c = buf[i];
767 if (col++ >= conversion_blocksize)
769 col = pending_spaces = 0; /* Wipe out any pending spaces. */
770 i--; /* Push the char back; get it later. */
771 output_char (newline_character);
773 else if (c == space_character)
774 pending_spaces++;
775 else
777 /* `c' is the character after a run of spaces that were not
778 at the end of the conversion buffer. Output them. */
779 while (pending_spaces)
781 output_char (space_character);
782 --pending_spaces;
784 output_char (c);
789 /* Write, then empty, the output buffer `obuf'. */
791 static void
792 write_output (void)
794 int nwritten = full_write (output_fd, obuf, output_blocksize);
795 if (nwritten != output_blocksize)
797 error (0, errno, "%s", output_file);
798 if (nwritten > 0)
799 w_partial++;
800 quit (1);
802 else
803 w_full++;
804 oc = 0;
807 static void
808 scanargs (int argc, char **argv)
810 int i, n;
811 int c;
813 while ((c = getopt_long (argc, argv, "", long_options, (int *) 0)) != EOF)
815 switch (c)
817 case 0:
818 break;
820 default:
821 usage (1);
825 for (i = optind; i < argc; i++)
827 char *name, *val;
829 name = argv[i];
830 val = strchr (name, '=');
831 if (val == NULL)
833 error (0, 0, _("unrecognized option `%s'"), name);
834 usage (1);
836 *val++ = '\0';
838 if (equal (name, "if"))
839 input_file = val;
840 else if (equal (name, "of"))
841 output_file = val;
842 else if (equal (name, "conv"))
843 parse_conversion (val);
844 else
846 n = parse_integer (val);
847 if (n < 0)
848 error (1, 0, _("invalid number `%s'"), val);
850 if (equal (name, "ibs"))
852 input_blocksize = n;
853 conversions_mask |= C_TWOBUFS;
855 else if (equal (name, "obs"))
857 output_blocksize = n;
858 conversions_mask |= C_TWOBUFS;
860 else if (equal (name, "bs"))
861 output_blocksize = input_blocksize = n;
862 else if (equal (name, "cbs"))
863 conversion_blocksize = n;
864 else if (equal (name, "skip"))
865 skip_records = n;
866 else if (equal (name, "seek"))
867 seek_record = n;
868 else if (equal (name, "count"))
869 max_records = n;
870 else
872 error (0, 0, _("unrecognized option `%s=%s'"), name, val);
873 usage (1);
878 /* If bs= was given, both `input_blocksize' and `output_blocksize' will
879 have been set to non-negative values. If either has not been set,
880 bs= was not given, so make sure two buffers are used. */
881 if (input_blocksize == -1 || output_blocksize == -1)
882 conversions_mask |= C_TWOBUFS;
883 if (input_blocksize == -1)
884 input_blocksize = DEFAULT_BLOCKSIZE;
885 if (output_blocksize == -1)
886 output_blocksize = DEFAULT_BLOCKSIZE;
887 if (conversion_blocksize == 0)
888 conversions_mask &= ~(C_BLOCK | C_UNBLOCK);
891 /* Return the value of STR, interpreted as a non-negative decimal integer,
892 optionally multiplied by various values.
893 Return -1 if STR does not represent a number in this format. */
895 /* FIXME: use xstrtou?l */
897 static int
898 parse_integer (char *str)
900 register int n = 0;
901 register int temp;
902 register char *p = str;
904 while (ISDIGIT (*p))
906 n = n * 10 + *p - '0';
907 p++;
909 loop:
910 switch (*p++)
912 case '\0':
913 return n;
914 case 'b':
915 n *= 512;
916 goto loop;
917 case 'c':
918 goto loop;
919 case 'k':
920 n *= 1024;
921 goto loop;
922 case 'w':
923 n *= 2;
924 goto loop;
925 case 'x':
926 temp = parse_integer (p);
927 if (temp == -1)
928 return -1;
929 n *= temp;
930 break;
931 default:
932 return -1;
934 return n;
937 /* Interpret one "conv=..." option. */
939 static void
940 parse_conversion (char *str)
942 char *new;
943 int i;
947 new = strchr (str, ',');
948 if (new != NULL)
949 *new++ = '\0';
950 for (i = 0; conversions[i].convname != NULL; i++)
951 if (equal (conversions[i].convname, str))
953 conversions_mask |= conversions[i].conversion;
954 break;
956 if (conversions[i].convname == NULL)
958 error (0, 0, _("%s: invalid conversion"), str);
959 usage (1);
961 str = new;
962 } while (new != NULL);
965 /* Fix up translation table. */
967 static void
968 apply_translations (void)
970 int i;
972 #define MX(a) (bit_count (conversions_mask & (a)))
973 if ((MX (C_ASCII | C_EBCDIC | C_IBM) > 1)
974 || (MX (C_BLOCK | C_UNBLOCK) > 1)
975 || (MX (C_LCASE | C_UCASE) > 1)
976 || (MX (C_UNBLOCK | C_SYNC) > 1))
978 error (1, 0, _("\
979 only one conv in {ascii,ebcdic,ibm}, {lcase,ucase}, {block,unblock}, {unblock,sync}"));
981 #undef MX
983 if (conversions_mask & C_ASCII)
984 translate_charset (ebcdic_to_ascii);
986 if (conversions_mask & C_UCASE)
988 for (i = 0; i < 256; i++)
989 if (ISLOWER (trans_table[i]))
990 trans_table[i] = toupper (trans_table[i]);
991 translation_needed = 1;
993 else if (conversions_mask & C_LCASE)
995 for (i = 0; i < 256; i++)
996 if (ISUPPER (trans_table[i]))
997 trans_table[i] = tolower (trans_table[i]);
998 translation_needed = 1;
1001 if (conversions_mask & C_EBCDIC)
1003 translate_charset (ascii_to_ebcdic);
1004 newline_character = ascii_to_ebcdic['\n'];
1005 space_character = ascii_to_ebcdic[' '];
1007 else if (conversions_mask & C_IBM)
1009 translate_charset (ascii_to_ibm);
1010 newline_character = ascii_to_ibm['\n'];
1011 space_character = ascii_to_ibm[' '];
1015 static void
1016 translate_charset (const unsigned char *new_trans)
1018 int i;
1020 for (i = 0; i < 256; i++)
1021 trans_table[i] = new_trans[trans_table[i]];
1022 translation_needed = 1;
1025 /* Return the number of 1 bits in `i'. */
1027 static int
1028 bit_count (register unsigned int i)
1030 register int set_bits;
1032 for (set_bits = 0; i != 0; set_bits++)
1033 i &= i - 1;
1034 return set_bits;
1037 static void
1038 print_stats (void)
1040 fprintf (stderr, _("%u+%u records in\n"), r_full, r_partial);
1041 fprintf (stderr, _("%u+%u records out\n"), w_full, w_partial);
1042 if (r_truncate > 0)
1043 fprintf (stderr, _("%u truncated record%s\n"), r_truncate,
1044 r_truncate == 1 ? "" : "s");
1047 static void
1048 cleanup (void)
1050 print_stats ();
1051 if (close (input_fd) < 0)
1052 error (1, errno, "%s", input_file);
1053 if (close (output_fd) < 0)
1054 error (1, errno, "%s", output_file);
1057 static void
1058 quit (int code)
1060 cleanup ();
1061 exit (code);
1064 static RETSIGTYPE
1065 interrupt_handler (int sig)
1067 #ifdef SA_INTERRUPT
1068 struct sigaction sigact;
1070 sigact.sa_handler = SIG_DFL;
1071 sigemptyset (&sigact.sa_mask);
1072 sigact.sa_flags = 0;
1073 sigaction (sig, &sigact, NULL);
1074 #else /* !SA_INTERRUPT */
1075 signal (sig, SIG_DFL);
1076 #endif /* SA_INTERRUPT */
1077 cleanup ();
1078 kill (getpid (), sig);
1081 static void
1082 usage (int status)
1084 if (status != 0)
1085 fprintf (stderr, _("Try `%s --help' for more information.\n"),
1086 program_name);
1087 else
1089 printf (_("Usage: %s [OPTION]...\n"), program_name);
1090 printf (_("\
1091 Copy a file, converting and formatting according to the options.\n\
1093 bs=BYTES force ibs=BYTES and obs=BYTES\n\
1094 cbs=BYTES convert BYTES bytes at a time\n\
1095 conv=KEYWORDS convert the file as per the comma separated keyword list\n\
1096 count=BLOCKS copy only BLOCKS input blocks\n\
1097 ibs=BYTES read BYTES bytes at a time\n\
1098 if=FILE read from FILE instead of stdin\n\
1099 obs=BYTES write BYTES bytes at a time\n\
1100 of=FILE write to FILE instead of stdout, don't truncate file\n\
1101 seek=BLOCKS skip BLOCKS obs-sized blocks at start of output\n\
1102 skip=BLOCKS skip BLOCKS ibs-sized blocks at start of input\n\
1103 --help display this help and exit\n\
1104 --version output version information and exit\n\
1106 BYTES may be suffixed: by xM for multiplication by M, by c for x1,\n\
1107 by w for x2, by b for x512, by k for x1024. Each KEYWORD may be:\n\
1109 ascii from EBCDIC to ASCII\n\
1110 ebcdic from ASCII to EBCDIC\n\
1111 ibm from ASCII to alternated EBCDIC\n\
1112 block pad newline-terminated records with spaces to cbs-size \n\
1113 unblock replace trailing spaces in cbs-size records with newline\n\
1114 lcase change upper case to lower case\n\
1115 ucase change lower case to upper case\n\
1116 swab swap every pair of input bytes\n\
1117 noerror continue after read errors\n\
1118 sync pad every input block with NULs to ibs-size\n"));
1120 exit (status);