LCOV - code coverage report
Current view: top level - src - dd.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 298 560 53.2 %
Date: 2018-01-30 Functions: 21 32 65.6 %

          Line data    Source code
       1             : /* dd -- convert a file while copying it.
       2             :    Copyright (C) 85, 90, 91, 1995-2008 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 3 of the License, or
       7             :    (at your option) 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, see <http://www.gnu.org/licenses/>.  */
      16             : 
      17             : /* Written by Paul Rubin, David MacKenzie, and Stuart Kemp. */
      18             : 
      19             : #include <config.h>
      20             : 
      21             : #define SWAB_ALIGN_OFFSET 2
      22             : 
      23             : #include <sys/types.h>
      24             : #include <signal.h>
      25             : #include <getopt.h>
      26             : 
      27             : #include "system.h"
      28             : #include "error.h"
      29             : #include "fd-reopen.h"
      30             : #include "gethrxtime.h"
      31             : #include "human.h"
      32             : #include "long-options.h"
      33             : #include "quote.h"
      34             : #include "quotearg.h"
      35             : #include "xstrtol.h"
      36             : #include "xtime.h"
      37             : 
      38             : static void process_signals (void);
      39             : 
      40             : /* The official name of this program (e.g., no `g' prefix).  */
      41             : #define PROGRAM_NAME "dd"
      42             : 
      43             : #define AUTHORS "Paul Rubin", "David MacKenzie", "Stuart Kemp"
      44             : 
      45             : /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
      46             :    present.  SA_NODEFER and SA_RESETHAND are XSI extensions.  */
      47             : #ifndef SA_NOCLDSTOP
      48             : # define SA_NOCLDSTOP 0
      49             : # define sigprocmask(How, Set, Oset) /* empty */
      50             : # define sigset_t int
      51             : # if ! HAVE_SIGINTERRUPT
      52             : #  define siginterrupt(sig, flag) /* empty */
      53             : # endif
      54             : #endif
      55             : #ifndef SA_NODEFER
      56             : # define SA_NODEFER 0
      57             : #endif
      58             : #ifndef SA_RESETHAND
      59             : # define SA_RESETHAND 0
      60             : #endif
      61             : 
      62             : #ifndef SIGINFO
      63             : # define SIGINFO SIGUSR1
      64             : #endif
      65             : 
      66             : #if ! HAVE_FDATASYNC
      67             : # define fdatasync(fd) (errno = ENOSYS, -1)
      68             : #endif
      69             : 
      70             : #define max(a, b) ((a) > (b) ? (a) : (b))
      71             : #define output_char(c)                          \
      72             :   do                                            \
      73             :     {                                           \
      74             :       obuf[oc++] = (c);                         \
      75             :       if (oc >= output_blocksize)            \
      76             :         write_output ();                        \
      77             :     }                                           \
      78             :   while (0)
      79             : 
      80             : /* Default input and output blocksize. */
      81             : #define DEFAULT_BLOCKSIZE 512
      82             : 
      83             : /* How many bytes to add to the input and output block sizes before invoking
      84             :    malloc.  See dd_copy for details.  INPUT_BLOCK_SLOP must be no less than
      85             :    OUTPUT_BLOCK_SLOP.  */
      86             : #define INPUT_BLOCK_SLOP (2 * SWAB_ALIGN_OFFSET + 2 * page_size - 1)
      87             : #define OUTPUT_BLOCK_SLOP (page_size - 1)
      88             : 
      89             : /* Maximum blocksize for the given SLOP.
      90             :    Keep it smaller than SIZE_MAX - SLOP, so that we can
      91             :    allocate buffers that size.  Keep it smaller than SSIZE_MAX, for
      92             :    the benefit of system calls like "read".  And keep it smaller than
      93             :    OFF_T_MAX, for the benefit of the large-offset seek code.  */
      94             : #define MAX_BLOCKSIZE(slop) MIN (SIZE_MAX - (slop), MIN (SSIZE_MAX, OFF_T_MAX))
      95             : 
      96             : /* Conversions bit masks. */
      97             : enum
      98             :   {
      99             :     C_ASCII = 01,
     100             : 
     101             :     C_EBCDIC = 02,
     102             :     C_IBM = 04,
     103             :     C_BLOCK = 010,
     104             :     C_UNBLOCK = 020,
     105             :     C_LCASE = 040,
     106             :     C_UCASE = 0100,
     107             :     C_SWAB = 0200,
     108             :     C_NOERROR = 0400,
     109             :     C_NOTRUNC = 01000,
     110             :     C_SYNC = 02000,
     111             : 
     112             :     /* Use separate input and output buffers, and combine partial
     113             :        input blocks. */
     114             :     C_TWOBUFS = 04000,
     115             : 
     116             :     C_NOCREAT = 010000,
     117             :     C_EXCL = 020000,
     118             :     C_FDATASYNC = 040000,
     119             :     C_FSYNC = 0100000
     120             :   };
     121             : 
     122             : /* Status bit masks.  */
     123             : enum
     124             :   {
     125             :     STATUS_NOXFER = 01
     126             :   };
     127             : 
     128             : /* The name this program was run with. */
     129             : char *program_name;
     130             : 
     131             : /* The name of the input file, or NULL for the standard input. */
     132             : static char const *input_file = NULL;
     133             : 
     134             : /* The name of the output file, or NULL for the standard output. */
     135             : static char const *output_file = NULL;
     136             : 
     137             : /* The page size on this host.  */
     138             : static size_t page_size;
     139             : 
     140             : /* The number of bytes in which atomic reads are done. */
     141             : static size_t input_blocksize = 0;
     142             : 
     143             : /* The number of bytes in which atomic writes are done. */
     144             : static size_t output_blocksize = 0;
     145             : 
     146             : /* Conversion buffer size, in bytes.  0 prevents conversions. */
     147             : static size_t conversion_blocksize = 0;
     148             : 
     149             : /* Skip this many records of `input_blocksize' bytes before input. */
     150             : static uintmax_t skip_records = 0;
     151             : 
     152             : /* Skip this many records of `output_blocksize' bytes before output. */
     153             : static uintmax_t seek_records = 0;
     154             : 
     155             : /* Copy only this many records.  The default is effectively infinity.  */
     156             : static uintmax_t max_records = (uintmax_t) -1;
     157             : 
     158             : /* Bit vector of conversions to apply. */
     159             : static int conversions_mask = 0;
     160             : 
     161             : /* Open flags for the input and output files.  */
     162             : static int input_flags = 0;
     163             : static int output_flags = 0;
     164             : 
     165             : /* Status flags for what is printed to stderr.  */
     166             : static int status_flags = 0;
     167             : 
     168             : /* If nonzero, filter characters through the translation table.  */
     169             : static bool translation_needed = false;
     170             : 
     171             : /* Number of partial blocks written. */
     172             : static uintmax_t w_partial = 0;
     173             : 
     174             : /* Number of full blocks written. */
     175             : static uintmax_t w_full = 0;
     176             : 
     177             : /* Number of partial blocks read. */
     178             : static uintmax_t r_partial = 0;
     179             : 
     180             : /* Number of full blocks read. */
     181             : static uintmax_t r_full = 0;
     182             : 
     183             : /* Number of bytes written.  */
     184             : static uintmax_t w_bytes = 0;
     185             : 
     186             : /* Time that dd started.  */
     187             : static xtime_t start_time;
     188             : 
     189             : /* True if input is seekable.  */
     190             : static bool input_seekable;
     191             : 
     192             : /* Error number corresponding to initial attempt to lseek input.
     193             :    If ESPIPE, do not issue any more diagnostics about it.  */
     194             : static int input_seek_errno;
     195             : 
     196             : /* File offset of the input, in bytes, along with a flag recording
     197             :    whether it overflowed.  The offset is valid only if the input is
     198             :    seekable and if the offset has not overflowed.  */
     199             : static uintmax_t input_offset;
     200             : static bool input_offset_overflow;
     201             : 
     202             : /* Records truncated by conv=block. */
     203             : static uintmax_t r_truncate = 0;
     204             : 
     205             : /* Output representation of newline and space characters.
     206             :    They change if we're converting to EBCDIC.  */
     207             : static char newline_character = '\n';
     208             : static char space_character = ' ';
     209             : 
     210             : /* Output buffer. */
     211             : static char *obuf;
     212             : 
     213             : /* Current index into `obuf'. */
     214             : static size_t oc = 0;
     215             : 
     216             : /* Index into current line, for `conv=block' and `conv=unblock'.  */
     217             : static size_t col = 0;
     218             : 
     219             : /* The set of signals that are caught.  */
     220             : static sigset_t caught_signals;
     221             : 
     222             : /* If nonzero, the value of the pending fatal signal.  */
     223             : static sig_atomic_t volatile interrupt_signal;
     224             : 
     225             : /* A count of the number of pending info signals that have been received.  */
     226             : static sig_atomic_t volatile info_signal_count;
     227             : 
     228             : /* A longest symbol in the struct symbol_values tables below.  */
     229             : #define LONGEST_SYMBOL "fdatasync"
     230             : 
     231             : /* A symbol and the corresponding integer value.  */
     232             : struct symbol_value
     233             : {
     234             :   char symbol[sizeof LONGEST_SYMBOL];
     235             :   int value;
     236             : };
     237             : 
     238             : /* Conversion symbols, for conv="...".  */
     239             : static struct symbol_value const conversions[] =
     240             : {
     241             :   {"ascii", C_ASCII | C_TWOBUFS},     /* EBCDIC to ASCII. */
     242             :   {"ebcdic", C_EBCDIC | C_TWOBUFS},   /* ASCII to EBCDIC. */
     243             :   {"ibm", C_IBM | C_TWOBUFS}, /* Slightly different ASCII to EBCDIC. */
     244             :   {"block", C_BLOCK | C_TWOBUFS},     /* Variable to fixed length records. */
     245             :   {"unblock", C_UNBLOCK | C_TWOBUFS}, /* Fixed to variable length records. */
     246             :   {"lcase", C_LCASE | C_TWOBUFS},     /* Translate upper to lower case. */
     247             :   {"ucase", C_UCASE | C_TWOBUFS},     /* Translate lower to upper case. */
     248             :   {"swab", C_SWAB | C_TWOBUFS},       /* Swap bytes of input. */
     249             :   {"noerror", C_NOERROR},     /* Ignore i/o errors. */
     250             :   {"nocreat", C_NOCREAT},     /* Do not create output file.  */
     251             :   {"excl", C_EXCL},           /* Fail if the output file already exists.  */
     252             :   {"notrunc", C_NOTRUNC},     /* Do not truncate output file. */
     253             :   {"sync", C_SYNC},           /* Pad input records to ibs with NULs. */
     254             :   {"fdatasync", C_FDATASYNC}, /* Synchronize output data before finishing.  */
     255             :   {"fsync", C_FSYNC},         /* Also synchronize output metadata.  */
     256             :   {"", 0}
     257             : };
     258             : 
     259             : /* Flags, for iflag="..." and oflag="...".  */
     260             : static struct symbol_value const flags[] =
     261             : {
     262             :   {"append",  O_APPEND},
     263             :   {"binary",  O_BINARY},
     264             :   {"direct",  O_DIRECT},
     265             :   {"directory",       O_DIRECTORY},
     266             :   {"dsync",   O_DSYNC},
     267             :   {"noatime", O_NOATIME},
     268             :   {"noctty",  O_NOCTTY},
     269             :   {"nofollow",        HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0},
     270             :   {"nolinks", O_NOLINKS},
     271             :   {"nonblock",        O_NONBLOCK},
     272             :   {"sync",    O_SYNC},
     273             :   {"text",    O_TEXT},
     274             :   {"",                0}
     275             : };
     276             : 
     277             : /* Status, for status="...".  */
     278             : static struct symbol_value const statuses[] =
     279             : {
     280             :   {"noxfer",  STATUS_NOXFER},
     281             :   {"",                0}
     282             : };
     283             : 
     284             : /* Translation table formed by applying successive transformations. */
     285             : static unsigned char trans_table[256];
     286             : 
     287             : static char const ascii_to_ebcdic[] =
     288             : {
     289             :   '\000', '\001', '\002', '\003', '\067', '\055', '\056', '\057',
     290             :   '\026', '\005', '\045', '\013', '\014', '\015', '\016', '\017',
     291             :   '\020', '\021', '\022', '\023', '\074', '\075', '\062', '\046',
     292             :   '\030', '\031', '\077', '\047', '\034', '\035', '\036', '\037',
     293             :   '\100', '\117', '\177', '\173', '\133', '\154', '\120', '\175',
     294             :   '\115', '\135', '\134', '\116', '\153', '\140', '\113', '\141',
     295             :   '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
     296             :   '\370', '\371', '\172', '\136', '\114', '\176', '\156', '\157',
     297             :   '\174', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
     298             :   '\310', '\311', '\321', '\322', '\323', '\324', '\325', '\326',
     299             :   '\327', '\330', '\331', '\342', '\343', '\344', '\345', '\346',
     300             :   '\347', '\350', '\351', '\112', '\340', '\132', '\137', '\155',
     301             :   '\171', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
     302             :   '\210', '\211', '\221', '\222', '\223', '\224', '\225', '\226',
     303             :   '\227', '\230', '\231', '\242', '\243', '\244', '\245', '\246',
     304             :   '\247', '\250', '\251', '\300', '\152', '\320', '\241', '\007',
     305             :   '\040', '\041', '\042', '\043', '\044', '\025', '\006', '\027',
     306             :   '\050', '\051', '\052', '\053', '\054', '\011', '\012', '\033',
     307             :   '\060', '\061', '\032', '\063', '\064', '\065', '\066', '\010',
     308             :   '\070', '\071', '\072', '\073', '\004', '\024', '\076', '\341',
     309             :   '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110',
     310             :   '\111', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
     311             :   '\130', '\131', '\142', '\143', '\144', '\145', '\146', '\147',
     312             :   '\150', '\151', '\160', '\161', '\162', '\163', '\164', '\165',
     313             :   '\166', '\167', '\170', '\200', '\212', '\213', '\214', '\215',
     314             :   '\216', '\217', '\220', '\232', '\233', '\234', '\235', '\236',
     315             :   '\237', '\240', '\252', '\253', '\254', '\255', '\256', '\257',
     316             :   '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
     317             :   '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
     318             :   '\312', '\313', '\314', '\315', '\316', '\317', '\332', '\333',
     319             :   '\334', '\335', '\336', '\337', '\352', '\353', '\354', '\355',
     320             :   '\356', '\357', '\372', '\373', '\374', '\375', '\376', '\377'
     321             : };
     322             : 
     323             : static char const ascii_to_ibm[] =
     324             : {
     325             :   '\000', '\001', '\002', '\003', '\067', '\055', '\056', '\057',
     326             :   '\026', '\005', '\045', '\013', '\014', '\015', '\016', '\017',
     327             :   '\020', '\021', '\022', '\023', '\074', '\075', '\062', '\046',
     328             :   '\030', '\031', '\077', '\047', '\034', '\035', '\036', '\037',
     329             :   '\100', '\132', '\177', '\173', '\133', '\154', '\120', '\175',
     330             :   '\115', '\135', '\134', '\116', '\153', '\140', '\113', '\141',
     331             :   '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
     332             :   '\370', '\371', '\172', '\136', '\114', '\176', '\156', '\157',
     333             :   '\174', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
     334             :   '\310', '\311', '\321', '\322', '\323', '\324', '\325', '\326',
     335             :   '\327', '\330', '\331', '\342', '\343', '\344', '\345', '\346',
     336             :   '\347', '\350', '\351', '\255', '\340', '\275', '\137', '\155',
     337             :   '\171', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
     338             :   '\210', '\211', '\221', '\222', '\223', '\224', '\225', '\226',
     339             :   '\227', '\230', '\231', '\242', '\243', '\244', '\245', '\246',
     340             :   '\247', '\250', '\251', '\300', '\117', '\320', '\241', '\007',
     341             :   '\040', '\041', '\042', '\043', '\044', '\025', '\006', '\027',
     342             :   '\050', '\051', '\052', '\053', '\054', '\011', '\012', '\033',
     343             :   '\060', '\061', '\032', '\063', '\064', '\065', '\066', '\010',
     344             :   '\070', '\071', '\072', '\073', '\004', '\024', '\076', '\341',
     345             :   '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110',
     346             :   '\111', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
     347             :   '\130', '\131', '\142', '\143', '\144', '\145', '\146', '\147',
     348             :   '\150', '\151', '\160', '\161', '\162', '\163', '\164', '\165',
     349             :   '\166', '\167', '\170', '\200', '\212', '\213', '\214', '\215',
     350             :   '\216', '\217', '\220', '\232', '\233', '\234', '\235', '\236',
     351             :   '\237', '\240', '\252', '\253', '\254', '\255', '\256', '\257',
     352             :   '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
     353             :   '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
     354             :   '\312', '\313', '\314', '\315', '\316', '\317', '\332', '\333',
     355             :   '\334', '\335', '\336', '\337', '\352', '\353', '\354', '\355',
     356             :   '\356', '\357', '\372', '\373', '\374', '\375', '\376', '\377'
     357             : };
     358             : 
     359             : static char const ebcdic_to_ascii[] =
     360             : {
     361             :   '\000', '\001', '\002', '\003', '\234', '\011', '\206', '\177',
     362             :   '\227', '\215', '\216', '\013', '\014', '\015', '\016', '\017',
     363             :   '\020', '\021', '\022', '\023', '\235', '\205', '\010', '\207',
     364             :   '\030', '\031', '\222', '\217', '\034', '\035', '\036', '\037',
     365             :   '\200', '\201', '\202', '\203', '\204', '\012', '\027', '\033',
     366             :   '\210', '\211', '\212', '\213', '\214', '\005', '\006', '\007',
     367             :   '\220', '\221', '\026', '\223', '\224', '\225', '\226', '\004',
     368             :   '\230', '\231', '\232', '\233', '\024', '\025', '\236', '\032',
     369             :   '\040', '\240', '\241', '\242', '\243', '\244', '\245', '\246',
     370             :   '\247', '\250', '\133', '\056', '\074', '\050', '\053', '\041',
     371             :   '\046', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
     372             :   '\260', '\261', '\135', '\044', '\052', '\051', '\073', '\136',
     373             :   '\055', '\057', '\262', '\263', '\264', '\265', '\266', '\267',
     374             :   '\270', '\271', '\174', '\054', '\045', '\137', '\076', '\077',
     375             :   '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301',
     376             :   '\302', '\140', '\072', '\043', '\100', '\047', '\075', '\042',
     377             :   '\303', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
     378             :   '\150', '\151', '\304', '\305', '\306', '\307', '\310', '\311',
     379             :   '\312', '\152', '\153', '\154', '\155', '\156', '\157', '\160',
     380             :   '\161', '\162', '\313', '\314', '\315', '\316', '\317', '\320',
     381             :   '\321', '\176', '\163', '\164', '\165', '\166', '\167', '\170',
     382             :   '\171', '\172', '\322', '\323', '\324', '\325', '\326', '\327',
     383             :   '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
     384             :   '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
     385             :   '\173', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
     386             :   '\110', '\111', '\350', '\351', '\352', '\353', '\354', '\355',
     387             :   '\175', '\112', '\113', '\114', '\115', '\116', '\117', '\120',
     388             :   '\121', '\122', '\356', '\357', '\360', '\361', '\362', '\363',
     389             :   '\134', '\237', '\123', '\124', '\125', '\126', '\127', '\130',
     390             :   '\131', '\132', '\364', '\365', '\366', '\367', '\370', '\371',
     391             :   '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
     392             :   '\070', '\071', '\372', '\373', '\374', '\375', '\376', '\377'
     393             : };
     394             : 
     395             : /* True if we need to close the standard output *stream*.  */
     396             : static bool close_stdout_required = true;
     397             : 
     398             : /* The only reason to close the standard output *stream* is if
     399             :    parse_long_options fails (as it does for --help or --version).
     400             :    In any other case, dd uses only the STDOUT_FILENO file descriptor,
     401             :    and the "cleanup" function calls "close (STDOUT_FILENO)".
     402             :    Closing the file descriptor and then letting the usual atexit-run
     403             :    close_stdout function call "fclose (stdout)" would result in a
     404             :    harmless failure of the close syscall (with errno EBADF).
     405             :    This function serves solely to avoid the unnecessary close_stdout
     406             :    call, once parse_long_options has succeeded.  */
     407             : static void
     408          75 : maybe_close_stdout (void)
     409             : {
     410          75 :   if (close_stdout_required)
     411           3 :     close_stdout ();
     412          75 : }
     413             : 
     414             : void
     415          53 : usage (int status)
     416             : {
     417          53 :   if (status != EXIT_SUCCESS)
     418          51 :     fprintf (stderr, _("Try `%s --help' for more information.\n"),
     419             :              program_name);
     420             :   else
     421             :     {
     422           2 :       printf (_("\
     423             : Usage: %s [OPERAND]...\n\
     424             :   or:  %s OPTION\n\
     425             : "),
     426             :               program_name, program_name);
     427           2 :       fputs (_("\
     428             : Copy a file, converting and formatting according to the operands.\n\
     429             : \n\
     430             :   bs=BYTES        force ibs=BYTES and obs=BYTES\n\
     431             :   cbs=BYTES       convert BYTES bytes at a time\n\
     432             :   conv=CONVS      convert the file as per the comma separated symbol list\n\
     433             :   count=BLOCKS    copy only BLOCKS input blocks\n\
     434             :   ibs=BYTES       read BYTES bytes at a time\n\
     435             : "), stdout);
     436           2 :       fputs (_("\
     437             :   if=FILE         read from FILE instead of stdin\n\
     438             :   iflag=FLAGS     read as per the comma separated symbol list\n\
     439             :   obs=BYTES       write BYTES bytes at a time\n\
     440             :   of=FILE         write to FILE instead of stdout\n\
     441             :   oflag=FLAGS     write as per the comma separated symbol list\n\
     442             :   seek=BLOCKS     skip BLOCKS obs-sized blocks at start of output\n\
     443             :   skip=BLOCKS     skip BLOCKS ibs-sized blocks at start of input\n\
     444             :   status=noxfer   suppress transfer statistics\n\
     445             : "), stdout);
     446           2 :       fputs (_("\
     447             : \n\
     448             : BLOCKS and BYTES may be followed by the following multiplicative suffixes:\n\
     449             : xM M, c 1, w 2, b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024,\n\
     450             : GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y.\n\
     451             : \n\
     452             : Each CONV symbol may be:\n\
     453             : \n\
     454             : "), stdout);
     455           2 :       fputs (_("\
     456             :   ascii     from EBCDIC to ASCII\n\
     457             :   ebcdic    from ASCII to EBCDIC\n\
     458             :   ibm       from ASCII to alternate EBCDIC\n\
     459             :   block     pad newline-terminated records with spaces to cbs-size\n\
     460             :   unblock   replace trailing spaces in cbs-size records with newline\n\
     461             :   lcase     change upper case to lower case\n\
     462             : "), stdout);
     463           2 :       fputs (_("\
     464             :   nocreat   do not create the output file\n\
     465             :   excl      fail if the output file already exists\n\
     466             :   notrunc   do not truncate the output file\n\
     467             :   ucase     change lower case to upper case\n\
     468             :   swab      swap every pair of input bytes\n\
     469             : "), stdout);
     470           2 :       fputs (_("\
     471             :   noerror   continue after read errors\n\
     472             :   sync      pad every input block with NULs to ibs-size; when used\n\
     473             :             with block or unblock, pad with spaces rather than NULs\n\
     474             :   fdatasync  physically write output file data before finishing\n\
     475             :   fsync     likewise, but also write metadata\n\
     476             : "), stdout);
     477           2 :       fputs (_("\
     478             : \n\
     479             : Each FLAG symbol may be:\n\
     480             : \n\
     481             :   append    append mode (makes sense only for output; conv=notrunc suggested)\n\
     482             : "), stdout);
     483             :       if (O_DIRECT)
     484           2 :         fputs (_("  direct    use direct I/O for data\n"), stdout);
     485             :       if (O_DIRECTORY)
     486           2 :         fputs (_("  directory fail unless a directory\n"), stdout);
     487             :       if (O_DSYNC)
     488           2 :         fputs (_("  dsync     use synchronized I/O for data\n"), stdout);
     489             :       if (O_SYNC)
     490           2 :         fputs (_("  sync      likewise, but also for metadata\n"), stdout);
     491             :       if (O_NONBLOCK)
     492           2 :         fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
     493             :       if (O_NOATIME)
     494           2 :         fputs (_("  noatime   do not update access time\n"), stdout);
     495             :       if (O_NOCTTY)
     496           2 :         fputs (_("  noctty    do not assign controlling terminal from file\n"),
     497             :                stdout);
     498             :       if (HAVE_WORKING_O_NOFOLLOW)
     499           2 :         fputs (_("  nofollow  do not follow symlinks\n"), stdout);
     500             :       if (O_NOLINKS)
     501             :         fputs (_("  nolinks   fail if multiply-linked\n"), stdout);
     502             :       if (O_BINARY)
     503             :         fputs (_("  binary    use binary I/O for data\n"), stdout);
     504             :       if (O_TEXT)
     505             :         fputs (_("  text      use text I/O for data\n"), stdout);
     506             : 
     507             :       {
     508           2 :         char const *siginfo_name = (SIGINFO == SIGUSR1 ? "USR1" : "INFO");
     509           2 :         printf (_("\
     510             : \n\
     511             : Sending a %s signal to a running `dd' process makes it\n\
     512             : print I/O statistics to standard error and then resume copying.\n\
     513             : \n\
     514             :   $ dd if=/dev/zero of=/dev/null& pid=$!\n\
     515             :   $ kill -%s $pid; sleep 1; kill $pid\n\
     516             :   18335302+0 records in\n\
     517             :   18335302+0 records out\n\
     518             :   9387674624 bytes (9.4 GB) copied, 34.6279 seconds, 271 MB/s\n\
     519             : \n\
     520             : Options are:\n\
     521             : \n\
     522             : "),
     523             :                 siginfo_name, siginfo_name);
     524             :       }
     525             : 
     526           2 :       fputs (HELP_OPTION_DESCRIPTION, stdout);
     527           2 :       fputs (VERSION_OPTION_DESCRIPTION, stdout);
     528           2 :       emit_bug_reporting_address ();
     529             :     }
     530          53 :   exit (status);
     531             : }
     532             : 
     533             : static void
     534           0 : translate_charset (char const *new_trans)
     535             : {
     536             :   int i;
     537             : 
     538           0 :   for (i = 0; i < 256; i++)
     539           0 :     trans_table[i] = new_trans[trans_table[i]];
     540           0 :   translation_needed = true;
     541           0 : }
     542             : 
     543             : /* Return true if I has more than one bit set.  I must be nonnegative.  */
     544             : 
     545             : static inline bool
     546          60 : multiple_bits_set (int i)
     547             : {
     548          60 :   return (i & (i - 1)) != 0;
     549             : }
     550             : 
     551             : /* Print transfer statistics.  */
     552             : 
     553             : static void
     554          11 : print_stats (void)
     555             : {
     556          11 :   xtime_t now = gethrxtime ();
     557             :   char hbuf[LONGEST_HUMAN_READABLE + 1];
     558          11 :   int human_opts =
     559             :     (human_autoscale | human_round_to_nearest
     560             :      | human_space_before_unit | human_SI | human_B);
     561             :   double delta_s;
     562             :   char const *bytes_per_second;
     563             : 
     564          11 :   fprintf (stderr,
     565             :            _("%"PRIuMAX"+%"PRIuMAX" records in\n"
     566             :              "%"PRIuMAX"+%"PRIuMAX" records out\n"),
     567             :            r_full, r_partial, w_full, w_partial);
     568             : 
     569          11 :   if (r_truncate != 0)
     570           0 :     fprintf (stderr,
     571           0 :              ngettext ("%"PRIuMAX" truncated record\n",
     572             :                        "%"PRIuMAX" truncated records\n",
     573             :                        select_plural (r_truncate)),
     574             :              r_truncate);
     575             : 
     576          11 :   if (status_flags & STATUS_NOXFER)
     577           0 :     return;
     578             : 
     579             :   /* Use integer arithmetic to compute the transfer rate,
     580             :      since that makes it easy to use SI abbreviations.  */
     581             : 
     582          22 :   fprintf (stderr,
     583          11 :            ngettext ("%"PRIuMAX" byte (%s) copied",
     584             :                      "%"PRIuMAX" bytes (%s) copied",
     585             :                      select_plural (w_bytes)),
     586             :            w_bytes,
     587             :            human_readable (w_bytes, hbuf, human_opts, 1, 1));
     588             : 
     589          11 :   if (start_time < now)
     590             :     {
     591          11 :       double XTIME_PRECISIONe0 = XTIME_PRECISION;
     592          11 :       uintmax_t delta_xtime = now;
     593          11 :       delta_xtime -= start_time;
     594          11 :       delta_s = delta_xtime / XTIME_PRECISIONe0;
     595          11 :       bytes_per_second = human_readable (w_bytes, hbuf, human_opts,
     596             :                                          XTIME_PRECISION, delta_xtime);
     597             :     }
     598             :   else
     599             :     {
     600           0 :       delta_s = 0;
     601           0 :       bytes_per_second = _("Infinity B");
     602             :     }
     603             : 
     604             :   /* TRANSLATORS: The two instances of "s" in this string are the SI
     605             :      symbol "s" (meaning second), and should not be translated.
     606             : 
     607             :      This format used to be:
     608             : 
     609             :      ngettext (", %g second, %s/s\n", ", %g seconds, %s/s\n", delta_s == 1)
     610             : 
     611             :      but that was incorrect for languages like Polish.  To fix this
     612             :      bug we now use SI symbols even though they're a bit more
     613             :      confusing in English.  */
     614          11 :   fprintf (stderr, _(", %g s, %s/s\n"), delta_s, bytes_per_second);
     615             : }
     616             : 
     617             : static void
     618          11 : cleanup (void)
     619             : {
     620          11 :   if (close (STDIN_FILENO) < 0)
     621           0 :     error (EXIT_FAILURE, errno,
     622             :            _("closing input file %s"), quote (input_file));
     623             : 
     624             :   /* Don't remove this call to close, even though close_stdout
     625             :      closes standard output.  This close is necessary when cleanup
     626             :      is called as part of a signal handler.  */
     627          11 :   if (close (STDOUT_FILENO) < 0)
     628           0 :     error (EXIT_FAILURE, errno,
     629             :            _("closing output file %s"), quote (output_file));
     630          11 : }
     631             : 
     632             : static inline void ATTRIBUTE_NORETURN
     633          11 : quit (int code)
     634             : {
     635          11 :   cleanup ();
     636          11 :   print_stats ();
     637          11 :   process_signals ();
     638          11 :   exit (code);
     639             : }
     640             : 
     641             : /* An ordinary signal was received; arrange for the program to exit.  */
     642             : 
     643             : static void
     644           0 : interrupt_handler (int sig)
     645             : {
     646             :   if (! SA_RESETHAND)
     647             :     signal (sig, SIG_DFL);
     648           0 :   interrupt_signal = sig;
     649           0 : }
     650             : 
     651             : /* An info signal was received; arrange for the program to print status.  */
     652             : 
     653             : static void
     654           0 : siginfo_handler (int sig)
     655             : {
     656             :   if (! SA_NOCLDSTOP)
     657             :     signal (sig, siginfo_handler);
     658           0 :   info_signal_count++;
     659           0 : }
     660             : 
     661             : /* Install the signal handlers.  */
     662             : 
     663             : static void
     664          11 : install_signal_handlers (void)
     665             : {
     666          11 :   bool catch_siginfo = ! (SIGINFO == SIGUSR1 && getenv ("POSIXLY_CORRECT"));
     667             : 
     668             : #if SA_NOCLDSTOP
     669             : 
     670             :   struct sigaction act;
     671          11 :   sigemptyset (&caught_signals);
     672          11 :   if (catch_siginfo)
     673             :     {
     674          11 :       sigaction (SIGINFO, NULL, &act);
     675          11 :       if (act.sa_handler != SIG_IGN)
     676          11 :         sigaddset (&caught_signals, SIGINFO);
     677             :     }
     678          11 :   sigaction (SIGINT, NULL, &act);
     679          11 :   if (act.sa_handler != SIG_IGN)
     680          11 :     sigaddset (&caught_signals, SIGINT);
     681          11 :   act.sa_mask = caught_signals;
     682             : 
     683          11 :   if (sigismember (&caught_signals, SIGINFO))
     684             :     {
     685          11 :       act.sa_handler = siginfo_handler;
     686          11 :       act.sa_flags = 0;
     687          11 :       sigaction (SIGINFO, &act, NULL);
     688             :     }
     689             : 
     690          11 :   if (sigismember (&caught_signals, SIGINT))
     691             :     {
     692             :       /* POSIX 1003.1-2001 says SA_RESETHAND implies SA_NODEFER,
     693             :          but this is not true on Solaris 8 at least.  It doesn't
     694             :          hurt to use SA_NODEFER here, so leave it in.  */
     695          11 :       act.sa_handler = interrupt_handler;
     696          11 :       act.sa_flags = SA_NODEFER | SA_RESETHAND;
     697          11 :       sigaction (SIGINT, &act, NULL);
     698             :     }
     699             : 
     700             : #else
     701             : 
     702             :   if (catch_siginfo && signal (SIGINFO, SIG_IGN) != SIG_IGN)
     703             :     {
     704             :       signal (SIGINFO, siginfo_handler);
     705             :       siginterrupt (SIGINFO, 1);
     706             :     }
     707             :   if (signal (SIGINT, SIG_IGN) != SIG_IGN)
     708             :     {
     709             :       signal (SIGINT, interrupt_handler);
     710             :       siginterrupt (SIGINT, 1);
     711             :     }
     712             : #endif
     713          11 : }
     714             : 
     715             : /* Process any pending signals.  If signals are caught, this function
     716             :    should be called periodically.  Ideally there should never be an
     717             :    unbounded amount of time when signals are not being processed.  */
     718             : 
     719             : static void
     720          40 : process_signals (void)
     721             : {
     722          80 :   while (interrupt_signal | info_signal_count)
     723             :     {
     724             :       int interrupt;
     725             :       int infos;
     726             :       sigset_t oldset;
     727             : 
     728           0 :       sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
     729             : 
     730             :       /* Reload interrupt_signal and info_signal_count, in case a new
     731             :          signal was handled before sigprocmask took effect.  */
     732           0 :       interrupt = interrupt_signal;
     733           0 :       infos = info_signal_count;
     734             : 
     735           0 :       if (infos)
     736           0 :         info_signal_count = infos - 1;
     737             : 
     738           0 :       sigprocmask (SIG_SETMASK, &oldset, NULL);
     739             : 
     740           0 :       if (interrupt)
     741           0 :         cleanup ();
     742           0 :       print_stats ();
     743           0 :       if (interrupt)
     744           0 :         raise (interrupt);
     745             :     }
     746          40 : }
     747             : 
     748             : /* Read from FD into the buffer BUF of size SIZE, processing any
     749             :    signals that arrive before bytes are read.  Return the number of
     750             :    bytes read if successful, -1 (setting errno) on failure.  */
     751             : 
     752             : static ssize_t
     753          20 : iread (int fd, char *buf, size_t size)
     754             : {
     755             :   for (;;)
     756           0 :     {
     757             :       ssize_t nread;
     758          20 :       process_signals ();
     759          20 :       nread = read (fd, buf, size);
     760          20 :       if (! (nread < 0 && errno == EINTR))
     761          40 :         return nread;
     762             :     }
     763             : }
     764             : 
     765             : /* Write to FD the buffer BUF of size SIZE, processing any signals
     766             :    that arrive.  Return the number of bytes written, setting errno if
     767             :    this is less than SIZE.  Keep trying if there are partial
     768             :    writes.  */
     769             : 
     770             : static size_t
     771           9 : iwrite (int fd, char const *buf, size_t size)
     772             : {
     773           9 :   size_t total_written = 0;
     774             : 
     775          27 :   while (total_written < size)
     776             :     {
     777             :       ssize_t nwritten;
     778           9 :       process_signals ();
     779           9 :       nwritten = write (fd, buf + total_written, size - total_written);
     780           9 :       if (nwritten < 0)
     781             :         {
     782           0 :           if (errno != EINTR)
     783           0 :             break;
     784             :         }
     785           9 :       else if (nwritten == 0)
     786             :         {
     787             :           /* Some buggy drivers return 0 when one tries to write beyond
     788             :              a device's end.  (Example: Linux 1.2.13 on /dev/fd0.)
     789             :              Set errno to ENOSPC so they get a sensible diagnostic.  */
     790           0 :           errno = ENOSPC;
     791           0 :           break;
     792             :         }
     793             :       else
     794           9 :         total_written += nwritten;
     795             :     }
     796             : 
     797           9 :   return total_written;
     798             : }
     799             : 
     800             : /* Write, then empty, the output buffer `obuf'. */
     801             : 
     802             : static void
     803           0 : write_output (void)
     804             : {
     805           0 :   size_t nwritten = iwrite (STDOUT_FILENO, obuf, output_blocksize);
     806           0 :   w_bytes += nwritten;
     807           0 :   if (nwritten != output_blocksize)
     808             :     {
     809           0 :       error (0, errno, _("writing to %s"), quote (output_file));
     810           0 :       if (nwritten != 0)
     811           0 :         w_partial++;
     812           0 :       quit (EXIT_FAILURE);
     813             :     }
     814             :   else
     815           0 :     w_full++;
     816           0 :   oc = 0;
     817           0 : }
     818             : 
     819             : /* Return true if STR is of the form "PATTERN" or "PATTERNDELIM...".  */
     820             : 
     821             : static bool
     822         665 : operand_matches (char const *str, char const *pattern, char delim)
     823             : {
     824        1413 :   while (*pattern)
     825         720 :     if (*str++ != *pattern++)
     826         637 :       return false;
     827          28 :   return !*str || *str == delim;
     828             : }
     829             : 
     830             : /* Interpret one "conv=..." or similar operand STR according to the
     831             :    symbols in TABLE, returning the flags specified.  If the operand
     832             :    cannot be parsed, use ERROR_MSGID to generate a diagnostic.  */
     833             : 
     834             : static int
     835           3 : parse_symbols (char const *str, struct symbol_value const *table,
     836             :                char const *error_msgid)
     837             : {
     838           3 :   int value = 0;
     839             : 
     840             :   for (;;)
     841           0 :     {
     842           3 :       char const *strcomma = strchr (str, ',');
     843             :       struct symbol_value const *entry;
     844             : 
     845          45 :       for (entry = table;
     846          45 :            ! (operand_matches (str, entry->symbol, ',') && entry->value);
     847          39 :            entry++)
     848             :         {
     849          42 :           if (! entry->symbol[0])
     850             :             {
     851           3 :               size_t slen = strcomma ? strcomma - str : strlen (str);
     852           3 :               error (0, 0, "%s: %s", _(error_msgid),
     853             :                      quotearg_n_style_mem (0, locale_quoting_style, str, slen));
     854           3 :               usage (EXIT_FAILURE);
     855             :             }
     856             :         }
     857             : 
     858           0 :       value |= entry->value;
     859           0 :       if (!strcomma)
     860           0 :         break;
     861           0 :       str = strcomma + 1;
     862             :     }
     863             : 
     864           0 :   return value;
     865             : }
     866             : 
     867             : /* Return the value of STR, interpreted as a non-negative decimal integer,
     868             :    optionally multiplied by various values.
     869             :    Set *INVALID if STR does not represent a number in this format.  */
     870             : 
     871             : static uintmax_t
     872          52 : parse_integer (const char *str, bool *invalid)
     873             : {
     874             :   uintmax_t n;
     875             :   char *suffix;
     876          52 :   enum strtol_error e = xstrtoumax (str, &suffix, 10, &n, "bcEGkKMPTwYZ0");
     877             : 
     878          52 :   if (e == LONGINT_INVALID_SUFFIX_CHAR && *suffix == 'x')
     879           2 :     {
     880           2 :       uintmax_t multiplier = parse_integer (suffix + 1, invalid);
     881             : 
     882           2 :       if (multiplier != 0 && n * multiplier / multiplier != n)
     883             :         {
     884           0 :           *invalid = true;
     885           0 :           return 0;
     886             :         }
     887             : 
     888           2 :       n *= multiplier;
     889             :     }
     890          50 :   else if (e != LONGINT_OK)
     891             :     {
     892          31 :       *invalid = true;
     893          31 :       return 0;
     894             :     }
     895             : 
     896          21 :   return n;
     897             : }
     898             : 
     899             : /* OPERAND is of the form "X=...".  Return true if X is NAME.  */
     900             : 
     901             : static bool
     902         623 : operand_is (char const *operand, char const *name)
     903             : {
     904         623 :   return operand_matches (operand, name, '=');
     905             : }
     906             : 
     907             : static void
     908          68 : scanargs (int argc, char *const *argv)
     909             : {
     910             :   int i;
     911          68 :   size_t blocksize = 0;
     912             : 
     913          82 :   for (i = optind; i < argc; i++)
     914             :     {
     915          67 :       char const *name = argv[i];
     916          67 :       char const *val = strchr (name, '=');
     917             : 
     918          67 :       if (val == NULL)
     919             :         {
     920           5 :           error (0, 0, _("unrecognized operand %s"), quote (name));
     921           5 :           usage (EXIT_FAILURE);
     922             :         }
     923          62 :       val++;
     924             : 
     925          62 :       if (operand_is (name, "if"))
     926           6 :         input_file = val;
     927          56 :       else if (operand_is (name, "of"))
     928           3 :         output_file = val;
     929          53 :       else if (operand_is (name, "conv"))
     930           1 :         conversions_mask |= parse_symbols (val, conversions,
     931             :                                            N_("invalid conversion"));
     932          52 :       else if (operand_is (name, "iflag"))
     933           1 :         input_flags |= parse_symbols (val, flags,
     934             :                                       N_("invalid input flag"));
     935          51 :       else if (operand_is (name, "oflag"))
     936           1 :         output_flags |= parse_symbols (val, flags,
     937             :                                        N_("invalid output flag"));
     938          50 :       else if (operand_is (name, "status"))
     939           0 :         status_flags |= parse_symbols (val, statuses,
     940             :                                        N_("invalid status flag"));
     941             :       else
     942             :         {
     943          50 :           bool invalid = false;
     944          50 :           uintmax_t n = parse_integer (val, &invalid);
     945             : 
     946          50 :           if (operand_is (name, "ibs"))
     947             :             {
     948           3 :               invalid |= ! (0 < n && n <= MAX_BLOCKSIZE (INPUT_BLOCK_SLOP));
     949           3 :               input_blocksize = n;
     950           3 :               conversions_mask |= C_TWOBUFS;
     951             :             }
     952          47 :           else if (operand_is (name, "obs"))
     953             :             {
     954           3 :               invalid |= ! (0 < n && n <= MAX_BLOCKSIZE (OUTPUT_BLOCK_SLOP));
     955           3 :               output_blocksize = n;
     956           3 :               conversions_mask |= C_TWOBUFS;
     957             :             }
     958          44 :           else if (operand_is (name, "bs"))
     959             :             {
     960           3 :               invalid |= ! (0 < n && n <= MAX_BLOCKSIZE (INPUT_BLOCK_SLOP));
     961           3 :               blocksize = n;
     962             :             }
     963          41 :           else if (operand_is (name, "cbs"))
     964             :             {
     965           2 :               invalid |= ! (0 < n && n <= SIZE_MAX);
     966           2 :               conversion_blocksize = n;
     967             :             }
     968          39 :           else if (operand_is (name, "skip"))
     969           0 :             skip_records = n;
     970          39 :           else if (operand_is (name, "seek"))
     971           0 :             seek_records = n;
     972          39 :           else if (operand_is (name, "count"))
     973           0 :             max_records = n;
     974             :           else
     975             :             {
     976          39 :               error (0, 0, _("unrecognized operand %s"), quote (name));
     977          39 :               usage (EXIT_FAILURE);
     978             :             }
     979             : 
     980          11 :           if (invalid)
     981           6 :             error (EXIT_FAILURE, 0, _("invalid number %s"), quote (val));
     982             :         }
     983             :     }
     984             : 
     985          15 :   if (blocksize)
     986           1 :     input_blocksize = output_blocksize = blocksize;
     987             : 
     988             :   /* If bs= was given, both `input_blocksize' and `output_blocksize' will
     989             :      have been set to positive values.  If either has not been set,
     990             :      bs= was not given, so make sure two buffers are used. */
     991          15 :   if (input_blocksize == 0 || output_blocksize == 0)
     992          14 :     conversions_mask |= C_TWOBUFS;
     993          15 :   if (input_blocksize == 0)
     994          12 :     input_blocksize = DEFAULT_BLOCKSIZE;
     995          15 :   if (output_blocksize == 0)
     996          13 :     output_blocksize = DEFAULT_BLOCKSIZE;
     997          15 :   if (conversion_blocksize == 0)
     998          14 :     conversions_mask &= ~(C_BLOCK | C_UNBLOCK);
     999             : 
    1000          15 :   if (input_flags & (O_DSYNC | O_SYNC))
    1001           0 :     input_flags |= O_RSYNC;
    1002             : 
    1003          15 :   if (multiple_bits_set (conversions_mask & (C_ASCII | C_EBCDIC | C_IBM)))
    1004           0 :     error (EXIT_FAILURE, 0, _("cannot combine any two of {ascii,ebcdic,ibm}"));
    1005          15 :   if (multiple_bits_set (conversions_mask & (C_BLOCK | C_UNBLOCK)))
    1006           0 :     error (EXIT_FAILURE, 0, _("cannot combine block and unblock"));
    1007          15 :   if (multiple_bits_set (conversions_mask & (C_LCASE | C_UCASE)))
    1008           0 :     error (EXIT_FAILURE, 0, _("cannot combine lcase and ucase"));
    1009          15 :   if (multiple_bits_set (conversions_mask & (C_EXCL | C_NOCREAT)))
    1010           0 :     error (EXIT_FAILURE, 0, _("cannot combine excl and nocreat"));
    1011          15 : }
    1012             : 
    1013             : /* Fix up translation table. */
    1014             : 
    1015             : static void
    1016          15 : apply_translations (void)
    1017             : {
    1018             :   int i;
    1019             : 
    1020          15 :   if (conversions_mask & C_ASCII)
    1021           0 :     translate_charset (ebcdic_to_ascii);
    1022             : 
    1023          15 :   if (conversions_mask & C_UCASE)
    1024             :     {
    1025           0 :       for (i = 0; i < 256; i++)
    1026           0 :         trans_table[i] = toupper (trans_table[i]);
    1027           0 :       translation_needed = true;
    1028             :     }
    1029          15 :   else if (conversions_mask & C_LCASE)
    1030             :     {
    1031           0 :       for (i = 0; i < 256; i++)
    1032           0 :         trans_table[i] = tolower (trans_table[i]);
    1033           0 :       translation_needed = true;
    1034             :     }
    1035             : 
    1036          15 :   if (conversions_mask & C_EBCDIC)
    1037             :     {
    1038           0 :       translate_charset (ascii_to_ebcdic);
    1039           0 :       newline_character = ascii_to_ebcdic['\n'];
    1040           0 :       space_character = ascii_to_ebcdic[' '];
    1041             :     }
    1042          15 :   else if (conversions_mask & C_IBM)
    1043             :     {
    1044           0 :       translate_charset (ascii_to_ibm);
    1045           0 :       newline_character = ascii_to_ibm['\n'];
    1046           0 :       space_character = ascii_to_ibm[' '];
    1047             :     }
    1048          15 : }
    1049             : 
    1050             : /* Apply the character-set translations specified by the user
    1051             :    to the NREAD bytes in BUF.  */
    1052             : 
    1053             : static void
    1054           0 : translate_buffer (char *buf, size_t nread)
    1055             : {
    1056             :   char *cp;
    1057             :   size_t i;
    1058             : 
    1059           0 :   for (i = nread, cp = buf; i; i--, cp++)
    1060           0 :     *cp = trans_table[to_uchar (*cp)];
    1061           0 : }
    1062             : 
    1063             : /* If true, the last char from the previous call to `swab_buffer'
    1064             :    is saved in `saved_char'.  */
    1065             : static bool char_is_saved = false;
    1066             : 
    1067             : /* Odd char from previous call.  */
    1068             : static char saved_char;
    1069             : 
    1070             : /* Swap NREAD bytes in BUF, plus possibly an initial char from the
    1071             :    previous call.  If NREAD is odd, save the last char for the
    1072             :    next call.   Return the new start of the BUF buffer.  */
    1073             : 
    1074             : static char *
    1075           0 : swab_buffer (char *buf, size_t *nread)
    1076             : {
    1077           0 :   char *bufstart = buf;
    1078             :   char *cp;
    1079             :   size_t i;
    1080             : 
    1081             :   /* Is a char left from last time?  */
    1082           0 :   if (char_is_saved)
    1083             :     {
    1084           0 :       *--bufstart = saved_char;
    1085           0 :       (*nread)++;
    1086           0 :       char_is_saved = false;
    1087             :     }
    1088             : 
    1089           0 :   if (*nread & 1)
    1090             :     {
    1091             :       /* An odd number of chars are in the buffer.  */
    1092           0 :       saved_char = bufstart[--*nread];
    1093           0 :       char_is_saved = true;
    1094             :     }
    1095             : 
    1096             :   /* Do the byte-swapping by moving every second character two
    1097             :      positions toward the end, working from the end of the buffer
    1098             :      toward the beginning.  This way we only move half of the data.  */
    1099             : 
    1100           0 :   cp = bufstart + *nread;       /* Start one char past the last.  */
    1101           0 :   for (i = *nread / 2; i; i--, cp -= 2)
    1102           0 :     *cp = *(cp - 2);
    1103             : 
    1104           0 :   return ++bufstart;
    1105             : }
    1106             : 
    1107             : /* Add OFFSET to the input offset, setting the overflow flag if
    1108             :    necessary.  */
    1109             : 
    1110             : static void
    1111           9 : advance_input_offset (uintmax_t offset)
    1112             : {
    1113           9 :   input_offset += offset;
    1114           9 :   if (input_offset < offset)
    1115           0 :     input_offset_overflow = true;
    1116           9 : }
    1117             : 
    1118             : /* This is a wrapper for lseek.  It detects and warns about a kernel
    1119             :    bug that makes lseek a no-op for tape devices, even though the kernel
    1120             :    lseek return value suggests that the function succeeded.
    1121             : 
    1122             :    The parameters are the same as those of the lseek function, but
    1123             :    with the addition of FILENAME, the name of the file associated with
    1124             :    descriptor FDESC.  The file name is used solely in the warning that's
    1125             :    printed when the bug is detected.  Return the same value that lseek
    1126             :    would have returned, but when the lseek bug is detected, return -1
    1127             :    to indicate that lseek failed.
    1128             : 
    1129             :    The offending behavior has been confirmed with an Exabyte SCSI tape
    1130             :    drive accessed via /dev/nst0 on both Linux-2.2.17 and Linux-2.4.16.  */
    1131             : 
    1132             : #ifdef __linux__
    1133             : 
    1134             : # include <sys/mtio.h>
    1135             : 
    1136             : # define MT_SAME_POSITION(P, Q) \
    1137             :    ((P).mt_resid == (Q).mt_resid \
    1138             :     && (P).mt_fileno == (Q).mt_fileno \
    1139             :     && (P).mt_blkno == (Q).mt_blkno)
    1140             : 
    1141             : static off_t
    1142           0 : skip_via_lseek (char const *filename, int fdesc, off_t offset, int whence)
    1143             : {
    1144             :   struct mtget s1;
    1145             :   struct mtget s2;
    1146           0 :   bool got_original_tape_position = (ioctl (fdesc, MTIOCGET, &s1) == 0);
    1147             :   /* known bad device type */
    1148             :   /* && s.mt_type == MT_ISSCSI2 */
    1149             : 
    1150           0 :   off_t new_position = lseek (fdesc, offset, whence);
    1151           0 :   if (0 <= new_position
    1152           0 :       && got_original_tape_position
    1153           0 :       && ioctl (fdesc, MTIOCGET, &s2) == 0
    1154           0 :       && MT_SAME_POSITION (s1, s2))
    1155             :     {
    1156           0 :       error (0, 0, _("warning: working around lseek kernel bug for file (%s)\n\
    1157             :   of mt_type=0x%0lx -- see <sys/mtio.h> for the list of types"),
    1158             :              filename, s2.mt_type);
    1159           0 :       errno = 0;
    1160           0 :       new_position = -1;
    1161             :     }
    1162             : 
    1163           0 :   return new_position;
    1164             : }
    1165             : #else
    1166             : # define skip_via_lseek(Filename, Fd, Offset, Whence) lseek (Fd, Offset, Whence)
    1167             : #endif
    1168             : 
    1169             : /* Throw away RECORDS blocks of BLOCKSIZE bytes on file descriptor FDESC,
    1170             :    which is open with read permission for FILE.  Store up to BLOCKSIZE
    1171             :    bytes of the data at a time in BUF, if necessary.  RECORDS must be
    1172             :    nonzero.  If fdesc is STDIN_FILENO, advance the input offset.
    1173             :    Return the number of records remaining, i.e., that were not skipped
    1174             :    because EOF was reached.  */
    1175             : 
    1176             : static uintmax_t
    1177           0 : skip (int fdesc, char const *file, uintmax_t records, size_t blocksize,
    1178             :       char *buf)
    1179             : {
    1180           0 :   uintmax_t offset = records * blocksize;
    1181             : 
    1182             :   /* Try lseek and if an error indicates it was an inappropriate operation --
    1183             :      or if the file offset is not representable as an off_t --
    1184             :      fall back on using read.  */
    1185             : 
    1186           0 :   errno = 0;
    1187           0 :   if (records <= OFF_T_MAX / blocksize
    1188           0 :       && 0 <= skip_via_lseek (file, fdesc, offset, SEEK_CUR))
    1189             :     {
    1190           0 :       if (fdesc == STDIN_FILENO)
    1191           0 :         advance_input_offset (offset);
    1192           0 :       return 0;
    1193             :     }
    1194             :   else
    1195             :     {
    1196           0 :       int lseek_errno = errno;
    1197             : 
    1198             :       do
    1199             :         {
    1200           0 :           ssize_t nread = iread (fdesc, buf, blocksize);
    1201           0 :           if (nread < 0)
    1202             :             {
    1203           0 :               if (fdesc == STDIN_FILENO)
    1204             :                 {
    1205           0 :                   error (0, errno, _("reading %s"), quote (file));
    1206           0 :                   if (conversions_mask & C_NOERROR)
    1207             :                     {
    1208           0 :                       print_stats ();
    1209           0 :                       continue;
    1210             :                     }
    1211             :                 }
    1212             :               else
    1213           0 :                 error (0, lseek_errno, _("%s: cannot seek"), quote (file));
    1214           0 :               quit (EXIT_FAILURE);
    1215             :             }
    1216             : 
    1217           0 :           if (nread == 0)
    1218           0 :             break;
    1219           0 :           if (fdesc == STDIN_FILENO)
    1220           0 :             advance_input_offset (nread);
    1221             :         }
    1222           0 :       while (--records != 0);
    1223             : 
    1224           0 :       return records;
    1225             :     }
    1226             : }
    1227             : 
    1228             : /* Advance the input by NBYTES if possible, after a read error.
    1229             :    The input file offset may or may not have advanced after the failed
    1230             :    read; adjust it to point just after the bad record regardless.
    1231             :    Return true if successful, or if the input is already known to not
    1232             :    be seekable.  */
    1233             : 
    1234             : static bool
    1235           0 : advance_input_after_read_error (size_t nbytes)
    1236             : {
    1237           0 :   if (! input_seekable)
    1238             :     {
    1239           0 :       if (input_seek_errno == ESPIPE)
    1240           0 :         return true;
    1241           0 :       errno = input_seek_errno;
    1242             :     }
    1243             :   else
    1244             :     {
    1245             :       off_t offset;
    1246           0 :       advance_input_offset (nbytes);
    1247           0 :       input_offset_overflow |= (OFF_T_MAX < input_offset);
    1248           0 :       if (input_offset_overflow)
    1249             :         {
    1250           0 :           error (0, 0, _("offset overflow while reading file %s"),
    1251             :                  quote (input_file));
    1252           0 :           return false;
    1253             :         }
    1254           0 :       offset = lseek (STDIN_FILENO, 0, SEEK_CUR);
    1255           0 :       if (0 <= offset)
    1256             :         {
    1257             :           off_t diff;
    1258           0 :           if (offset == input_offset)
    1259           0 :             return true;
    1260           0 :           diff = input_offset - offset;
    1261           0 :           if (! (0 <= diff && diff <= nbytes))
    1262           0 :             error (0, 0, _("warning: invalid file offset after failed read"));
    1263           0 :           if (0 <= skip_via_lseek (input_file, STDIN_FILENO, diff, SEEK_CUR))
    1264           0 :             return true;
    1265           0 :           if (errno == 0)
    1266           0 :             error (0, 0, _("cannot work around kernel bug after all"));
    1267             :         }
    1268             :     }
    1269             : 
    1270           0 :   error (0, errno, _("%s: cannot seek"), quote (input_file));
    1271           0 :   return false;
    1272             : }
    1273             : 
    1274             : /* Copy NREAD bytes of BUF, with no conversions.  */
    1275             : 
    1276             : static void
    1277           8 : copy_simple (char const *buf, size_t nread)
    1278             : {
    1279           8 :   const char *start = buf;      /* First uncopied char in BUF.  */
    1280             : 
    1281             :   do
    1282             :     {
    1283           8 :       size_t nfree = MIN (nread, output_blocksize - oc);
    1284             : 
    1285           8 :       memcpy (obuf + oc, start, nfree);
    1286             : 
    1287           8 :       nread -= nfree;           /* Update the number of bytes left to copy. */
    1288           8 :       start += nfree;
    1289           8 :       oc += nfree;
    1290           8 :       if (oc >= output_blocksize)
    1291           0 :         write_output ();
    1292             :     }
    1293           8 :   while (nread != 0);
    1294           8 : }
    1295             : 
    1296             : /* Copy NREAD bytes of BUF, doing conv=block
    1297             :    (pad newline-terminated records to `conversion_blocksize',
    1298             :    replacing the newline with trailing spaces).  */
    1299             : 
    1300             : static void
    1301           0 : copy_with_block (char const *buf, size_t nread)
    1302             : {
    1303             :   size_t i;
    1304             : 
    1305           0 :   for (i = nread; i; i--, buf++)
    1306             :     {
    1307           0 :       if (*buf == newline_character)
    1308             :         {
    1309           0 :           if (col < conversion_blocksize)
    1310             :             {
    1311             :               size_t j;
    1312           0 :               for (j = col; j < conversion_blocksize; j++)
    1313           0 :                 output_char (space_character);
    1314             :             }
    1315           0 :           col = 0;
    1316             :         }
    1317             :       else
    1318             :         {
    1319           0 :           if (col == conversion_blocksize)
    1320           0 :             r_truncate++;
    1321           0 :           else if (col < conversion_blocksize)
    1322           0 :             output_char (*buf);
    1323           0 :           col++;
    1324             :         }
    1325             :     }
    1326           0 : }
    1327             : 
    1328             : /* Copy NREAD bytes of BUF, doing conv=unblock
    1329             :    (replace trailing spaces in `conversion_blocksize'-sized records
    1330             :    with a newline).  */
    1331             : 
    1332             : static void
    1333           0 : copy_with_unblock (char const *buf, size_t nread)
    1334             : {
    1335             :   size_t i;
    1336             :   char c;
    1337             :   static size_t pending_spaces = 0;
    1338             : 
    1339           0 :   for (i = 0; i < nread; i++)
    1340             :     {
    1341           0 :       c = buf[i];
    1342             : 
    1343           0 :       if (col++ >= conversion_blocksize)
    1344             :         {
    1345           0 :           col = pending_spaces = 0; /* Wipe out any pending spaces.  */
    1346           0 :           i--;                  /* Push the char back; get it later. */
    1347           0 :           output_char (newline_character);
    1348             :         }
    1349           0 :       else if (c == space_character)
    1350           0 :         pending_spaces++;
    1351             :       else
    1352             :         {
    1353             :           /* `c' is the character after a run of spaces that were not
    1354             :              at the end of the conversion buffer.  Output them.  */
    1355           0 :           while (pending_spaces)
    1356             :             {
    1357           0 :               output_char (space_character);
    1358           0 :               --pending_spaces;
    1359             :             }
    1360           0 :           output_char (c);
    1361             :         }
    1362             :     }
    1363           0 : }
    1364             : 
    1365             : /* Set the file descriptor flags for FD that correspond to the nonzero bits
    1366             :    in ADD_FLAGS.  The file's name is NAME.  */
    1367             : 
    1368             : static void
    1369          20 : set_fd_flags (int fd, int add_flags, char const *name)
    1370             : {
    1371             :   /* Ignore file creation flags that are no-ops on file descriptors.  */
    1372          20 :   add_flags &= ~ (O_NOCTTY | O_NOFOLLOW);
    1373             : 
    1374          20 :   if (add_flags)
    1375             :     {
    1376           0 :       int old_flags = fcntl (fd, F_GETFL);
    1377           0 :       int new_flags = old_flags | add_flags;
    1378           0 :       bool ok = true;
    1379           0 :       if (old_flags < 0)
    1380           0 :         ok = false;
    1381           0 :       else if (old_flags != new_flags)
    1382             :         {
    1383           0 :           if (new_flags & (O_DIRECTORY | O_NOLINKS))
    1384             :             {
    1385             :               /* NEW_FLAGS contains at least one file creation flag that
    1386             :                  requires some checking of the open file descriptor.  */
    1387             :               struct stat st;
    1388           0 :               if (fstat (fd, &st) != 0)
    1389           0 :                 ok = false;
    1390           0 :               else if ((new_flags & O_DIRECTORY) && ! S_ISDIR (st.st_mode))
    1391             :                 {
    1392           0 :                   errno = ENOTDIR;
    1393           0 :                   ok = false;
    1394             :                 }
    1395             :               else if ((new_flags & O_NOLINKS) && 1 < st.st_nlink)
    1396             :                 {
    1397             :                   errno = EMLINK;
    1398             :                   ok = false;
    1399             :                 }
    1400           0 :               new_flags &= ~ (O_DIRECTORY | O_NOLINKS);
    1401             :             }
    1402             : 
    1403           0 :           if (ok && old_flags != new_flags
    1404           0 :               && fcntl (fd, F_SETFL, new_flags) == -1)
    1405           0 :             ok = false;
    1406             :         }
    1407             : 
    1408           0 :       if (!ok)
    1409           0 :         error (EXIT_FAILURE, errno, _("setting flags for %s"), quote (name));
    1410             :     }
    1411          20 : }
    1412             : 
    1413             : /* The main loop.  */
    1414             : 
    1415             : static int
    1416          11 : dd_copy (void)
    1417             : {
    1418             :   char *ibuf, *bufstart;        /* Input buffer. */
    1419             :   /* These are declared static so that even though we don't free the
    1420             :      buffers, valgrind will recognize that there is no "real" leak.  */
    1421             :   static char *real_buf;        /* real buffer address before alignment */
    1422             :   static char *real_obuf;
    1423             :   ssize_t nread;                /* Bytes read in the current block.  */
    1424             : 
    1425             :   /* If nonzero, then the previously read block was partial and
    1426             :      PARTREAD was its size.  */
    1427          11 :   size_t partread = 0;
    1428             : 
    1429          11 :   int exit_status = EXIT_SUCCESS;
    1430             :   size_t n_bytes_read;
    1431             : 
    1432             :   /* Leave at least one extra byte at the beginning and end of `ibuf'
    1433             :      for conv=swab, but keep the buffer address even.  But some peculiar
    1434             :      device drivers work only with word-aligned buffers, so leave an
    1435             :      extra two bytes.  */
    1436             : 
    1437             :   /* Some devices require alignment on a sector or page boundary
    1438             :      (e.g. character disk devices).  Align the input buffer to a
    1439             :      page boundary to cover all bases.  Note that due to the swab
    1440             :      algorithm, we must have at least one byte in the page before
    1441             :      the input buffer;  thus we allocate 2 pages of slop in the
    1442             :      real buffer.  8k above the blocksize shouldn't bother anyone.
    1443             : 
    1444             :      The page alignment is necessary on any linux system that supports
    1445             :      either the SGI raw I/O patch or Steven Tweedies raw I/O patch.
    1446             :      It is necessary when accessing raw (i.e. character special) disk
    1447             :      devices on Unixware or other SVR4-derived system.  */
    1448             : 
    1449          11 :   real_buf = xmalloc (input_blocksize + INPUT_BLOCK_SLOP);
    1450          11 :   ibuf = real_buf;
    1451          11 :   ibuf += SWAB_ALIGN_OFFSET;    /* allow space for swab */
    1452             : 
    1453          11 :   ibuf = ptr_align (ibuf, page_size);
    1454             : 
    1455          11 :   if (conversions_mask & C_TWOBUFS)
    1456             :     {
    1457             :       /* Page-align the output buffer, too.  */
    1458          10 :       real_obuf = xmalloc (output_blocksize + OUTPUT_BLOCK_SLOP);
    1459          10 :       obuf = ptr_align (real_obuf, page_size);
    1460             :     }
    1461             :   else
    1462             :     {
    1463           1 :       real_obuf = NULL;
    1464           1 :       obuf = ibuf;
    1465             :     }
    1466             : 
    1467          11 :   if (skip_records != 0)
    1468             :     {
    1469           0 :       skip (STDIN_FILENO, input_file, skip_records, input_blocksize, ibuf);
    1470             :       /* POSIX doesn't say what to do when dd detects it has been
    1471             :          asked to skip past EOF, so I assume it's non-fatal if the
    1472             :          call to 'skip' returns nonzero.  FIXME: maybe give a warning.  */
    1473             :     }
    1474             : 
    1475          11 :   if (seek_records != 0)
    1476             :     {
    1477           0 :       uintmax_t write_records = skip (STDOUT_FILENO, output_file,
    1478             :                                       seek_records, output_blocksize, obuf);
    1479             : 
    1480           0 :       if (write_records != 0)
    1481             :         {
    1482           0 :           memset (obuf, 0, output_blocksize);
    1483             : 
    1484             :           do
    1485           0 :             if (iwrite (STDOUT_FILENO, obuf, output_blocksize)
    1486           0 :                 != output_blocksize)
    1487             :               {
    1488           0 :                 error (0, errno, _("writing to %s"), quote (output_file));
    1489           0 :                 quit (EXIT_FAILURE);
    1490             :               }
    1491           0 :           while (--write_records != 0);
    1492             :         }
    1493             :     }
    1494             : 
    1495          11 :   if (max_records == 0)
    1496           0 :     return exit_status;
    1497             : 
    1498             :   while (1)
    1499             :     {
    1500          29 :       if (r_partial + r_full >= max_records)
    1501           0 :         break;
    1502             : 
    1503             :       /* Zero the buffer before reading, so that if we get a read error,
    1504             :          whatever data we are able to read is followed by zeros.
    1505             :          This minimizes data loss. */
    1506          20 :       if ((conversions_mask & C_SYNC) && (conversions_mask & C_NOERROR))
    1507           0 :         memset (ibuf,
    1508           0 :                 (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
    1509             :                 input_blocksize);
    1510             : 
    1511          20 :       nread = iread (STDIN_FILENO, ibuf, input_blocksize);
    1512             : 
    1513          20 :       if (nread == 0)
    1514           9 :         break;                  /* EOF.  */
    1515             : 
    1516          11 :       if (nread < 0)
    1517             :         {
    1518           2 :           error (0, errno, _("reading %s"), quote (input_file));
    1519           2 :           if (conversions_mask & C_NOERROR)
    1520             :             {
    1521           0 :               print_stats ();
    1522             :               /* Seek past the bad block if possible. */
    1523           0 :               if (!advance_input_after_read_error (input_blocksize - partread))
    1524             :                 {
    1525           0 :                   exit_status = EXIT_FAILURE;
    1526             : 
    1527             :                   /* Suppress duplicate diagnostics.  */
    1528           0 :                   input_seekable = false;
    1529           0 :                   input_seek_errno = ESPIPE;
    1530             :                 }
    1531           0 :               if ((conversions_mask & C_SYNC) && !partread)
    1532             :                 /* Replace the missing input with null bytes and
    1533             :                    proceed normally.  */
    1534           0 :                 nread = 0;
    1535             :               else
    1536           0 :                 continue;
    1537             :             }
    1538             :           else
    1539             :             {
    1540             :               /* Write any partial block. */
    1541           2 :               exit_status = EXIT_FAILURE;
    1542           2 :               break;
    1543             :             }
    1544             :         }
    1545             : 
    1546           9 :       n_bytes_read = nread;
    1547           9 :       advance_input_offset (nread);
    1548             : 
    1549           9 :       if (n_bytes_read < input_blocksize)
    1550             :         {
    1551           9 :           r_partial++;
    1552           9 :           partread = n_bytes_read;
    1553           9 :           if (conversions_mask & C_SYNC)
    1554             :             {
    1555           0 :               if (!(conversions_mask & C_NOERROR))
    1556             :                 /* If C_NOERROR, we zeroed the block before reading. */
    1557           0 :                 memset (ibuf + n_bytes_read,
    1558           0 :                         (conversions_mask & (C_BLOCK | C_UNBLOCK)) ? ' ' : '\0',
    1559             :                         input_blocksize - n_bytes_read);
    1560           0 :               n_bytes_read = input_blocksize;
    1561             :             }
    1562             :         }
    1563             :       else
    1564             :         {
    1565           0 :           r_full++;
    1566           0 :           partread = 0;
    1567             :         }
    1568             : 
    1569           9 :       if (ibuf == obuf)         /* If not C_TWOBUFS. */
    1570             :         {
    1571           1 :           size_t nwritten = iwrite (STDOUT_FILENO, obuf, n_bytes_read);
    1572           1 :           w_bytes += nwritten;
    1573           1 :           if (nwritten != n_bytes_read)
    1574             :             {
    1575           0 :               error (0, errno, _("writing %s"), quote (output_file));
    1576           0 :               return EXIT_FAILURE;
    1577             :             }
    1578           1 :           else if (n_bytes_read == input_blocksize)
    1579           0 :             w_full++;
    1580             :           else
    1581           1 :             w_partial++;
    1582           1 :           continue;
    1583             :         }
    1584             : 
    1585             :       /* Do any translations on the whole buffer at once.  */
    1586             : 
    1587           8 :       if (translation_needed)
    1588           0 :         translate_buffer (ibuf, n_bytes_read);
    1589             : 
    1590           8 :       if (conversions_mask & C_SWAB)
    1591           0 :         bufstart = swab_buffer (ibuf, &n_bytes_read);
    1592             :       else
    1593           8 :         bufstart = ibuf;
    1594             : 
    1595           8 :       if (conversions_mask & C_BLOCK)
    1596           0 :         copy_with_block (bufstart, n_bytes_read);
    1597           8 :       else if (conversions_mask & C_UNBLOCK)
    1598           0 :         copy_with_unblock (bufstart, n_bytes_read);
    1599             :       else
    1600           8 :         copy_simple (bufstart, n_bytes_read);
    1601             :     }
    1602             : 
    1603             :   /* If we have a char left as a result of conv=swab, output it.  */
    1604          11 :   if (char_is_saved)
    1605             :     {
    1606           0 :       if (conversions_mask & C_BLOCK)
    1607           0 :         copy_with_block (&saved_char, 1);
    1608           0 :       else if (conversions_mask & C_UNBLOCK)
    1609           0 :         copy_with_unblock (&saved_char, 1);
    1610             :       else
    1611           0 :         output_char (saved_char);
    1612             :     }
    1613             : 
    1614          11 :   if ((conversions_mask & C_BLOCK) && col > 0)
    1615             :     {
    1616             :       /* If the final input line didn't end with a '\n', pad
    1617             :          the output block to `conversion_blocksize' chars.  */
    1618             :       size_t i;
    1619           0 :       for (i = col; i < conversion_blocksize; i++)
    1620           0 :         output_char (space_character);
    1621             :     }
    1622             : 
    1623          11 :   if ((conversions_mask & C_UNBLOCK) && col == conversion_blocksize)
    1624             :     /* Add a final '\n' if there are exactly `conversion_blocksize'
    1625             :        characters in the final record. */
    1626           0 :     output_char (newline_character);
    1627             : 
    1628             :   /* Write out the last block. */
    1629          11 :   if (oc != 0)
    1630             :     {
    1631           8 :       size_t nwritten = iwrite (STDOUT_FILENO, obuf, oc);
    1632           8 :       w_bytes += nwritten;
    1633           8 :       if (nwritten != 0)
    1634           8 :         w_partial++;
    1635           8 :       if (nwritten != oc)
    1636             :         {
    1637           0 :           error (0, errno, _("writing %s"), quote (output_file));
    1638           0 :           return EXIT_FAILURE;
    1639             :         }
    1640             :     }
    1641             : 
    1642          11 :   if ((conversions_mask & C_FDATASYNC) && fdatasync (STDOUT_FILENO) != 0)
    1643             :     {
    1644           0 :       if (errno != ENOSYS && errno != EINVAL)
    1645             :         {
    1646           0 :           error (0, errno, _("fdatasync failed for %s"), quote (output_file));
    1647           0 :           exit_status = EXIT_FAILURE;
    1648             :         }
    1649           0 :       conversions_mask |= C_FSYNC;
    1650             :     }
    1651             : 
    1652          11 :   if (conversions_mask & C_FSYNC)
    1653           0 :     while (fsync (STDOUT_FILENO) != 0)
    1654           0 :       if (errno != EINTR)
    1655             :         {
    1656           0 :           error (0, errno, _("fsync failed for %s"), quote (output_file));
    1657           0 :           return EXIT_FAILURE;
    1658             :         }
    1659             : 
    1660          11 :   return exit_status;
    1661             : }
    1662             : 
    1663             : int
    1664          75 : main (int argc, char **argv)
    1665             : {
    1666             :   int i;
    1667             :   int exit_status;
    1668             :   off_t offset;
    1669             : 
    1670             :   initialize_main (&argc, &argv);
    1671          75 :   program_name = argv[0];
    1672          75 :   setlocale (LC_ALL, "");
    1673             :   bindtextdomain (PACKAGE, LOCALEDIR);
    1674             :   textdomain (PACKAGE);
    1675             : 
    1676             :   /* Arrange to close stdout if parse_long_options exits.  */
    1677          75 :   atexit (maybe_close_stdout);
    1678             : 
    1679          75 :   page_size = getpagesize ();
    1680             : 
    1681          75 :   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, VERSION,
    1682             :                       usage, AUTHORS, (char const *) NULL);
    1683          72 :   close_stdout_required = false;
    1684             : 
    1685          72 :   if (getopt_long (argc, argv, "", NULL, NULL) != -1)
    1686           4 :     usage (EXIT_FAILURE);
    1687             : 
    1688             :   /* Initialize translation table to identity translation. */
    1689       17476 :   for (i = 0; i < 256; i++)
    1690       17408 :     trans_table[i] = i;
    1691             : 
    1692             :   /* Decode arguments. */
    1693          68 :   scanargs (argc, argv);
    1694             : 
    1695          15 :   apply_translations ();
    1696             : 
    1697          15 :   if (input_file == NULL)
    1698             :     {
    1699          10 :       input_file = _("standard input");
    1700          10 :       set_fd_flags (STDIN_FILENO, input_flags, input_file);
    1701             :     }
    1702             :   else
    1703             :     {
    1704           5 :       if (fd_reopen (STDIN_FILENO, input_file, O_RDONLY | input_flags, 0) < 0)
    1705           2 :         error (EXIT_FAILURE, errno, _("opening %s"), quote (input_file));
    1706             :     }
    1707             : 
    1708          13 :   offset = lseek (STDIN_FILENO, 0, SEEK_CUR);
    1709          13 :   input_seekable = (0 <= offset);
    1710          13 :   input_offset = offset;
    1711          13 :   input_seek_errno = errno;
    1712             : 
    1713          13 :   if (output_file == NULL)
    1714             :     {
    1715          10 :       output_file = _("standard output");
    1716          10 :       set_fd_flags (STDOUT_FILENO, output_flags, output_file);
    1717             :     }
    1718             :   else
    1719             :     {
    1720           3 :       mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
    1721           3 :       int opts
    1722             :         = (output_flags
    1723           3 :            | (conversions_mask & C_NOCREAT ? 0 : O_CREAT)
    1724           3 :            | (conversions_mask & C_EXCL ? O_EXCL : 0)
    1725           3 :            | (seek_records || (conversions_mask & C_NOTRUNC) ? 0 : O_TRUNC));
    1726             : 
    1727             :       /* Open the output file with *read* access only if we might
    1728             :          need to read to satisfy a `seek=' request.  If we can't read
    1729             :          the file, go ahead with write-only access; it might work.  */
    1730           3 :       if ((! seek_records
    1731           0 :            || fd_reopen (STDOUT_FILENO, output_file, O_RDWR | opts, perms) < 0)
    1732           3 :           && (fd_reopen (STDOUT_FILENO, output_file, O_WRONLY | opts, perms)
    1733             :               < 0))
    1734           2 :         error (EXIT_FAILURE, errno, _("opening %s"), quote (output_file));
    1735             : 
    1736             : #if HAVE_FTRUNCATE
    1737           1 :       if (seek_records != 0 && !(conversions_mask & C_NOTRUNC))
    1738             :         {
    1739           0 :           uintmax_t size = seek_records * output_blocksize;
    1740           0 :           unsigned long int obs = output_blocksize;
    1741             : 
    1742           0 :           if (OFF_T_MAX / output_blocksize < seek_records)
    1743           0 :             error (EXIT_FAILURE, 0,
    1744             :                    _("offset too large: "
    1745             :                      "cannot truncate to a length of seek=%"PRIuMAX""
    1746             :                      " (%lu-byte) blocks"),
    1747             :                    seek_records, obs);
    1748             : 
    1749           0 :           if (ftruncate (STDOUT_FILENO, size) != 0)
    1750             :             {
    1751             :               /* Complain only when ftruncate fails on a regular file, a
    1752             :                  directory, or a shared memory object, as POSIX 1003.1-2004
    1753             :                  specifies ftruncate's behavior only for these file types.
    1754             :                  For example, do not complain when Linux 2.4 ftruncate
    1755             :                  fails on /dev/fd0.  */
    1756           0 :               int ftruncate_errno = errno;
    1757             :               struct stat stdout_stat;
    1758           0 :               if (fstat (STDOUT_FILENO, &stdout_stat) != 0)
    1759           0 :                 error (EXIT_FAILURE, errno, _("cannot fstat %s"),
    1760             :                        quote (output_file));
    1761           0 :               if (S_ISREG (stdout_stat.st_mode)
    1762           0 :                   || S_ISDIR (stdout_stat.st_mode)
    1763           0 :                   || S_TYPEISSHM (&stdout_stat))
    1764           0 :                 error (EXIT_FAILURE, ftruncate_errno,
    1765             :                        _("truncating at %"PRIuMAX" bytes in output file %s"),
    1766             :                        size, quote (output_file));
    1767             :             }
    1768             :         }
    1769             : #endif
    1770             :     }
    1771             : 
    1772          11 :   install_signal_handlers ();
    1773             : 
    1774          11 :   start_time = gethrxtime ();
    1775             : 
    1776          11 :   exit_status = dd_copy ();
    1777             : 
    1778          11 :   quit (exit_status);
    1779             : }

Generated by: LCOV version 1.10