"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 ¬runc,
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 }