"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sdd/sdd.c" (20 Aug 2021, 41411 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* @(#)sdd.c    1.72 21/08/20 Copyright 1984-2021 J. Schilling */
    2 #include <schily/mconfig.h>
    3 #ifndef lint
    4 static  UConst char sccsid[] =
    5     "@(#)sdd.c  1.72 21/08/20 Copyright 1984-2021 J. Schilling";
    6 #endif
    7 /*
    8  *  sdd Disk and Tape copy
    9  *
   10  *  Large File remarks:
   11  *
   12  *  Even platforms without large file support don't limit the
   13  *  amount of data that may be read/written to io-streams
   14  *  (e.g. stdin/stdout) and tapes. It makes no sense to use
   15  *  off_t for several data types. As more platforms support long long
   16  *  than large files, we use long long for several important
   17  *  variables that should not overflow.
   18  *
   19  *  Copyright (c) 1984-2021 J. Schilling
   20  */
   21 /*
   22  * The contents of this file are subject to the terms of the
   23  * Common Development and Distribution License, Version 1.0 only
   24  * (the "License").  You may not use this file except in compliance
   25  * with the License.
   26  *
   27  * See the file CDDL.Schily.txt in this distribution for details.
   28  * A copy of the CDDL is also available via the Internet at
   29  * http://www.opensource.org/licenses/cddl1.txt
   30  *
   31  * When distributing Covered Code, include this CDDL HEADER in each
   32  * file and include the License file CDDL.Schily.txt from this distribution.
   33  */
   34 
   35 #include <schily/mconfig.h>
   36 
   37 /*
   38  * XXX Until we find a better way, the next definitions must be in sync
   39  * XXX with the definitions in librmt/remote.c
   40  */
   41 #if !defined(HAVE_FORK) || !defined(HAVE_SOCKETPAIR) || !defined(HAVE_DUP2)
   42 #undef  USE_RCMD_RSH
   43 #endif
   44 #if !defined(HAVE_GETSERVBYNAME)
   45 #undef  USE_REMOTE              /* Cannot get rcmd() port # */
   46 #endif
   47 #if (!defined(HAVE_NETDB_H) || !defined(HAVE_RCMD)) && !defined(USE_RCMD_RSH)
   48 #undef  USE_REMOTE              /* There is no rcmd() */
   49 #endif
   50 
   51 #include <schily/stdio.h>
   52 #include <schily/stdlib.h>
   53 #include <schily/unistd.h>
   54 #include <schily/signal.h>
   55 #include <schily/utypes.h>
   56 #include <schily/time.h>
   57 #include <schily/standard.h>
   58 #include <schily/fcntl.h>
   59 #include <schily/string.h>
   60 #define GT_COMERR       /* #define comerr gtcomerr */
   61 #define GT_ERROR        /* #define error gterror   */
   62 #include <schily/schily.h>
   63 #include <schily/librmt.h>
   64 #include <schily/errno.h>
   65 #include <schily/md5.h>
   66 #include <schily/nlsdefs.h>
   67 
   68 #ifdef  SIGRELSE
   69 #   define  signal  sigset  /* reliable signal */
   70 #endif
   71 
   72 EXPORT  int main        __PR((int ac, char **av));
   73 LOCAL   void    set_signal  __PR((int sig, RETSIGTYPE (*handler)(int)));
   74 LOCAL   void    intr        __PR((int sig));
   75 LOCAL   FILE    *openfile   __PR((char *name, char *mode));
   76 LOCAL   char    *memalloc   __PR((long size));
   77 LOCAL   void    simple_copy __PR((void));
   78 LOCAL   void    copy_reblocked  __PR((void));
   79 LOCAL   long    readvol     __PR((char *buf, long len));
   80 LOCAL   long    writevol    __PR((char *buf, long len));
   81 LOCAL   BOOL    next_in     __PR((void));
   82 LOCAL   BOOL    next_out    __PR((void));
   83 LOCAL   BOOL    next        __PR((char *fname, char *inout, int fd, long pos, int volnum));
   84 LOCAL   BOOL    cont        __PR((char *inout, int num));
   85 LOCAL   void    makelower   __PR((char *s));
   86 LOCAL   long    readbuf     __PR((char *buf, long len));
   87 LOCAL   long    writebuf    __PR((char *buf, long len));
   88 LOCAL   long    readblocks  __PR((char *buf, long len));
   89 LOCAL   long    writeblocks __PR((char *buf, long len));
   90 LOCAL   void    fill        __PR((char *bp, long start, long end));
   91 LOCAL   void    swabb       __PR((char *bp, long cnt));
   92 LOCAL   void    lcase       __PR((char *bp, long cnt));
   93 LOCAL   void    ucase       __PR((char *bp, long cnt));
   94 LOCAL   long    block       __PR((char *bp, long cnt));
   95 LOCAL   long    unblock     __PR((char *bp, long cnt));
   96 LOCAL   void    conv        __PR((char *bp, long cnt, unsigned char *tab));
   97 LOCAL   void    term        __PR((int ret));
   98 LOCAL   void    getstarttime    __PR((void));
   99 LOCAL   void    prstats     __PR((void));
  100 LOCAL   void    getopts     __PR((int ac, char **av));
  101 LOCAL   void    usage       __PR((int ex));
  102 LOCAL   int openremote  __PR((char *filename, long iosize));
  103 LOCAL   int ropenfile   __PR((int rfd, char *name, int mode));
  104 LOCAL   ssize_t rread       __PR((void *buf, size_t cnt));
  105 LOCAL   ssize_t rwrite      __PR((void *buf, size_t cnt));
  106 LOCAL   off_t   riseek      __PR((off_t pos));
  107 LOCAL   off_t   roseek      __PR((off_t pos));
  108 LOCAL   off_t   ifsize      __PR((void));
  109 
  110 LOCAL   void    mdinit      __PR((void));
  111 LOCAL   void    mdupdate    __PR((void *a, size_t s));
  112 LOCAL   void    mdfinal     __PR((void));
  113 
  114 #undef  min
  115 #define min(a, b)   ((a) < (b) ? (a) : (b))
  116 
  117 #define SDD_BSIZE   512L
  118 
  119 #define FILL        000001
  120 #define SWAB        000002
  121 #define LCASE       000004
  122 #define UCASE       000010
  123 #define BLOCK       000020
  124 #define UNBLOCK     000040
  125 #define ASCII       000100
  126 #define EBCDIC      000200
  127 #define IBM     000400
  128 #define NULLIN      010000
  129 #define NULLOUT     020000
  130 #define MD5SUM      040000
  131 
  132 LOCAL   char    *infile;
  133 LOCAL   char    *outfile;
  134 LOCAL   char    *rmtin;
  135 LOCAL   char    *rmtout;
  136 
  137 LOCAL   FILE    *tty;
  138 LOCAL   FILE    *fin;
  139 LOCAL   FILE    *fout;
  140 LOCAL   int ifd;
  141 LOCAL   int ofd;
  142 LOCAL   int rmtifd = -1;
  143 LOCAL   int rmtofd = -1;
  144 
  145 LOCAL   long    ibs;
  146 LOCAL   long    obs;
  147 LOCAL   long    bs;
  148 LOCAL   long    cbs;
  149 LOCAL   long    sdd_bsize = SDD_BSIZE;  /* Sector size */
  150 LOCAL   Llong   count;
  151 LOCAL   off_t   iseek;
  152 LOCAL   off_t   oseek;
  153 LOCAL   off_t   seek;
  154 LOCAL   Llong   iskip;  /* May skip on stdin so it may be more than off_t */
  155 LOCAL   Llong   oskip;  /* May skip on stdin so it may be more than off_t */
  156 LOCAL   Llong   skip;   /* May skip on stdin so it may be more than off_t */
  157 LOCAL   off_t   ivseek;
  158 LOCAL   off_t   ovseek;
  159 LOCAL   Llong   ivsize; /* If volume is a tape, it may be more than off_t */
  160 LOCAL   Llong   ovsize; /* If volume is a tape, it may be more than off_t */
  161 LOCAL   int try = 2;
  162 
  163 LOCAL   Llong   irec;
  164 LOCAL   Llong   orec;
  165 LOCAL   Llong   iparts;
  166 LOCAL   Llong   oparts;
  167 LOCAL   off_t   ivpos;
  168 LOCAL   off_t   ovpos;
  169 LOCAL   int ivolnum = 1;
  170 LOCAL   int ovolnum = 1;
  171 LOCAL   Llong   readerrs;
  172 LOCAL   Llong   writeerrs;
  173 LOCAL   Llong   lastreaderrs;
  174 #ifdef  timerclear
  175 LOCAL   struct  timeval starttime;
  176 LOCAL   struct  timeval stoptime;
  177 #endif
  178 
  179 LOCAL   int flags;
  180 LOCAL   BOOL    notrunc;
  181 LOCAL   BOOL    progress;
  182 LOCAL   BOOL    noerror;
  183 LOCAL   BOOL    noerrwrite;
  184 LOCAL   BOOL    noseek;
  185 LOCAL   BOOL    debug;
  186 LOCAL   BOOL    showtime;
  187 
  188 /* ebcdic to ascii */
  189 LOCAL   unsigned char   asctab[] = {
  190 /*  0 */    0x00,   0x01,   0x02,   0x03,   0x9C,   0x09,   0x86,   0x7F,
  191 /*  8 */    0x97,   0x8D,   0x8E,   0x0B,   0x0C,   0x0D,   0x0E,   0x0F,
  192 /* 10 */    0x10,   0x11,   0x12,   0x13,   0x9D,   0x85,   0x08,   0x87,
  193 /* 18 */    0x18,   0x19,   0x92,   0x8F,   0x1C,   0x1D,   0x1E,   0x1F,
  194 /* 20 */    0x80,   0x81,   0x82,   0x83,   0x84,   0x0A,   0x17,   0x1B,
  195 /* 28 */    0x88,   0x89,   0x8A,   0x8B,   0x8C,   0x05,   0x06,   0x07,
  196 /* 30 */    0x90,   0x91,   0x16,   0x93,   0x94,   0x95,   0x96,   0x04,
  197 /* 38 */    0x98,   0x99,   0x9A,   0x9B,   0x14,   0x15,   0x9E,   0x1A,
  198 /* 40 */    0x20,   0xA0,   0xA1,   0xA2,   0xA3,   0xA4,   0xA5,   0xA6,
  199 /* 48 */    0xA7,   0xA8,   0xD5,   0x2E,   0x3C,   0x28,   0x2B,   0x7C,
  200 /* 50 */    0x26,   0xA9,   0xAA,   0xAB,   0xAC,   0xAD,   0xAE,   0xAF,
  201 /* 58 */    0xB0,   0xB1,   0x21,   0x24,   0x2A,   0x29,   0x3B,   0x7E,
  202 /* 60 */    0x2D,   0x2F,   0xB2,   0xB3,   0xB4,   0xB5,   0xB6,   0xB7,
  203 /* 68 */    0xB8,   0xB9,   0xCB,   0x2C,   0x25,   0x5F,   0x3E,   0x3F,
  204 /* 70 */    0xBA,   0xBB,   0xBC,   0xBD,   0xBE,   0xBF,   0xC0,   0xC1,
  205 /* 78 */    0xC2,   0x60,   0x3A,   0x23,   0x40,   0x27,   0x3D,   0x22,
  206 /* 80 */    0xC3,   0x61,   0x62,   0x63,   0x64,   0x65,   0x66,   0x67,
  207 /* 88 */    0x68,   0x69,   0xC4,   0xC5,   0xC6,   0xC7,   0xC8,   0xC9,
  208 /* 90 */    0xCA,   0x6A,   0x6B,   0x6C,   0x6D,   0x6E,   0x6F,   0x70,
  209 /* 98 */    0x71,   0x72,   0x5E,   0xCC,   0xCD,   0xCE,   0xCF,   0xD0,
  210 /* A0 */    0xD1,   0xE5,   0x73,   0x74,   0x75,   0x76,   0x77,   0x78,
  211 /* A8 */    0x79,   0x7A,   0xD2,   0xD3,   0xD4,   0x5B,   0xD6,   0xD7,
  212 /* B0 */    0xD8,   0xD9,   0xDA,   0xDB,   0xDC,   0xDD,   0xDE,   0xDF,
  213 /* B8 */    0xE0,   0xE1,   0xE2,   0xE3,   0xE4,   0x5D,   0xE6,   0xE7,
  214 /* C0 */    0x7B,   0x41,   0x42,   0x43,   0x44,   0x45,   0x46,   0x47,
  215 /* C8 */    0x48,   0x49,   0xE8,   0xE9,   0xEA,   0xEB,   0xEC,   0xED,
  216 /* D0 */    0x7D,   0x4A,   0x4B,   0x4C,   0x4D,   0x4E,   0x4F,   0x50,
  217 /* D8 */    0x51,   0x52,   0xEE,   0xEF,   0xF0,   0xF1,   0xF2,   0xF3,
  218 /* E0 */    0x5C,   0x9F,   0x53,   0x54,   0x55,   0x56,   0x57,   0x58,
  219 /* E8 */    0x59,   0x5A,   0xF4,   0xF5,   0xF6,   0xF7,   0xF8,   0xF9,
  220 /* F0 */    0x30,   0x31,   0x32,   0x33,   0x34,   0x35,   0x36,   0x37,
  221 /* F8 */    0x38,   0x39,   0xFA,   0xFB,   0xFC,   0xFD,   0xFE,   0xFF,
  222 };
  223 
  224 /* ascii to ebcdic */
  225 
  226 LOCAL   unsigned char   ebctab[] = {
  227 
  228 /*  0   1   2   3   4   5   6   7   */
  229 /*  0   NUL(@)  SOH(A)  STX(B)  ETX(C)  EOT(D)  ENQ(E)  ACK(F)  BEL(G)  */
  230     0x00,   0x01,   0x02,   0x03,   0x37,   0x2D,   0x2E,   0x2F,
  231 
  232 /*  8   BS(H)   HT(I)   LF(J)   VT(K)   FF(L)   CR(M)   SO(N)   SI(O)   */
  233     0x16,   0x05,   0x25,   0x0B,   0x0C,   0x0D,   0x0E,   0x0F,
  234 
  235 /* 10   DLE(P)  DC1(Q)  DC2(R)  DC3(S)  DC4(T)  NAK(U)  SYN(V)  ETB(W)  */
  236     0x10,   0x11,   0x12,   0x13,   0x3C,   0x3D,   0x32,   0x26,
  237 
  238 /* 18   CAN(X)  EM(Y)   SUB(Z)  ESC([)  FS(\)   GS(])   RS(^)   US(_)   */
  239     0x18,   0x19,   0x3F,   0x27,   0x1C,   0x1D,   0x1E,   0x1F,
  240 
  241 /* 20   SP  !   "   #   $   %   &   '   */
  242     0x40,   0x5A,   0x7F,   0x7B,   0x5B,   0x6C,   0x50,   0x7D,
  243 
  244 /* 28   (   )   *   +   ,   -   .   /   */
  245     0x4D,   0x5D,   0x5C,   0x4E,   0x6B,   0x60,   0x4B,   0x61,
  246 
  247 /* 30   0   1   2   3   4   5   6   7   */
  248     0xF0,   0xF1,   0xF2,   0xF3,   0xF4,   0xF5,   0xF6,   0xF7,
  249 
  250 /* 38   8   9   :   ;   <   =   >   ?   */
  251     0xF8,   0xF9,   0x7A,   0x5E,   0x4C,   0x7E,   0x6E,   0x6F,
  252 
  253 /* 40   @   A   B   C   D   E   F   G   */
  254     0x7C,   0xC1,   0xC2,   0xC3,   0xC4,   0xC5,   0xC6,   0xC7,
  255 
  256 /* 48   H   I   J   K   L   M   N   O   */
  257     0xC8,   0xC9,   0xD1,   0xD2,   0xD3,   0xD4,   0xD5,   0xD6,
  258 
  259 /* 50   P   Q   R   S   T   U   V   W   */
  260     0xD7,   0xD8,   0xD9,   0xE2,   0xE3,   0xE4,   0xE5,   0xE6,
  261 
  262 /* 58   X   Y   Z   [   \   ]   ^ ??    _   */
  263     0xE7,   0xE8,   0xE9,   0xAD,   0xE0,   0xBD,   0x9A,   0x6D,
  264 
  265 /* 60   `   a   b   c   d   e   f   g   */
  266     0x79,   0x81,   0x82,   0x83,   0x84,   0x85,   0x86,   0x87,
  267 
  268 /* 68   h   i   j   k   l   m   n   o   */
  269     0x88,   0x89,   0x91,   0x92,   0x93,   0x94,   0x95,   0x96,
  270 
  271 /* 70   p   q   r   s   t   u   v   w   */
  272     0x97,   0x98,   0x99,   0xA2,   0xA3,   0xA4,   0xA5,   0xA6,
  273 
  274 /* 78   x   y   z   {   |   }   ~ ??    DEL */
  275     0xA7,   0xA8,   0xA9,   0xC0,   0x4F,   0xD0,   0x5F,   0x07,
  276 
  277 /* 80   NUL(@)  SOH(A)  STX(B)  ETX(C)  EOT(D)  ENQ(E)  ACK(F)  BEL(G)  */
  278     0xC3,   0x61,   0x62,   0x63,   0x64,   0x65,   0x66,   0x67,
  279 
  280 /* 88   BS(H)   HT(I)   LF(J)   VT(K)   FF(L)   CR(M)   SO(N)   SI(O)   */
  281     0x68,   0x69,   0xC4,   0xC5,   0xC6,   0xC7,   0xC8,   0xC9,
  282 
  283 /* 90   DLE(P)  DC1(Q)  DC2(R)  DC3(S)  DC4(T)  NAK(U)  SYN(V)  ETB(W)  */
  284     0xCA,   0x6A,   0x6B,   0x6C,   0x6D,   0x6E,   0x6F,   0x70,
  285 
  286 /* 98   CAN(X)  EM(Y)   SUB(Z)  ESC([)  FS(\)   GS(])   RS(^)   US(_)   */
  287     0x71,   0x72,   0x5E,   0xCC,   0xCD,   0xCE,   0xCF,   0xD0,
  288 
  289 /* A0   SP  !   "   #   $   %   &   '   */
  290     0xD1,   0xE5,   0x73,   0x74,   0x75,   0x76,   0x77,   0x78,
  291 
  292 /* A8   (   )   *   +   ,   -   .   /   */
  293     0x79,   0x7A,   0xD2,   0xD3,   0xD4,   0x5B,   0xD6,   0xD7,
  294 
  295 /* B0   0   1   2   3   4   5   6   7   */
  296     0xD8,   0xD9,   0xDA,   0xDB,   0xDC,   0xDD,   0xDE,   0xDF,
  297 
  298 /* B8   8   9   :   ;   <   =   >   ?   */
  299     0xE0,   0xE1,   0xE2,   0xE3,   0xE4,   0x5D,   0xE6,   0xE7,
  300 
  301 /* C0   @   A   B   C   D   E   F   G   */
  302     0x7B,   0x41,   0x42,   0x43,   0x44,   0x45,   0x46,   0x47,
  303 
  304 /* C8   H   I   J   K   L   M   N   O   */
  305     0x48,   0x49,   0xE8,   0xE9,   0xEA,   0xEB,   0xEC,   0xED,
  306 
  307 /* D0   P   Q   R   S   T   U   V   W   */
  308     0x7D,   0x4A,   0x4B,   0x4C,   0x4D,   0x4E,   0x4F,   0x50,
  309 
  310 /* D8   X   Y   Z   [   \   ]   ^   _   */
  311     0x51,   0x52,   0xEE,   0xEF,   0xF0,   0xF1,   0xF2,   0xF3,
  312 
  313 /* E0   `   a   b   c   d   e   f   g   */
  314     0x5C,   0x9F,   0x53,   0x54,   0x55,   0x56,   0x57,   0x58,
  315 
  316 /* E8   h   i   j   k   l   m   n   o   */
  317     0x59,   0x5A,   0xF4,   0xF5,   0xF6,   0xF7,   0xF8,   0xF9,
  318 
  319 /* F0   p   q   r   s   t   u   v   w   */
  320     0x30,   0x31,   0x32,   0x33,   0x34,   0x35,   0x36,   0x37,
  321 
  322 /* F8   x   y   z   {   |   }   ~   DEL */
  323     0x38,   0x39,   0xFA,   0xFB,   0xFC,   0xFD,   0xFE,   0xFF,
  324 };
  325 
  326 /* ascii to ibm */
  327 LOCAL   unsigned char   ibmtab[] = {
  328 
  329 /*  0   1   2   3   4   5   6   7   */
  330 /*  0   NUL(@)  SOH(A)  STX(B)  ETX(C)  EOT(D)  ENQ(E)  ACK(F)  BEL(G)  */
  331     0x00,   0x01,   0x02,   0x03,   0x37,   0x2D,   0x2E,   0x2F,
  332 
  333 /*  8   BS(H)   HT(I)   LF(J)   VT(K)   FF(L)   CR(M)   SO(N)   SI(O)   */
  334     0x16,   0x05,   0x25,   0x0B,   0x0C,   0x0D,   0x0E,   0x0F,
  335 
  336 /* 10   DLE(P)  DC1(Q)  DC2(R)  DC3(S)  DC4(T)  NAK(U)  SYN(V)  ETB(W)  */
  337     0x10,   0x11,   0x12,   0x13,   0x3C,   0x3D,   0x32,   0x26,
  338 
  339 /* 18   CAN(X)  EM(Y)   SUB(Z)  ESC([)  FS(\)   GS(])   RS(^)   US(_)   */
  340     0x18,   0x19,   0x3F,   0x27,   0x1C,   0x1D,   0x1E,   0x1F,
  341 
  342 /* 20   SP  !   "   #   $   %   &   '   */
  343     0x40,   0x5A,   0x7F,   0x7B,   0x5B,   0x6C,   0x50,   0x7D,
  344 
  345 /* 28   (   )   *   +   ,   -   .   /   */
  346     0x4D,   0x5D,   0x5C,   0x4E,   0x6B,   0x60,   0x4B,   0x61,
  347 
  348 /* 30   0   1   2   3   4   5   6   7   */
  349     0xF0,   0xF1,   0xF2,   0xF3,   0xF4,   0xF5,   0xF6,   0xF7,
  350 
  351 /* 38   8   9   :   ;   <   =   >   ?   */
  352     0xF8,   0xF9,   0x7A,   0x5E,   0x4C,   0x7E,   0x6E,   0x6F,
  353 
  354 /* 40   @   A   B   C   D   E   F   G   */
  355     0x7C,   0xC1,   0xC2,   0xC3,   0xC4,   0xC5,   0xC6,   0xC7,
  356 
  357 /* 48   H   I   J   K   L   M   N   O   */
  358     0xC8,   0xC9,   0xD1,   0xD2,   0xD3,   0xD4,   0xD5,   0xD6,
  359 
  360 /* 50   P   Q   R   S   T   U   V   W   */
  361     0xD7,   0xD8,   0xD9,   0xE2,   0xE3,   0xE4,   0xE5,   0xE6,
  362 
  363 /* 58   X   Y   Z   [   \   ]   ^   _   */
  364     0xE7,   0xE8,   0xE9,   0xAD,   0xE0,   0xBD,   0x5F,   0x6D,
  365 
  366 /* 60   `   a   b   c   d   e   f   g   */
  367     0x79,   0x81,   0x82,   0x83,   0x84,   0x85,   0x86,   0x87,
  368 
  369 /* 68   h   i   j   k   l   m   n   o   */
  370     0x88,   0x89,   0x91,   0x92,   0x93,   0x94,   0x95,   0x96,
  371 
  372 /* 70   p   q   r   s   t   u   v   w   */
  373     0x97,   0x98,   0x99,   0xA2,   0xA3,   0xA4,   0xA5,   0xA6,
  374 
  375 /* 78   x   y   z   {   |   }   ~   DEL */
  376     0xA7,   0xA8,   0xA9,   0xC0,   0x4F,   0xD0,   0xA1,   0x07,
  377 
  378 /* 80   NUL(@)  SOH(A)  STX(B)  ETX(C)  EOT(D)  ENQ(E)  ACK(F)  BEL(G)  */
  379     0x20,   0x21,   0x22,   0x23,   0x24,   0x15,   0x06,   0x17,
  380 
  381 /* 88   BS(H)   HT(I)   LF(J)   VT(K)   FF(L)   CR(M)   SO(N)   SI(O)   */
  382     0x28,   0x29,   0x2A,   0x2B,   0x2C,   0x09,   0x0A,   0x1B,
  383 
  384 /* 90   DLE(P)  DC1(Q)  DC2(R)  DC3(S)  DC4(T)  NAK(U)  SYN(V)  ETB(W)  */
  385     0x30,   0x31,   0x1A,   0x33,   0x34,   0x35,   0x36,   0x0B,
  386 
  387 /* 98   CAN(X)  EM(Y)   SUB(Z)  ESC([)  FS(\)   GS(])   RS(^)   US(_)   */
  388     0x38,   0x39,   0x3A,   0x3B,   0x04,   0x14,   0x3E,   0xE1,
  389 
  390 /* A0   SP  !   "   #   $   %   &   '   */
  391     0x41,   0x42,   0x43,   0x44,   0x45,   0x46,   0x47,   0x48,
  392 
  393 /* A8   (   )   *   +   ,   -   .   /   */
  394     0x49,   0x51,   0x52,   0x53,   0x54,   0x55,   0x56,   0x57,
  395 
  396 /* B0   0   1   2   3   4   5   6   7   */
  397     0x58,   0x59,   0x62,   0x63,   0x64,   0x65,   0x66,   0x67,
  398 
  399 /* B8   8   9   :   ;   <   =   >   ?   */
  400     0x68,   0x69,   0x70,   0x71,   0x72,   0x73,   0x74,   0x75,
  401 
  402 /* C0   @   A   B   C   D   E   F   G   */
  403     0x76,   0x77,   0x78,   0x80,   0x8A,   0x8B,   0x8C,   0x8D,
  404 
  405 /* C8   H   I   J   K   L   M   N   O   */
  406     0x8E,   0x8F,   0x90,   0x6A,   0x9B,   0x9C,   0x9D,   0x9E,
  407 
  408 /* D0   P   Q   R   S   T   U   V   W   */
  409     0x9F,   0xA0,   0xAA,   0xAB,   0xAC,   0x4A,   0xAE,   0xAF,
  410 
  411 /* D8   X   Y   Z   [   \   ]   ^   _   */
  412     0xB0,   0xB1,   0xB2,   0xB3,   0xB4,   0xB5,   0xB6,   0xB7,
  413 
  414 /* E0   `   a   b   c   d   e   f   g   */
  415     0xB8,   0xB9,   0xBA,   0xBB,   0xBC,   0xA1,   0xBE,   0xBF,
  416 
  417 /* E8   h   i   j   k   l   m   n   o   */
  418     0xCA,   0xCB,   0xCC,   0xCD,   0xCE,   0xCF,   0xDA,   0xDB,
  419 
  420 /* F0   p   q   r   s   t   u   v   w   */
  421     0xDC,   0xDD,   0xDE,   0xDF,   0xEA,   0xEB,   0xEC,   0xED,
  422 
  423 /* F8   x   y   z   {   |   }   ~   DEL */
  424     0xEE,   0xEF,   0xFA,   0xFB,   0xFC,   0xFD,   0xFE,   0xFF,
  425 };
  426 
  427 
  428 EXPORT int
  429 main(ac, av)
  430     int ac;
  431     char    *av[];
  432 {
  433     int ret = 0;
  434 
  435     save_args(ac, av);
  436 
  437     (void) setlocale(LC_ALL, "");
  438 
  439 #ifdef  USE_NLS
  440 #if !defined(TEXT_DOMAIN)   /* Should be defined by cc -D */
  441 #define TEXT_DOMAIN "sdd"   /* Use this only if it weren't */
  442 #endif
  443     { char  *dir;
  444     dir = searchfileinpath("share/locale", F_OK,
  445                     SIP_ANY_FILE|SIP_NO_PATH, NULL);
  446     if (dir)
  447         (void) bindtextdomain(TEXT_DOMAIN, dir);
  448     else
  449 #if defined(PROTOTYPES) && defined(INS_BASE)
  450     (void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
  451 #else
  452     (void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
  453 #endif
  454     (void) textdomain(TEXT_DOMAIN);
  455     }
  456 #endif  /* USE_NLS */
  457 
  458     getopts(ac, av);
  459     tty = stdin;
  460 
  461     getstarttime();
  462     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  463         (void) set_signal(SIGINT, intr);
  464 #ifdef  SIGQUIT
  465     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  466         (void) set_signal(SIGQUIT, intr);
  467 #endif
  468 #ifdef  SIGINFO
  469     /*
  470      * Be polite to *BSD users.
  471      * They copied our idea and implemented intermediate status
  472      * printing in 'dd' in 1990.
  473      */
  474     if (signal(SIGINFO, SIG_IGN) != SIG_IGN)
  475         (void) set_signal(SIGINFO, intr);
  476 #endif
  477 
  478 #ifdef  USE_REMOTE
  479     rmtdebug(debug);
  480     if (infile)
  481         rmtin = rmtfilename(infile);
  482     if (outfile)
  483         rmtout = rmtfilename(outfile);
  484     if (rmtin)
  485         rmtifd = openremote(infile, ibs); /* Needs root privilleges */
  486 
  487     if (rmtout)
  488         rmtofd = openremote(outfile, obs); /* Needs root privilleges */
  489 #endif
  490 
  491 
  492     if (geteuid() != getuid()) {    /* AIX does not like to do this */
  493                     /* If we are not root       */
  494 #ifdef  HAVE_SETREUID
  495         if (setreuid(-1, getuid()) < 0)
  496 #else
  497 #ifdef  HAVE_SETEUID
  498         if (seteuid(getuid()) < 0)
  499 #else
  500         if (setuid(getuid()) < 0)
  501 #endif
  502 #endif
  503             comerr("Panic cannot set back effective uid.\n");
  504     }
  505 
  506     if (infile) {
  507         if (rmtin) {
  508             ropenfile(rmtifd, rmtin, O_RDONLY);
  509         } else {
  510             fin = openfile(infile, "ru");
  511         }
  512     } else {
  513         fin = stdin;
  514         setbuf(fin, NULL);
  515         file_raise(fin, FALSE);
  516         infile = "stdin";
  517         if (ivsize != 0 || ovsize != 0)
  518 #ifdef  HAVE__DEV_TTY
  519             tty = openfile("/dev/tty", "r");
  520 #else
  521             tty = stderr;
  522 #endif
  523     }
  524     if (outfile) {
  525         if (rmtout) {
  526             ropenfile(rmtofd, rmtout,
  527                     notrunc ?
  528                     (O_WRONLY|O_CREAT):
  529                     (O_WRONLY|O_CREAT|O_TRUNC));
  530         } else {
  531             fout = openfile(outfile,
  532                     notrunc ? "wcu" : "wctu");
  533         }
  534     } else {
  535         fout = stdout;
  536         setbuf(fout, NULL);
  537         file_raise(fout, FALSE);
  538         outfile = "stdout";
  539     }
  540     if (rmtin)
  541         ifd = rmtifd;
  542     else
  543         ifd = fdown(fin);
  544     if (rmtout)
  545         ofd = rmtofd;
  546     else
  547         ofd = fdown(fout);
  548 
  549     ivpos = iseek + ivseek;
  550     ovpos = oseek + ovseek;
  551     (void) riseek(ivpos);
  552     (void) roseek(ovpos);
  553 
  554     if (flags & MD5SUM)
  555         mdinit();
  556 
  557     getstarttime();
  558 
  559     if ((obs != ibs) ||
  560         (flags & (BLOCK|UNBLOCK)) ||    /* Reblock forced uncond.   */
  561         (ivsize && !(flags & NULLOUT)) ||   /* Reblock at end of vol    */
  562         (ovsize &&
  563         (((ovsize - ovpos) % obs) ||    /* Reblock at end of 1st vol */
  564         ((ovsize - ovseek) % obs))))    /* Reblock at end of 2nd vol */
  565         copy_reblocked();
  566     else
  567         simple_copy();
  568 
  569     term(ret);
  570     return (0); /* Keep lint happy */
  571 }
  572 
  573 LOCAL void
  574 set_signal(sig, handler)
  575     int     sig;
  576     RETSIGTYPE  (*handler)  __PR((int));
  577 {
  578 #if defined(HAVE_SIGPROCMASK) && defined(SA_RESTART)
  579     struct sigaction sa;
  580 
  581     sigemptyset(&sa.sa_mask);
  582     sa.sa_handler = handler;
  583     sa.sa_flags = SA_RESTART;
  584     (void) sigaction(sig, &sa, (struct sigaction *)0);
  585 #else
  586 #ifdef  HAVE_SIGSETMASK
  587     struct sigvec   sv;
  588 
  589     sv.sv_mask = 0;
  590     sv.sv_handler = handler;
  591     sv.sv_flags = 0;
  592     (void) sigvec(sig, &sv, (struct sigvec *)0);
  593 #else
  594     (void) signal(sig, handler);
  595 #endif
  596 #endif
  597 }
  598 
  599 LOCAL void
  600 intr(sig)
  601     int sig;
  602 {
  603     (void) signal(sig, intr);
  604     prstats();
  605     if (sig == SIGINT) {
  606         errmsgno(EX_BAD, "KILLED by SIGINT.\n");
  607         exit(SIGINT);
  608     }
  609 }
  610 
  611 LOCAL FILE *
  612 openfile(name, mode)
  613     char    *name;
  614     char    *mode;
  615 {
  616     FILE    *f;
  617 
  618     if ((f = fileopen(name, mode)) == (FILE *) NULL)
  619         comerr("Can't open '%s'.\n", name);
  620     file_raise(f, FALSE);
  621     return (f);
  622 }
  623 
  624 #undef  roundup
  625 #define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
  626 
  627 LOCAL char *
  628 memalloc(size)
  629     long    size;
  630 {
  631     char    *ret;
  632     unsigned int pagesize = 512;
  633     UIntptr_t l;
  634 
  635 #ifdef  HAVE_GETPAGESIZE
  636     pagesize = getpagesize();
  637 #else
  638 #ifdef  _SC_PAGESIZE
  639     pagesize = sysconf(_SC_PAGESIZE);
  640 #endif
  641 #endif
  642     if ((ret = malloc((size_t)(size+pagesize))) == NULL)
  643         comerr("No memory.\n");
  644 
  645     l = (UIntptr_t)ret;
  646     l = roundup(l, pagesize);
  647     ret = (char *)l;
  648 
  649     return (ret);
  650 }
  651 
  652 /*
  653  * Simple copy
  654  *
  655  * Input buffer size == output buffer size.
  656  */
  657 LOCAL void
  658 simple_copy()
  659 {
  660     register long   obcnt;
  661     register long   cnt;
  662     register char   *obp;
  663     register int    rflags;
  664 
  665     if (debug)
  666         error("Simple copy ...\n");
  667 
  668     obp = memalloc(bs); /* obs == ibs == bs */
  669     rflags = flags;
  670 
  671     if (rflags & NULLIN)
  672         fill(obp, 0L, bs);
  673 
  674     while ((cnt = readvol(obp, bs)) > 0) {
  675         if (rflags & NULLOUT) {
  676             if (progress && !debug) {
  677                 (void) putc('.', stderr);
  678                 (void) fflush(stderr);
  679             }
  680             continue;
  681         }
  682         if (cnt < bs && (rflags & FILL)) {
  683             fill(obp, cnt, bs);
  684             cnt = bs;
  685         }
  686         for (obcnt = 0; obcnt < cnt; )
  687             obcnt += writevol(obp + obcnt, (long) (cnt - obcnt));
  688     }
  689 }
  690 
  691 /*
  692  * Copy reblocked
  693  *
  694  * Input buffer size != output buffer size or any other condition
  695  * that forces us to use not the simple method.
  696  */
  697 LOCAL void
  698 copy_reblocked()
  699 {
  700     register long   obcnt = 0;
  701     register long   cnt;
  702     register char   *obp;
  703 
  704     if (debug)
  705         error("Copy reblocked ...\n");
  706 
  707     obp = memalloc((long) (obs + ibs));
  708 
  709     while ((cnt = readvol(obp + obcnt, ibs)) > 0) {
  710         obcnt += cnt;
  711         cnt = 0;
  712         for (cnt = 0; obcnt - cnt >= obs; )
  713             cnt += writevol(obp + cnt, obs);
  714         if (cnt != 0) {
  715             if (obcnt > cnt) {
  716                 if (debug)
  717                     error("Moving down %ld bytes.\n",
  718                                 obcnt - cnt);
  719                 (void) movebytes(obp + cnt, obp, obcnt - cnt);
  720             }
  721             obcnt -= cnt;
  722         }
  723     }
  724     if (obcnt > 0) {
  725         if (debug)
  726             error("Writing tail of %ld bytes\n", obcnt);
  727         if (flags & FILL) {
  728             fill(obp, obcnt, obs);
  729             obcnt = obs;
  730         }
  731         cnt = 0;
  732         while (obcnt - cnt > 0)
  733             cnt += writevol(obp + cnt, (long) (obcnt - cnt));
  734     }
  735 }
  736 
  737 /*
  738  * Read one input block from the input volume.
  739  * Switch to the next input volume if needed.
  740  * Do conversions.
  741  */
  742 LOCAL long
  743 readvol(buf, len)
  744     char    *buf;
  745     long    len;
  746 {
  747     Llong   left;
  748     long    cnt;
  749     register int    rflags;
  750 
  751     rflags = flags;
  752 
  753     if (count != 0 && irec >= count)
  754         return (0);
  755 
  756     if (rflags & NULLIN) {
  757         irec++;
  758         return (len);
  759     }
  760 
  761     if (ivsize == 0) {
  762         cnt = readbuf(buf, len);
  763     } else for (;;) {
  764         if ((left = ivsize - ivpos) > 0) {
  765             if ((cnt = readbuf(buf, (long) min(len, left))) > 0)
  766                 break;
  767         }
  768         if (!next_in())
  769             return (0);
  770     }
  771     ivpos += cnt;
  772     if (cnt == ibs)
  773         irec++;
  774     else
  775         iparts += cnt;
  776     if (rflags & NULLOUT)
  777         return (cnt);
  778     if (rflags & SWAB)
  779         swabb(buf, cnt);
  780     if (rflags & ASCII)
  781         conv(buf, cnt, asctab);
  782     if (rflags & LCASE)
  783         lcase(buf, cnt);
  784     if (rflags & UCASE)
  785         ucase(buf, cnt);
  786     if (rflags & BLOCK)
  787         cnt = block(buf, cnt);
  788     if (rflags & UNBLOCK)
  789         cnt = unblock(buf, cnt);
  790     if (rflags & EBCDIC)
  791         conv(buf, cnt, ebctab);
  792     if (rflags & IBM)
  793         conv(buf, cnt, ibmtab);
  794     return (cnt);
  795 }
  796 
  797 /*
  798  * Write one block to the output volume.
  799  * Switch to the next output volume if needed.
  800  */
  801 LOCAL long
  802 writevol(buf, len)
  803     char    *buf;
  804     long    len;
  805 {
  806     long cnt;
  807 
  808     if (ovsize != 0) {
  809         if (ovpos >= ovsize)
  810             if (!next_out())
  811                 term(EX_BAD);
  812         len = min(len, ovsize - ovpos);
  813     }
  814     cnt = writebuf(buf, len);
  815     ovpos += cnt;
  816     if (cnt == obs)
  817         orec++;
  818     else
  819         oparts += cnt;
  820     return (cnt);
  821 }
  822 
  823 /*
  824  * Switch to next input volume.
  825  */
  826 LOCAL BOOL
  827 next_in()
  828 {
  829     return (next(infile, "input", ifd, ivpos = ivseek, ivolnum++));
  830 }
  831 
  832 /*
  833  * Switch to next ouput volume.
  834  */
  835 LOCAL BOOL
  836 next_out()
  837 {
  838     return (next(outfile, "output", ofd, ovpos = ovseek, ovolnum++));
  839 }
  840 
  841 /*
  842  * Switch to next I/O volume.
  843  */
  844 LOCAL BOOL
  845 next(fname, inout, fd, pos, volnum)
  846     char    *fname;
  847     char    *inout;
  848     int fd;
  849     long    pos;
  850     int volnum;
  851 {
  852     if (progress || debug) {
  853         (void) putc('\n', stderr);
  854         (void) fflush(stderr);
  855     }
  856     errmsgno(EX_BAD, "Done with %s volume # %d.\n", inout, volnum);
  857     if (!cont(inout, ++volnum))
  858         return (FALSE);
  859     error("Insert %s volume # %d in '%s' and then hit <cr>: ",
  860                         inout, volnum, fname);
  861     (void) fflush(stderr);
  862     while (getc(tty) != '\n')
  863         if (feof(tty))
  864             return (FALSE);
  865     error("Working on %s volume # %d of '%s'.\n", inout, volnum, fname);
  866     if (fd == ifd)
  867         (void) riseek(pos);
  868     else
  869         (void) roseek(pos);
  870     return (TRUE);
  871 }
  872 
  873 LOCAL BOOL
  874 cont(inout, num)
  875     char    *inout;
  876     int num;
  877 {
  878         char    answer [16];
  879     register char   *ap;
  880 
  881     for (;;) {
  882         error("Do you want to continue with %s volume # %d (y/n): ",
  883                         inout, num);
  884         (void) fflush(stderr);
  885         ap = answer;
  886         if (fgetline(tty, ap, 16) == EOF)
  887             return (FALSE);
  888         while (*ap == ' ' || *ap == '\t')
  889             ap++;
  890         makelower(ap);
  891         if (streql(ap, "y") || streql(ap, "yes"))
  892             return (TRUE);
  893         if (streql(ap, "n") || streql(ap, "no"))
  894             return (FALSE);
  895     }
  896 }
  897 
  898 LOCAL void
  899 makelower(s)
  900     register char   *s;
  901 {
  902     while (*s) {
  903         if (*s >= 'A' && *s <= 'Z')
  904             *s += 'a' - 'A';
  905         else if (*s == ' ' || *s == '\t') {
  906             *s = '\0';
  907             return;
  908         }
  909         s++;
  910     }
  911 }
  912 
  913 /*
  914  * Read one input block.
  915  * Call readblocks if an error occured and -noerror has been specified.
  916  */
  917 LOCAL long
  918 readbuf(buf, len)
  919     char    *buf;
  920     long    len;
  921 {
  922     long    cnt;
  923     int err = 0;
  924 
  925     lastreaderrs = (Llong)0;
  926     if (debug) {
  927         error("readbuf  (%d, %p, %ld) ", ifd, (void *)buf, len);
  928         (void) fflush(stderr);
  929     }
  930     if (noerror && noseek)
  931         fill(buf, 0L, len);
  932     cnt = rread(buf, len);
  933     if (debug) {
  934         if (cnt < 0)
  935             err = geterrno();
  936         error("= %ld\n", cnt);
  937     }
  938     if (cnt < 0) {
  939         if (!debug)
  940             err = geterrno();
  941         if (progress && !debug)
  942             (void) putc('\n', stderr);
  943         errmsgno(err, "Error reading '%s'.\n", infile);
  944 #ifdef  ECONNRESET
  945         if (noerror && err != EPIPE && err != ECONNRESET) {
  946 #else
  947         if (noerror && err != EPIPE) {
  948 #endif
  949             seterrno(err);
  950             cnt = readblocks(buf, len);
  951         } else {
  952             term(err);
  953         }
  954     }
  955     if (cnt == 0)
  956         if (count != 0 && ivsize == 0) {
  957             if (progress || debug)
  958                 (void) putc('\n', stderr);
  959             errmsgno(EX_BAD, "END OF FILE\n");
  960         }
  961 
  962     if ((flags & (NULLOUT|MD5SUM)) == (NULLOUT|MD5SUM))
  963         mdupdate(buf, cnt);
  964     return (cnt);
  965 }
  966 
  967 /*
  968  * Write one output block.
  969  * Call writeblocks if an error occured and -noerror has been specified.
  970  */
  971 LOCAL long
  972 writebuf(buf, len)
  973     char    *buf;
  974     long    len;
  975 {
  976     long    cnt;
  977     int err = 0;
  978 
  979     if (debug)
  980         error("writebuf (%d, %p, %ld)\n", ofd, (void *)buf, len);
  981     if ((lastreaderrs > (Llong)0) && noerrwrite) {
  982         if (debug)
  983             error("seek(%d, %lld)\n", ofd, (Llong)(ovpos + len));
  984         if (roseek(ovpos + len) == (off_t)-1) {
  985             err = geterrno();
  986             if (progress && !debug)
  987                 (void) putc('\n', stderr);
  988             errmsgno((int) err, "Error seeking '%s'.\n", outfile);
  989         }
  990         cnt = len;
  991     } else if ((cnt = rwrite(buf, len)) <= 0) {
  992         if (debug)
  993             error("rwrite() -> cnt %ld\n", cnt);
  994         if (cnt == 0)       /* EOF */
  995             err = ENDOFFILE;
  996         else if (cnt < 0)
  997             err = geterrno();
  998         if (progress && !debug)
  999             (void) putc('\n', stderr);
 1000         errmsgno((int) err, "Error writing '%s'.\n", outfile);
 1001         if (noerror &&
 1002 #ifdef  ECONNRESET
 1003             err != ENDOFFILE && err != EPIPE && err != ECONNRESET) {
 1004 #else
 1005             err != ENDOFFILE && err != EPIPE) {
 1006 #endif
 1007             seterrno(err);
 1008             cnt = writeblocks(buf, len);
 1009         } else {
 1010             term((int) err);
 1011         }
 1012     }
 1013     if (progress && !debug) {
 1014         (void) putc('.', stderr);
 1015         (void) fflush(stderr);
 1016     }
 1017     if ((flags & (NULLOUT|MD5SUM)) == MD5SUM)
 1018         mdupdate(buf, cnt);
 1019     return (cnt);
 1020 }
 1021 
 1022 /*
 1023  * Input error recovery
 1024  */
 1025 LOCAL long
 1026 readblocks(buf, len)
 1027     register char   *buf;
 1028     register long   len;
 1029 {
 1030     register long   cnt;
 1031     register long   aktlen;
 1032     register int    trys;
 1033     register off_t  pos = ivpos;
 1034     register long   total = 0;
 1035         int err = 0;
 1036 
 1037     if (noseek) {
 1038         errmsgno(EX_BAD, "Can't read %ld Bytes at %lld\n",
 1039                             len, (Llong)pos);
 1040         readerrs++;
 1041         return (len);
 1042     } else {
 1043         errmsgno(EX_BAD,
 1044             "Retrying to read %ld Bytes at %lld (Block %lld)\n",
 1045             len, (Llong)pos, (Llong)pos/(Llong)sdd_bsize);
 1046     }
 1047     while (len > 0) {
 1048         aktlen = min(sdd_bsize, len);
 1049         trys = 0;
 1050         do {
 1051             if (trys && !(trys & 15)) {
 1052                 if (debug) {
 1053                     (void) putc('+', stderr);
 1054                     (void) fflush(stderr);
 1055                 }
 1056                 (void) riseek((off_t)(ifsize() - sdd_bsize));
 1057                 (void) rread(buf, aktlen);
 1058 
 1059             } else if (trys > 0 && (trys == 2 || ! (trys & 7))) {
 1060                 if (debug) {
 1061                     (void) putc('-', stderr);
 1062                     (void) fflush(stderr);
 1063                 }
 1064                 (void) riseek((off_t)0);
 1065                 (void) rread(buf, aktlen);
 1066             }
 1067             if (debug) {
 1068                 (void) putc(',', stderr);
 1069                 (void) fflush(stderr);
 1070             }
 1071             fill(buf, 0L, aktlen);
 1072             (void) riseek(pos);
 1073             cnt = rread(buf, aktlen);
 1074             if (cnt < 0) {
 1075                 err = geterrno();
 1076 #ifdef  ECONNRESET
 1077                 if (err == EPIPE || err == ECONNRESET)
 1078 #else
 1079                 if (err == EPIPE)
 1080 #endif
 1081                     break;
 1082                 err = 0;
 1083             }
 1084         } while (cnt < 0 && trys++ < try);
 1085 
 1086         if (cnt < 0) {
 1087             if (progress || debug) {
 1088                 (void) putc('\n', stderr);
 1089                 (void) fflush(stderr);
 1090             }
 1091             errmsgno(EX_BAD, "Block %lld not read correctly.\n",
 1092                         (Llong)pos/(Llong)sdd_bsize);
 1093             if (err != 0)
 1094                 term((int) err);
 1095             cnt = aktlen;
 1096             readerrs++;
 1097             lastreaderrs++;
 1098 
 1099         } else if (cnt == 0)    /* EOF */
 1100             break;
 1101         buf += cnt;
 1102         len -= cnt;
 1103         pos += cnt;
 1104         total += cnt;
 1105     }
 1106     (void) riseek(pos);
 1107     return (total);
 1108 }
 1109 
 1110 /*
 1111  * Output error recovery
 1112  */
 1113 LOCAL long
 1114 writeblocks(buf, len)
 1115     register char   *buf;
 1116     register long   len;
 1117 {
 1118     register long   cnt;
 1119     register long   aktlen;
 1120     register int    trys;
 1121     register off_t  pos = ovpos;
 1122     register long   total = 0;
 1123 /*      char    rdbuf[sdd_bsize];*/
 1124         int err = 0;
 1125 
 1126     if (noseek) {
 1127         errmsgno(EX_BAD, "Can't write %ld Bytes at %lld\n",
 1128                             len, (Llong)pos);
 1129         writeerrs++;
 1130         return (len);
 1131     } else {
 1132         errmsgno(EX_BAD,
 1133             "Retrying to write %ld Bytes at %lld (Block %lld)\n",
 1134             len, (Llong)pos, (Llong)pos/(Llong)sdd_bsize);
 1135     }
 1136     while (len > 0) {
 1137         aktlen = min(sdd_bsize, len);
 1138         trys = 0;
 1139         do {
 1140             if (trys && !(trys & 15)) {
 1141                 if (debug) {
 1142                     (void) putc('>', stderr);
 1143                     (void) fflush(stderr);
 1144                 }
 1145                 (void) roseek((off_t)(ifsize() - sdd_bsize));
 1146 /* XXX we would need to read the output file here - open with "r" ??? */
 1147 /*              (void) rread(rdbuf, aktlen);*/
 1148 
 1149             } else if (trys > 0 && (trys == 2 || ! (trys & 7))) {
 1150                 if (debug) {
 1151                     (void) putc('<', stderr);
 1152                     (void) fflush(stderr);
 1153                 }
 1154                 (void) roseek((off_t)0);
 1155 /* XXX we would need to read the output file here - open with "r" ??? */
 1156 /*              (void) rread(rdbuf, aktlen);*/
 1157             }
 1158             if (debug) {
 1159                 (void) putc(';', stderr);
 1160                 (void) fflush(stderr);
 1161             }
 1162             (void) roseek(pos);
 1163             cnt = rwrite(buf, aktlen);
 1164             if (cnt < 0) {
 1165                 err = geterrno();
 1166 #ifdef  ECONNRESET
 1167                 if (err == EPIPE || err == ECONNRESET)
 1168 #else
 1169                 if (err == EPIPE)
 1170 #endif
 1171                     break;
 1172                 err = 0;
 1173             }
 1174         } while (cnt < 0 && trys++ < try);
 1175         if (cnt < 0) {
 1176             if (progress || debug) {
 1177                 (void) putc('\n', stderr);
 1178                 (void) fflush(stderr);
 1179             }
 1180             errmsgno(EX_BAD, "Block %lld not written correctly.\n",
 1181                         (Llong)pos/(Llong)sdd_bsize);
 1182             if (err != 0)
 1183                 term((int) err);
 1184             cnt = aktlen;
 1185             writeerrs++;
 1186 
 1187         } else if (cnt == 0)    /* EOF */
 1188             break;
 1189         buf += cnt;
 1190         len -= cnt;
 1191         pos += cnt;
 1192         total += cnt;
 1193     }
 1194     (void) roseek(pos);
 1195     return (total);
 1196 }
 1197 
 1198 LOCAL void
 1199 fill(bp, start, end)
 1200     char    *bp;
 1201     long    start;
 1202     long    end;
 1203 {
 1204 #ifdef  OLD
 1205     register char *p = &bp[start];
 1206     register char *ep = &bp[end];
 1207 
 1208     while (p < ep)
 1209         *p++ = '\0';
 1210 #else
 1211     fillbytes(&bp[start], end-start, '\0');
 1212 #endif
 1213 }
 1214 
 1215 #define DO8(a)  a; a; a; a; a; a; a; a;
 1216 
 1217 LOCAL void
 1218 swabb(bp, cnt)
 1219     register char   *bp;
 1220     register long   cnt;
 1221 {
 1222     register char   c;
 1223 
 1224     cnt /= 2;   /* even count only */
 1225     while ((cnt -= 8) >= 0) {
 1226         DO8(
 1227             c = *bp++;
 1228             bp[-1] = *bp;
 1229             *bp++ = c;
 1230         );
 1231     }
 1232     cnt += 8;
 1233     while (--cnt >= 0) {
 1234         c = *bp++;
 1235         bp[-1] = *bp;
 1236         *bp++ = c;
 1237     }
 1238 }
 1239 
 1240 LOCAL void
 1241 lcase(bp, cnt)
 1242     register char   *bp;
 1243     register long   cnt;
 1244 {
 1245     while (--cnt >= 0) {
 1246         if (*bp >= 'A' && *bp <= 'Z')
 1247             *bp += 'a' - 'A';
 1248         bp++;
 1249     }
 1250 }
 1251 
 1252 LOCAL void
 1253 ucase(bp, cnt)
 1254     register char   *bp;
 1255     register long   cnt;
 1256 {
 1257     while (--cnt >= 0) {
 1258         if (*bp >= 'a' && *bp <= 'z')
 1259             *bp -= 'a' - 'A';
 1260         bp++;
 1261     }
 1262 }
 1263 
 1264 LOCAL long
 1265 block(bp, cnt)
 1266     register char   *bp;
 1267     register long   cnt;
 1268 {
 1269     register long   ocnt;
 1270 
 1271     ocnt = cnt;
 1272     while (--cnt >= 0) {
 1273         bp++;
 1274     }
 1275     return (ocnt);
 1276 }
 1277 
 1278 LOCAL long
 1279 unblock(bp, cnt)
 1280     register char   *bp;
 1281     register long   cnt;
 1282 {
 1283     register long   ocnt;
 1284 
 1285     ocnt = cnt;
 1286     while (--cnt >= 0) {
 1287         bp++;
 1288     }
 1289     return (ocnt);
 1290 }
 1291 
 1292 LOCAL void
 1293 conv(bp, cnt, tab)
 1294     register char   *bp;
 1295     register long   cnt;
 1296     register unsigned char  *tab;
 1297 {
 1298     register char   c;
 1299 
 1300     while ((cnt -= 8) >= 0) {
 1301         DO8(
 1302             c = (char)tab[(unsigned char) *bp];
 1303             *bp++ = c;
 1304         );
 1305     }
 1306     cnt += 8;
 1307     while (--cnt >= 0) {
 1308         c = (char)tab[(unsigned char) *bp];
 1309         *bp++ = c;
 1310     }
 1311 
 1312     /* Reihenfolge der Auswertung ist nicht sichergestellt !!! bei: */
 1313     /* XXX      *bp++ = tab[(unsigned char) *bp];*/
 1314 }
 1315 
 1316 LOCAL void
 1317 term(ret)
 1318     int ret;
 1319 {
 1320     if (rmtout) {
 1321 #ifdef  USE_REMOTE
 1322         /*
 1323          * Cannot happen in non remote versions.
 1324          */
 1325         if (rmtclose(rmtofd) < 0)
 1326             ret = geterrno();
 1327 #endif
 1328     } else {
 1329 #ifdef  HAVE_FSYNC
 1330         int cnt = 0;
 1331 
 1332         do {
 1333             if (fsync(ofd) != 0)
 1334                 ret = geterrno();
 1335 
 1336             if (ret == EINVAL)
 1337                 ret = 0;
 1338         } while (ret == EINTR && ++cnt < 10);
 1339 #endif
 1340         if (close(ofd) != 0 && ret == 0)
 1341             ret = geterrno();
 1342     }
 1343     prstats();
 1344     exit(ret);
 1345 }
 1346 
 1347 LOCAL void
 1348 getstarttime()
 1349 {
 1350 #ifdef  timerclear
 1351     if (showtime && gettimeofday(&starttime, 0L) < 0)
 1352         comerr("Cannot get starttime\n");
 1353 #endif
 1354 }
 1355 
 1356 LOCAL void
 1357 prstats()
 1358 {
 1359     Llong   savirec = (Llong)0;
 1360     Llong   ibytes;
 1361     Llong   obytes;
 1362     Llong   ikbytes;
 1363     Llong   okbytes;
 1364     int iper;
 1365     int oper;
 1366 #ifdef  timerclear
 1367     long    sec;
 1368     long    usec;
 1369     long    tmsec;
 1370 #endif
 1371 
 1372 #ifdef  timerclear
 1373     if (showtime && gettimeofday(&stoptime, 0L) < 0)
 1374             comerr("Cannot get stoptime\n");
 1375 #endif
 1376     if (flags & NULLIN) {
 1377         savirec = irec;
 1378         irec = (Llong)0;
 1379     }
 1380     ibytes = irec * (Llong)ibs + iparts;
 1381     obytes = orec * (Llong)obs + oparts;
 1382     ikbytes = ibytes >> 10;
 1383     okbytes = obytes >> 10;
 1384     iper = ((ibytes&1023)<<10)/10485;
 1385     oper = ((obytes&1023)<<10)/10485;
 1386 
 1387     if (progress || debug) (void) putc('\n', stderr);
 1388     if (readerrs)
 1389         errmsgno(EX_BAD, "%lld %s(s) not read correctly.\n",
 1390                     readerrs, noseek?"Record":"Block");
 1391     if (writeerrs)
 1392         errmsgno(EX_BAD, "%lld %s(s) not written correctly.\n",
 1393                     writeerrs, noseek?"Record":"Block");
 1394 
 1395     errmsgno(EX_BAD,
 1396     "Read  %lld records + %lld bytes (total of %lld bytes = %lld.%02dk).\n",
 1397     irec, iparts, ibytes, ikbytes, iper);
 1398     errmsgno(EX_BAD,
 1399     "Wrote %lld records + %lld bytes (total of %lld bytes = %lld.%02dk).\n",
 1400     orec, oparts, obytes, okbytes, oper);
 1401 
 1402     if (flags & NULLIN) {
 1403         irec = savirec;
 1404         ibytes = obytes;
 1405         ikbytes = okbytes;
 1406     }
 1407 #ifdef  timerclear
 1408     if (showtime) {
 1409         long    kbs;
 1410 
 1411         sec = stoptime.tv_sec - starttime.tv_sec;
 1412         usec = stoptime.tv_usec - starttime.tv_usec;
 1413         tmsec = sec*1000 + usec/1000;
 1414         if (usec < 0) {
 1415             sec--;
 1416             usec += 1000000;
 1417         }
 1418         if (tmsec == 0)
 1419             tmsec++;
 1420 
 1421         kbs = ikbytes*(Llong)1000/tmsec;
 1422         errmsgno(EX_BAD, "Total time %ld.%03ldsec (%ld kBytes/sec)\n",
 1423                 sec, usec/1000, kbs);
 1424     }
 1425 #endif
 1426     if (flags & MD5SUM)
 1427         mdfinal();
 1428 }
 1429 
 1430 LOCAL   char    opts[]  = "\
 1431 if*,of*,ibs&,obs&,bs&,cbs&,secsize&,\
 1432 count&,ivsize&,ovsize&,iseek&,oseek&,seek&,\
 1433 iskip&,oskip&,skip&,ivseek&,ovseek&,\
 1434 notrunc,pg,noerror,noerrwrite,noseek,try#,\
 1435 fill,swab,block,unblock,lcase,ucase,ascii,ebcdic,ibm,\
 1436 md5,\
 1437 inull,onull,help,version,debug,time,t";
 1438 
 1439 LOCAL void
 1440 getopts(ac, av)
 1441     int ac;
 1442     char    *av[];
 1443 {
 1444     int cac;
 1445     char    * const *cav;
 1446     BOOL    help    = FALSE;
 1447     BOOL    prvers  = FALSE;
 1448     BOOL    fillflg = FALSE;
 1449     BOOL    swabflg = FALSE;
 1450     BOOL    blkflg  = FALSE;
 1451     BOOL    ublkflg = FALSE;
 1452     BOOL    lcflg   = FALSE;
 1453     BOOL    ucflg   = FALSE;
 1454     BOOL    ascflg  = FALSE;
 1455     BOOL    ebcflg  = FALSE;
 1456     BOOL    ibmflg  = FALSE;
 1457     BOOL    md5flg  = FALSE;
 1458     BOOL    nullin  = FALSE;
 1459     BOOL    nullout = FALSE;
 1460     int trys    = -1;
 1461     Llong   lliseek  = (Llong)0;
 1462     Llong   lloseek  = (Llong)0;
 1463     Llong   llaseek  = (Llong)0;
 1464     Llong   llivseek = (Llong)0;
 1465     Llong   llovseek = (Llong)0;
 1466 
 1467     cac = ac - 1;
 1468     cav = av + 1;
 1469     if (getallargs(&cac, &cav, opts,
 1470                 &infile, &outfile,
 1471                 getnum, &ibs, getnum, &obs, getnum, &bs,
 1472                 getnum, &cbs,
 1473                 getnum, &sdd_bsize,
 1474                 getllnum, &count,
 1475                 getllnum, &ivsize, getllnum, &ovsize,
 1476                 getllnum, &lliseek,  getllnum, &lloseek,
 1477                 getllnum, &llaseek,
 1478                 getllnum, &iskip,  getllnum, &oskip,
 1479                 getllnum, &skip,
 1480                 getllnum, &llivseek, getllnum, &llovseek,
 1481 #ifndef lint            /* lint kann leider nur 52 args !!! */
 1482                 &notrunc,
 1483                 &progress,
 1484                 &noerror,
 1485                 &noerrwrite,
 1486                 &noseek,
 1487                 &trys,
 1488                 &fillflg,
 1489                 &swabflg,
 1490                 &blkflg, &ublkflg,
 1491                 &lcflg, &ucflg,
 1492                 &ascflg, &ebcflg, &ibmflg,
 1493                 &md5flg,
 1494                 &nullin,
 1495                 &nullout,
 1496 #endif
 1497                 &help, &prvers,
 1498                 &debug, &showtime, &showtime) < 0) {
 1499         errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
 1500         usage(EX_BAD);
 1501     }
 1502     if (help)
 1503         usage(0);
 1504     if (prvers) {
 1505         gtprintf("sdd %s %s (%s-%s-%s)\n\n", "1.72", "2021/08/20",
 1506                     HOST_CPU, HOST_VENDOR, HOST_OS);
 1507         gtprintf("Copyright (C) 1984-2021 %s\n", _("Jörg Schilling"));
 1508         gtprintf("This is free software; see the source for copying ");
 1509         gtprintf("conditions.  There is NO\n");
 1510         gtprintf("warranty; not even for MERCHANTABILITY or ");
 1511         gtprintf("FITNESS FOR A PARTICULAR PURPOSE.\n");
 1512         exit(0);
 1513     }
 1514     cac = ac - 1;
 1515     cav = av + 1;
 1516     if (getfiles(&cac, &cav, opts) != 0) {
 1517         errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
 1518         usage(EX_BAD);
 1519     }
 1520 
 1521     iseek   = (off_t)lliseek;
 1522     oseek   = (off_t)lloseek;
 1523     seek    = (off_t)llaseek;
 1524     ivseek  = (off_t)llivseek;
 1525     ovseek  = (off_t)llovseek;
 1526 
 1527     if (iseek != lliseek || oseek != lloseek || seek != llaseek ||
 1528         ivseek != llivseek || ovseek != llovseek) {
 1529 
 1530         errmsgno(EX_BAD,
 1531         "Value of *seek= is too large for data type 'off_t'.\n");
 1532         usage(EX_BAD);
 1533     }
 1534 
 1535     if (trys >= 0) {
 1536         if (!noerror) {
 1537             errmsgno(EX_BAD, "'try' only with '-noerror'.\n");
 1538             usage(EX_BAD);
 1539         }
 1540         if (noseek) {
 1541             errmsgno(EX_BAD, "Can't try with -noseek.\n");
 1542             usage(EX_BAD);
 1543         }
 1544         try = trys;
 1545     }
 1546     if ((iseek || oseek || seek) && (iskip || oskip || skip)) {
 1547         errmsgno(EX_BAD, "Can't seek and skip.\n");
 1548         usage(EX_BAD);
 1549     }
 1550     if ((iseek || oseek || seek) && noseek) {
 1551         errmsgno(EX_BAD, "Can't seek and noseek.\n");
 1552         usage(EX_BAD);
 1553     }
 1554     if (noseek && noerrwrite) {
 1555         errmsgno(EX_BAD, "Can't noseek and noerrwrite.\n");
 1556         usage(EX_BAD);
 1557     }
 1558     if (bs == 0)
 1559         bs = sdd_bsize;
 1560     if (ibs == 0)
 1561         ibs = bs;
 1562     if (obs == 0)
 1563         obs = bs;
 1564     /*
 1565      * It makes no sense to check for EISPIPE with lseek() and to
 1566      * disable seeking, since we currently do not distinct between
 1567      * noiseek and nooseek.
 1568      */
 1569     if (noerror && !noseek) {
 1570         if ((ibs == obs) &&
 1571             (bs % sdd_bsize)) {
 1572             errmsgno(EX_BAD,
 1573                 "Buffer size must be a multiple of %ld.\n",
 1574                 sdd_bsize);
 1575             usage(EX_BAD);
 1576         }
 1577         if (ibs % sdd_bsize) {
 1578             errmsgno(EX_BAD,
 1579                 "Input buffer size must be a multiple of %ld.\n",
 1580                 sdd_bsize);
 1581             usage(EX_BAD);
 1582         }
 1583         if (obs % sdd_bsize) {
 1584             errmsgno(EX_BAD,
 1585                 "Output buffer size must be a multiple of %ld.\n",
 1586                 sdd_bsize);
 1587             usage(EX_BAD);
 1588         }
 1589     }
 1590     if (iskip == 0)
 1591         iskip = skip;
 1592     if (oskip == 0)
 1593         oskip = skip;
 1594     if (iseek == 0)
 1595         iseek = seek;
 1596     if (oseek == 0)
 1597         oseek = seek;
 1598     if (iskip || oskip) {
 1599         errmsgno(EX_BAD, "skip not implemented.\n");
 1600         usage(EX_BAD);
 1601     }
 1602     if (fillflg)
 1603         flags |= FILL;
 1604     if (swabflg)
 1605         flags |= SWAB;
 1606     if (blkflg)
 1607         flags |= BLOCK;
 1608     if (ublkflg)
 1609         flags |= UNBLOCK;
 1610     if ((flags & (BLOCK|UNBLOCK)) && cbs == 0) {
 1611         errmsgno(EX_BAD, "Must specify cbs if block or unblock.\n");
 1612         usage(EX_BAD);
 1613     }
 1614     if (blkflg || ublkflg) {
 1615         errmsgno(EX_BAD, "block/unblock not implemented.\n");
 1616         usage(EX_BAD);
 1617     }
 1618     if (lcflg && ucflg) {
 1619         errmsgno(EX_BAD, "Can't lcase and ucase.\n");
 1620         usage(EX_BAD);
 1621     }
 1622     if (lcflg)
 1623         flags |= LCASE;
 1624     if (ucflg)
 1625         flags |= UCASE;
 1626     if (ascflg)
 1627         flags |= ASCII;
 1628     if (ebcflg && ibmflg) {
 1629         errmsgno(EX_BAD, "Can't ebcdic and ibm.\n");
 1630         usage(EX_BAD);
 1631     }
 1632     if (ebcflg)
 1633         flags |= EBCDIC;
 1634     if (ibmflg)
 1635         flags |= IBM;
 1636     if (md5flg)
 1637         flags |= MD5SUM;
 1638     if (nullin && nullout) {
 1639         errmsgno(EX_BAD, "Can't inull and onull.\n");
 1640         usage(EX_BAD);
 1641     }
 1642     if (nullin) {
 1643         flags &= ~(BLOCK|UNBLOCK);
 1644         flags |= NULLIN;
 1645         ibs = bs = obs;
 1646     }
 1647     if (nullout) {
 1648         flags &= ~(BLOCK|UNBLOCK);
 1649         flags |= NULLOUT;
 1650         obs = bs = ibs;
 1651     }
 1652 }
 1653 
 1654 LOCAL void
 1655 usage(ex)
 1656     int ex;
 1657 {
 1658     error("\
 1659 Usage:  sdd [option=value] [-flag]\n\
 1660 Options:\n\
 1661 ");
 1662     error("\
 1663     if=name       Read  input from name instead of stdin\n\
 1664     of=name       Write output to name instead of stdout\n\
 1665     -inull        Do not read input from file (use null char's)\n\
 1666     -onull        Do not write output to any file\n\
 1667     ibs=#,obs=#,bs=#  Set input/outbut buffersize or both to #\n\
 1668     cbs=#         Set conversion buffersize to #\n\
 1669     secsize=#     Set basic buffersize for -noerror to # (default %ld)\n\
 1670     ivsize=#,ovsize=# Set input/output volume size to #\n\
 1671     count=#       Transfer at most # input records\n\
 1672     iseek=#,iskip=#   Seek/skip # bytes on input before starting\n\
 1673     oseek=#,oskip=#   Seek/skip # bytes on output before starting\n\
 1674     seek=#,skip=#     Seek/skip # bytes on input/output before starting\n\
 1675     ivseek=#,ovseek=# Seek # bytes on input/output volumes before starting\n\
 1676 ",
 1677     sdd_bsize);
 1678     error("\
 1679     -notrunc      Do not trunctate existing output file\n\
 1680     -pg       Print a dot on each write to indicate progress\n\
 1681     -noerror      Do not stop on error\n\
 1682     -noerrwrite   Do not write blocks not read correctly\n\
 1683     -noseek       Don't seek\n\
 1684     try=#         Set error retrycount to # if -noerror (default 2)\n\
 1685     -debug        Print debugging messages\n\
 1686     -fill         Fill each record with zeros up to obs\n\
 1687     -swab,-block,-unblock,-lcase,-ucase,-ascii,-ebcdic,-ibm\n\
 1688     -md5          Compute the md5 sum for the data\n\
 1689 ");
 1690     error("\t-help\t\t  print this online help\n");
 1691     error("\t-version\t  print version number\n");
 1692     exit(ex);
 1693 }
 1694 
 1695 LOCAL int
 1696 openremote(filename, iosize)
 1697     char    *filename;
 1698     long    iosize;
 1699 {
 1700     int remfd   = -1;
 1701     char    *remfn;
 1702     char    host[128];
 1703 
 1704 #ifdef  USE_REMOTE
 1705     if ((remfn = rmtfilename(filename)) != NULL) {
 1706         rmthostname(host, sizeof (host), filename);
 1707 
 1708         if (debug)
 1709             errmsgno(EX_BAD, "Remote: %s Host: %s file: %s\n",
 1710                             filename, host, remfn);
 1711 
 1712         remfd = iosize;
 1713         if (remfd != iosize) {
 1714             comerrno(EX_BAD,
 1715                 "Buffer size %ld too large for remote operation.\n",
 1716                 iosize);
 1717         }
 1718         if ((remfd = rmtgetconn(host, (int)iosize, 0)) < 0)
 1719             comerrno(EX_BAD, "Cannot get connection to '%s'.\n",
 1720                 /* errno not valid !! */        host);
 1721     }
 1722 #else
 1723     comerrno(EX_BAD, "Remote tape support not present.\n");
 1724 #endif
 1725     return (remfd);
 1726 }
 1727 
 1728 LOCAL int
 1729 ropenfile(rfd, name, mode)
 1730     int rfd;
 1731     char    *name;
 1732     int mode;
 1733 {
 1734 #ifdef  USE_REMOTE
 1735     int fd;
 1736 
 1737     if ((fd = rmtopen(rfd, name, mode)) < 0)
 1738         comerr("Can't open '%s'.\n", name);
 1739     return (fd);
 1740 #else
 1741     comerrno(EX_BAD, "Remote tape support not present.\n");
 1742     /* NOTREACHED */
 1743     return (-1);
 1744 #endif
 1745 }
 1746 
 1747 LOCAL ssize_t
 1748 rread(buf, cnt)
 1749     void    *buf;
 1750     size_t  cnt;
 1751 {
 1752 #ifdef  USE_REMOTE
 1753     if (rmtifd >= 0) {
 1754         int icnt = cnt;
 1755 
 1756         /*
 1757          * This check is needed as long as librmt uses int in rmtread()
 1758          */
 1759         if (icnt != cnt) {
 1760             seterrno(EINVAL);
 1761             return (-1);
 1762         }
 1763         return (rmtread(rmtifd, buf, cnt));
 1764     }
 1765 #endif
 1766     return (_niread(ifd, buf, cnt));
 1767 }
 1768 
 1769 LOCAL ssize_t
 1770 rwrite(buf, cnt)
 1771     void    *buf;
 1772     size_t  cnt;
 1773 {
 1774 #ifdef  USE_REMOTE
 1775     if (rmtofd >= 0) {
 1776         int icnt = cnt;
 1777 
 1778         /*
 1779          * This check is needed as long as librmt uses int in rmtwrite()
 1780          */
 1781         if (icnt != cnt) {
 1782             seterrno(EINVAL);
 1783             return (-1);
 1784         }
 1785         return (rmtwrite(rmtofd, buf, cnt));
 1786     }
 1787 #endif
 1788     return (_niwrite(ofd, buf, cnt));
 1789 }
 1790 
 1791 LOCAL off_t
 1792 riseek(pos)
 1793     off_t   pos;
 1794 {
 1795 #ifdef  USE_REMOTE
 1796     if (rmtifd >= 0)
 1797         return (rmtseek(rmtifd, pos, SEEK_SET));
 1798 #endif
 1799     return (lseek(ifd, pos, SEEK_SET));
 1800 }
 1801 
 1802 LOCAL off_t
 1803 roseek(pos)
 1804     off_t   pos;
 1805 {
 1806 #ifdef  USE_REMOTE
 1807     if (rmtofd >= 0)
 1808         return (rmtseek(rmtofd, pos, SEEK_SET));
 1809 #endif
 1810     return (lseek(ofd, pos, SEEK_SET));
 1811 }
 1812 
 1813 LOCAL off_t
 1814 ifsize()
 1815 {
 1816 #ifdef  USE_REMOTE
 1817     off_t   opos;
 1818     off_t   pos;
 1819 
 1820     if (rmtifd >= 0) {
 1821         opos = rmtseek(rmtifd, (off_t)0, SEEK_CUR);
 1822         pos = rmtseek(rmtifd, (off_t)0, SEEK_END);
 1823         (void) rmtseek(rmtifd, opos, SEEK_SET);
 1824         return (pos);
 1825     }
 1826 #endif
 1827     return (filesize(fin));
 1828 }
 1829 
 1830 
 1831 MD5_CTX MD5_context;
 1832 
 1833 LOCAL void
 1834 mdinit()
 1835 {
 1836     MD5Init(&MD5_context);
 1837 }
 1838 
 1839 LOCAL void
 1840 mdupdate(a, s)
 1841     void    *a;
 1842     size_t  s;
 1843 {
 1844     MD5Update(&MD5_context, a, s);
 1845 }
 1846 
 1847 LOCAL void
 1848 mdfinal()
 1849 {
 1850     MD5_CTX ctx;
 1851     UInt8_t result[MD5_DIGEST_LENGTH];
 1852 
 1853     ctx = MD5_context;
 1854 
 1855     MD5Final(result, &ctx);
 1856 
 1857     errmsgno(EX_BAD,
 1858     "md5 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
 1859             result[0],
 1860             result[1],
 1861             result[2],
 1862             result[3],
 1863             result[4],
 1864             result[5],
 1865             result[6],
 1866             result[7],
 1867             result[8],
 1868             result[9],
 1869             result[10],
 1870             result[11],
 1871             result[12],
 1872             result[13],
 1873             result[14],
 1874             result[15]);
 1875 }