"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. For more information about "sdd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

    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 }