]>
Commit | Line | Data |
---|---|---|
44a7a5ab A |
1 | /* $OpenBSD: ar_io.c,v 1.17 1997/09/01 18:29:42 deraadt Exp $ */ |
2 | /* $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $ */ | |
3 | ||
4 | /*- | |
5 | * Copyright (c) 1992 Keith Muller. | |
6 | * Copyright (c) 1992, 1993 | |
7 | * The Regents of the University of California. All rights reserved. | |
8 | * | |
9 | * This code is derived from software contributed to Berkeley by | |
10 | * Keith Muller of the University of California, San Diego. | |
11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | |
15 | * 1. Redistributions of source code must retain the above copyright | |
16 | * notice, this list of conditions and the following disclaimer. | |
17 | * 2. Redistributions in binary form must reproduce the above copyright | |
18 | * notice, this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * 3. All advertising materials mentioning features or use of this software | |
21 | * must display the following acknowledgement: | |
22 | * This product includes software developed by the University of | |
23 | * California, Berkeley and its contributors. | |
24 | * 4. Neither the name of the University nor the names of its contributors | |
25 | * may be used to endorse or promote products derived from this software | |
26 | * without specific prior written permission. | |
27 | * | |
28 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
38 | * SUCH DAMAGE. | |
39 | */ | |
40 | ||
41 | #ifndef lint | |
42 | #if 0 | |
43 | static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 4/18/94"; | |
44 | #else | |
45 | static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997/09/01 18:29:42 deraadt Exp $"; | |
46 | #endif | |
47 | #endif /* not lint */ | |
48 | ||
49 | #include <sys/types.h> | |
50 | #include <sys/time.h> | |
51 | #include <sys/stat.h> | |
52 | #include <sys/ioctl.h> | |
53 | #include <sys/mtio.h> | |
54 | #include <sys/param.h> | |
55 | #include <signal.h> | |
56 | #include <string.h> | |
57 | #include <fcntl.h> | |
58 | #include <unistd.h> | |
59 | #include <stdio.h> | |
60 | #include <errno.h> | |
61 | #include <stdlib.h> | |
62 | #include <err.h> | |
63 | #include "pax.h" | |
64 | #include "options.h" | |
65 | #include "extern.h" | |
66 | ||
67 | /* | |
68 | * Routines which deal directly with the archive I/O device/file. | |
69 | */ | |
70 | ||
71 | #define DMOD 0666 /* default mode of created archives */ | |
72 | #define EXT_MODE O_RDONLY /* open mode for list/extract */ | |
73 | #define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */ | |
74 | #define APP_MODE O_RDWR /* mode for append */ | |
75 | #define STDO "<STDOUT>" /* psuedo name for stdout */ | |
76 | #define STDN "<STDIN>" /* psuedo name for stdin */ | |
77 | static int arfd = -1; /* archive file descriptor */ | |
78 | static int artyp = ISREG; /* archive type: file/FIFO/tape */ | |
79 | static int arvol = 1; /* archive volume number */ | |
80 | static int lstrval = -1; /* return value from last i/o */ | |
81 | static int io_ok; /* i/o worked on volume after resync */ | |
82 | static int did_io; /* did i/o ever occur on volume? */ | |
83 | static int done; /* set via tty termination */ | |
84 | static struct stat arsb; /* stat of archive device at open */ | |
85 | static int invld_rec; /* tape has out of spec record size */ | |
86 | static int wr_trail = 1; /* trailer was rewritten in append */ | |
87 | static int can_unlnk = 0; /* do we unlink null archives? */ | |
88 | char *arcname; /* printable name of archive */ | |
89 | char *gzip_program; /* name of gzip program */ | |
90 | ||
91 | static int get_phys __P((void)); | |
92 | extern sigset_t s_mask; | |
93 | static void ar_start_gzip __P((int)); | |
94 | ||
95 | /* | |
96 | * ar_open() | |
97 | * Opens the next archive volume. Determines the type of the device and | |
98 | * sets up block sizes as required by the archive device and the format. | |
99 | * Note: we may be called with name == NULL on the first open only. | |
100 | * Return: | |
101 | * -1 on failure, 0 otherwise | |
102 | */ | |
103 | ||
104 | #ifdef __STDC__ | |
105 | int | |
106 | ar_open(char *name) | |
107 | #else | |
108 | int | |
109 | ar_open(name) | |
110 | char *name; | |
111 | #endif | |
112 | { | |
113 | struct mtget mb; | |
114 | ||
115 | if (arfd != -1) | |
116 | (void)close(arfd); | |
117 | arfd = -1; | |
118 | can_unlnk = did_io = io_ok = invld_rec = 0; | |
119 | artyp = ISREG; | |
120 | flcnt = 0; | |
121 | ||
122 | /* | |
123 | * open based on overall operation mode | |
124 | */ | |
125 | switch (act) { | |
126 | case LIST: | |
127 | case EXTRACT: | |
128 | if (name == NULL) { | |
129 | arfd = STDIN_FILENO; | |
130 | arcname = STDN; | |
131 | } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) | |
132 | syswarn(0, errno, "Failed open to read on %s", name); | |
133 | if (zflag) | |
134 | ar_start_gzip(arfd); | |
135 | break; | |
136 | case ARCHIVE: | |
137 | if (name == NULL) { | |
138 | arfd = STDOUT_FILENO; | |
139 | arcname = STDO; | |
140 | } else if ((arfd = open(name, AR_MODE, DMOD)) < 0) | |
141 | syswarn(0, errno, "Failed open to write on %s", name); | |
142 | else | |
143 | can_unlnk = 1; | |
144 | if (zflag) | |
145 | ar_start_gzip(arfd); | |
146 | break; | |
147 | case APPND: | |
148 | if (zflag) | |
149 | err(1, "can not gzip while appending"); | |
150 | if (name == NULL) { | |
151 | arfd = STDOUT_FILENO; | |
152 | arcname = STDO; | |
153 | } else if ((arfd = open(name, APP_MODE, DMOD)) < 0) | |
154 | syswarn(0, errno, "Failed open to read/write on %s", | |
155 | name); | |
156 | break; | |
157 | case COPY: | |
158 | /* | |
159 | * arfd not used in COPY mode | |
160 | */ | |
161 | arcname = "<NONE>"; | |
162 | lstrval = 1; | |
163 | return(0); | |
164 | } | |
165 | if (arfd < 0) | |
166 | return(-1); | |
167 | ||
168 | if (chdname != NULL) | |
169 | if (chdir(chdname) != 0) | |
170 | syswarn(1, errno, "Failed chdir to %s", chdname); | |
171 | /* | |
172 | * set up is based on device type | |
173 | */ | |
174 | if (fstat(arfd, &arsb) < 0) { | |
175 | syswarn(0, errno, "Failed stat on %s", arcname); | |
176 | (void)close(arfd); | |
177 | arfd = -1; | |
178 | can_unlnk = 0; | |
179 | return(-1); | |
180 | } | |
181 | if (S_ISDIR(arsb.st_mode)) { | |
182 | paxwarn(0, "Cannot write an archive on top of a directory %s", | |
183 | arcname); | |
184 | (void)close(arfd); | |
185 | arfd = -1; | |
186 | can_unlnk = 0; | |
187 | return(-1); | |
188 | } | |
189 | ||
190 | if (S_ISCHR(arsb.st_mode)) | |
191 | artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE; | |
192 | else if (S_ISBLK(arsb.st_mode)) | |
193 | artyp = ISBLK; | |
194 | else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE)) | |
195 | artyp = ISPIPE; | |
196 | else | |
197 | artyp = ISREG; | |
198 | ||
199 | /* | |
200 | * make sure we beyond any doubt that we only can unlink regular files | |
201 | * we created | |
202 | */ | |
203 | if (artyp != ISREG) | |
204 | can_unlnk = 0; | |
205 | /* | |
206 | * if we are writing, we are done | |
207 | */ | |
208 | if (act == ARCHIVE) { | |
209 | blksz = rdblksz = wrblksz; | |
210 | lstrval = 1; | |
211 | return(0); | |
212 | } | |
213 | ||
214 | /* | |
215 | * set default blksz on read. APPNDs writes rdblksz on the last volume | |
216 | * On all new archive volumes, we shift to wrblksz (if the user | |
217 | * specified one, otherwize we will continue to use rdblksz). We | |
218 | * must to set blocksize based on what kind of device the archive is | |
219 | * stored. | |
220 | */ | |
221 | switch(artyp) { | |
222 | case ISTAPE: | |
223 | /* | |
224 | * Tape drives come in at least two flavors. Those that support | |
225 | * variable sized records and those that have fixed sized | |
226 | * records. They must be treated differently. For tape drives | |
227 | * that support variable sized records, we must make large | |
228 | * reads to make sure we get the entire record, otherwise we | |
229 | * will just get the first part of the record (up to size we | |
230 | * asked). Tapes with fixed sized records may or may not return | |
231 | * multiple records in a single read. We really do not care | |
232 | * what the physical record size is UNLESS we are going to | |
233 | * append. (We will need the physical block size to rewrite | |
234 | * the trailer). Only when we are appending do we go to the | |
235 | * effort to figure out the true PHYSICAL record size. | |
236 | */ | |
237 | blksz = rdblksz = MAXBLK; | |
238 | break; | |
239 | case ISPIPE: | |
240 | case ISBLK: | |
241 | case ISCHR: | |
242 | /* | |
243 | * Blocksize is not a major issue with these devices (but must | |
244 | * be kept a multiple of 512). If the user specified a write | |
245 | * block size, we use that to read. Under append, we must | |
246 | * always keep blksz == rdblksz. Otherwise we go ahead and use | |
247 | * the device optimal blocksize as (and if) returned by stat | |
248 | * and if it is within pax specs. | |
249 | */ | |
250 | if ((act == APPND) && wrblksz) { | |
251 | blksz = rdblksz = wrblksz; | |
252 | break; | |
253 | } | |
254 | ||
255 | if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) && | |
256 | ((arsb.st_blksize % BLKMULT) == 0)) | |
257 | rdblksz = arsb.st_blksize; | |
258 | else | |
259 | rdblksz = DEVBLK; | |
260 | /* | |
261 | * For performance go for large reads when we can without harm | |
262 | */ | |
263 | if ((act == APPND) || (artyp == ISCHR)) | |
264 | blksz = rdblksz; | |
265 | else | |
266 | blksz = MAXBLK; | |
267 | break; | |
268 | case ISREG: | |
269 | /* | |
270 | * if the user specified wrblksz works, use it. Under appends | |
271 | * we must always keep blksz == rdblksz | |
272 | */ | |
273 | if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){ | |
274 | blksz = rdblksz = wrblksz; | |
275 | break; | |
276 | } | |
277 | /* | |
278 | * See if we can find the blocking factor from the file size | |
279 | */ | |
280 | for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT) | |
281 | if ((arsb.st_size % rdblksz) == 0) | |
282 | break; | |
283 | /* | |
284 | * When we cannont find a match, we may have a flawed archive. | |
285 | */ | |
286 | if (rdblksz <= 0) | |
287 | rdblksz = FILEBLK; | |
288 | /* | |
289 | * for performance go for large reads when we can | |
290 | */ | |
291 | if (act == APPND) | |
292 | blksz = rdblksz; | |
293 | else | |
294 | blksz = MAXBLK; | |
295 | break; | |
296 | default: | |
297 | /* | |
298 | * should never happen, worse case, slow... | |
299 | */ | |
300 | blksz = rdblksz = BLKMULT; | |
301 | break; | |
302 | } | |
303 | lstrval = 1; | |
304 | return(0); | |
305 | } | |
306 | ||
307 | /* | |
308 | * ar_close() | |
309 | * closes archive device, increments volume number, and prints i/o summary | |
310 | */ | |
311 | #ifdef __STDC__ | |
312 | void | |
313 | ar_close(void) | |
314 | #else | |
315 | void | |
316 | ar_close() | |
317 | #endif | |
318 | { | |
319 | FILE *outf; | |
320 | ||
321 | if (arfd < 0) { | |
322 | did_io = io_ok = flcnt = 0; | |
323 | return; | |
324 | } | |
325 | ||
326 | if (act == LIST) | |
327 | outf = stdout; | |
328 | else | |
329 | outf = stderr; | |
330 | ||
331 | /* | |
332 | * Close archive file. This may take a LONG while on tapes (we may be | |
333 | * forced to wait for the rewind to complete) so tell the user what is | |
334 | * going on (this avoids the user hitting control-c thinking pax is | |
335 | * broken). | |
336 | */ | |
337 | if (vflag && (artyp == ISTAPE)) { | |
338 | if (vfpart) | |
339 | (void)putc('\n', outf); | |
340 | (void)fprintf(outf, | |
341 | "%s: Waiting for tape drive close to complete...", | |
342 | argv0); | |
343 | (void)fflush(outf); | |
344 | } | |
345 | ||
346 | /* | |
347 | * if nothing was written to the archive (and we created it), we remove | |
348 | * it | |
349 | */ | |
350 | if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) && | |
351 | (arsb.st_size == 0)) { | |
352 | (void)unlink(arcname); | |
353 | can_unlnk = 0; | |
354 | } | |
355 | ||
356 | (void)close(arfd); | |
357 | ||
358 | if (vflag && (artyp == ISTAPE)) { | |
359 | (void)fputs("done.\n", outf); | |
360 | vfpart = 0; | |
361 | (void)fflush(outf); | |
362 | } | |
363 | arfd = -1; | |
364 | ||
365 | if (!io_ok && !did_io) { | |
366 | flcnt = 0; | |
367 | return; | |
368 | } | |
369 | did_io = io_ok = 0; | |
370 | ||
371 | /* | |
372 | * The volume number is only increased when the last device has data | |
373 | * and we have already determined the archive format. | |
374 | */ | |
375 | if (frmt != NULL) | |
376 | ++arvol; | |
377 | ||
378 | if (!vflag) { | |
379 | flcnt = 0; | |
380 | return; | |
381 | } | |
382 | ||
383 | /* | |
384 | * Print out a summary of I/O for this archive volume. | |
385 | */ | |
386 | if (vfpart) { | |
387 | (void)putc('\n', outf); | |
388 | vfpart = 0; | |
389 | } | |
390 | ||
391 | /* | |
392 | * If we have not determined the format yet, we just say how many bytes | |
393 | * we have skipped over looking for a header to id. there is no way we | |
394 | * could have written anything yet. | |
395 | */ | |
396 | if (frmt == NULL) { | |
397 | # ifdef NET2_STAT | |
398 | (void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n", | |
399 | # else | |
400 | (void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n", | |
401 | # endif | |
402 | argv0, rdcnt); | |
403 | (void)fflush(outf); | |
404 | flcnt = 0; | |
405 | return; | |
406 | } | |
407 | ||
408 | if (strcmp(NM_CPIO, argv0) == 0) | |
409 | (void)fprintf(outf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120); | |
410 | else if (strcmp(NM_TAR, argv0) != 0) | |
411 | (void)fprintf(outf, | |
412 | # ifdef NET2_STAT | |
413 | "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n", | |
414 | # else | |
415 | "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n", | |
416 | # endif | |
417 | argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt); | |
418 | (void)fflush(outf); | |
419 | flcnt = 0; | |
420 | } | |
421 | ||
422 | /* | |
423 | * ar_drain() | |
424 | * drain any archive format independent padding from an archive read | |
425 | * from a socket or a pipe. This is to prevent the process on the | |
426 | * other side of the pipe from getting a SIGPIPE (pax will stop | |
427 | * reading an archive once a format dependent trailer is detected). | |
428 | */ | |
429 | #ifdef __STDC__ | |
430 | void | |
431 | ar_drain(void) | |
432 | #else | |
433 | void | |
434 | ar_drain() | |
435 | #endif | |
436 | { | |
437 | register int res; | |
438 | char drbuf[MAXBLK]; | |
439 | ||
440 | /* | |
441 | * we only drain from a pipe/socket. Other devices can be closed | |
442 | * without reading up to end of file. We sure hope that pipe is closed | |
443 | * on the other side so we will get an EOF. | |
444 | */ | |
445 | if ((artyp != ISPIPE) || (lstrval <= 0)) | |
446 | return; | |
447 | ||
448 | /* | |
449 | * keep reading until pipe is drained | |
450 | */ | |
451 | while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0) | |
452 | ; | |
453 | lstrval = res; | |
454 | } | |
455 | ||
456 | /* | |
457 | * ar_set_wr() | |
458 | * Set up device right before switching from read to write in an append. | |
459 | * device dependent code (if required) to do this should be added here. | |
460 | * For all archive devices we are already positioned at the place we want | |
461 | * to start writing when this routine is called. | |
462 | * Return: | |
463 | * 0 if all ready to write, -1 otherwise | |
464 | */ | |
465 | ||
466 | #ifdef __STDC__ | |
467 | int | |
468 | ar_set_wr(void) | |
469 | #else | |
470 | int | |
471 | ar_set_wr() | |
472 | #endif | |
473 | { | |
474 | off_t cpos; | |
475 | ||
476 | /* | |
477 | * we must make sure the trailer is rewritten on append, ar_next() | |
478 | * will stop us if the archive containing the trailer was not written | |
479 | */ | |
480 | wr_trail = 0; | |
481 | ||
482 | /* | |
483 | * Add any device dependent code as required here | |
484 | */ | |
485 | if (artyp != ISREG) | |
486 | return(0); | |
487 | /* | |
488 | * Ok we have an archive in a regular file. If we were rewriting a | |
489 | * file, we must get rid of all the stuff after the current offset | |
490 | * (it was not written by pax). | |
491 | */ | |
492 | if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) || | |
493 | (ftruncate(arfd, cpos) < 0)) { | |
494 | syswarn(1, errno, "Unable to truncate archive file"); | |
495 | return(-1); | |
496 | } | |
497 | return(0); | |
498 | } | |
499 | ||
500 | /* | |
501 | * ar_app_ok() | |
502 | * check if the last volume in the archive allows appends. We cannot check | |
503 | * this until we are ready to write since there is no spec that says all | |
504 | * volumes in a single archive have to be of the same type... | |
505 | * Return: | |
506 | * 0 if we can append, -1 otherwise. | |
507 | */ | |
508 | ||
509 | #ifdef __STDC__ | |
510 | int | |
511 | ar_app_ok(void) | |
512 | #else | |
513 | int | |
514 | ar_app_ok() | |
515 | #endif | |
516 | { | |
517 | if (artyp == ISPIPE) { | |
518 | paxwarn(1, "Cannot append to an archive obtained from a pipe."); | |
519 | return(-1); | |
520 | } | |
521 | ||
522 | if (!invld_rec) | |
523 | return(0); | |
524 | paxwarn(1,"Cannot append, device record size %d does not support %s spec", | |
525 | rdblksz, argv0); | |
526 | return(-1); | |
527 | } | |
528 | ||
529 | /* | |
530 | * ar_read() | |
531 | * read up to a specified number of bytes from the archive into the | |
532 | * supplied buffer. When dealing with tapes we may not always be able to | |
533 | * read what we want. | |
534 | * Return: | |
535 | * Number of bytes in buffer. 0 for end of file, -1 for a read error. | |
536 | */ | |
537 | ||
538 | #ifdef __STDC__ | |
539 | int | |
540 | ar_read(register char *buf, register int cnt) | |
541 | #else | |
542 | int | |
543 | ar_read(buf, cnt) | |
544 | register char *buf; | |
545 | register int cnt; | |
546 | #endif | |
547 | { | |
548 | register int res = 0; | |
549 | ||
550 | /* | |
551 | * if last i/o was in error, no more reads until reset or new volume | |
552 | */ | |
553 | if (lstrval <= 0) | |
554 | return(lstrval); | |
555 | ||
556 | /* | |
557 | * how we read must be based on device type | |
558 | */ | |
559 | switch (artyp) { | |
560 | case ISTAPE: | |
561 | if ((res = read(arfd, buf, cnt)) > 0) { | |
562 | /* | |
563 | * CAUTION: tape systems may not always return the same | |
564 | * sized records so we leave blksz == MAXBLK. The | |
565 | * physical record size that a tape drive supports is | |
566 | * very hard to determine in a uniform and portable | |
567 | * manner. | |
568 | */ | |
569 | io_ok = 1; | |
570 | if (res != rdblksz) { | |
571 | /* | |
572 | * Record size changed. If this is happens on | |
573 | * any record after the first, we probably have | |
574 | * a tape drive which has a fixed record size | |
575 | * we are getting multiple records in a single | |
576 | * read). Watch out for record blocking that | |
577 | * violates pax spec (must be a multiple of | |
578 | * BLKMULT). | |
579 | */ | |
580 | rdblksz = res; | |
581 | if (rdblksz % BLKMULT) | |
582 | invld_rec = 1; | |
583 | } | |
584 | return(res); | |
585 | } | |
586 | break; | |
587 | case ISREG: | |
588 | case ISBLK: | |
589 | case ISCHR: | |
590 | case ISPIPE: | |
591 | default: | |
592 | /* | |
593 | * Files are so easy to deal with. These other things cannot | |
594 | * be trusted at all. So when we are dealing with character | |
595 | * devices and pipes we just take what they have ready for us | |
596 | * and return. Trying to do anything else with them runs the | |
597 | * risk of failure. | |
598 | */ | |
599 | if ((res = read(arfd, buf, cnt)) > 0) { | |
600 | io_ok = 1; | |
601 | return(res); | |
602 | } | |
603 | break; | |
604 | } | |
605 | ||
606 | /* | |
607 | * We are in trouble at this point, something is broken... | |
608 | */ | |
609 | lstrval = res; | |
610 | if (res < 0) | |
611 | syswarn(1, errno, "Failed read on archive volume %d", arvol); | |
612 | else | |
613 | paxwarn(0, "End of archive volume %d reached", arvol); | |
614 | return(res); | |
615 | } | |
616 | ||
617 | /* | |
618 | * ar_write() | |
619 | * Write a specified number of bytes in supplied buffer to the archive | |
620 | * device so it appears as a single "block". Deals with errors and tries | |
621 | * to recover when faced with short writes. | |
622 | * Return: | |
623 | * Number of bytes written. 0 indicates end of volume reached and with no | |
624 | * flaws (as best that can be detected). A -1 indicates an unrecoverable | |
625 | * error in the archive occured. | |
626 | */ | |
627 | ||
628 | #ifdef __STDC__ | |
629 | int | |
630 | ar_write(register char *buf, register int bsz) | |
631 | #else | |
632 | int | |
633 | ar_write(buf, bsz) | |
634 | register char *buf; | |
635 | register int bsz; | |
636 | #endif | |
637 | { | |
638 | register int res; | |
639 | off_t cpos; | |
640 | ||
641 | /* | |
642 | * do not allow pax to create a "bad" archive. Once a write fails on | |
643 | * an archive volume prevent further writes to it. | |
644 | */ | |
645 | if (lstrval <= 0) | |
646 | return(lstrval); | |
647 | ||
648 | if ((res = write(arfd, buf, bsz)) == bsz) { | |
649 | wr_trail = 1; | |
650 | io_ok = 1; | |
651 | return(bsz); | |
652 | } | |
653 | /* | |
654 | * write broke, see what we can do with it. We try to send any partial | |
655 | * writes that may violate pax spec to the next archive volume. | |
656 | */ | |
657 | if (res < 0) | |
658 | lstrval = res; | |
659 | else | |
660 | lstrval = 0; | |
661 | ||
662 | switch (artyp) { | |
663 | case ISREG: | |
664 | if ((res > 0) && (res % BLKMULT)) { | |
665 | /* | |
666 | * try to fix up partial writes which are not BLKMULT | |
667 | * in size by forcing the runt record to next archive | |
668 | * volume | |
669 | */ | |
670 | if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) | |
671 | break; | |
672 | cpos -= (off_t)res; | |
673 | if (ftruncate(arfd, cpos) < 0) | |
674 | break; | |
675 | res = lstrval = 0; | |
676 | break; | |
677 | } | |
678 | if (res >= 0) | |
679 | break; | |
680 | /* | |
681 | * if file is out of space, handle it like a return of 0 | |
682 | */ | |
683 | if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT)) | |
684 | res = lstrval = 0; | |
685 | break; | |
686 | case ISTAPE: | |
687 | case ISCHR: | |
688 | case ISBLK: | |
689 | if (res >= 0) | |
690 | break; | |
691 | if (errno == EACCES) { | |
692 | paxwarn(0, "Write failed, archive is write protected."); | |
693 | res = lstrval = 0; | |
694 | return(0); | |
695 | } | |
696 | /* | |
697 | * see if we reached the end of media, if so force a change to | |
698 | * the next volume | |
699 | */ | |
700 | if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO)) | |
701 | res = lstrval = 0; | |
702 | break; | |
703 | case ISPIPE: | |
704 | default: | |
705 | /* | |
706 | * we cannot fix errors to these devices | |
707 | */ | |
708 | break; | |
709 | } | |
710 | ||
711 | /* | |
712 | * Better tell the user the bad news... | |
713 | * if this is a block aligned archive format, we may have a bad archive | |
714 | * if the format wants the header to start at a BLKMULT boundry. While | |
715 | * we can deal with the mis-aligned data, it violates spec and other | |
716 | * archive readers will likely fail. if the format is not block | |
717 | * aligned, the user may be lucky (and the archive is ok). | |
718 | */ | |
719 | if (res >= 0) { | |
720 | if (res > 0) | |
721 | wr_trail = 1; | |
722 | io_ok = 1; | |
723 | } | |
724 | ||
725 | /* | |
726 | * If we were trying to rewrite the trailer and it didn't work, we | |
727 | * must quit right away. | |
728 | */ | |
729 | if (!wr_trail && (res <= 0)) { | |
730 | paxwarn(1,"Unable to append, trailer re-write failed. Quitting."); | |
731 | return(res); | |
732 | } | |
733 | ||
734 | if (res == 0) | |
735 | paxwarn(0, "End of archive volume %d reached", arvol); | |
736 | else if (res < 0) | |
737 | syswarn(1, errno, "Failed write to archive volume: %d", arvol); | |
738 | else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0)) | |
739 | paxwarn(0,"WARNING: partial archive write. Archive MAY BE FLAWED"); | |
740 | else | |
741 | paxwarn(1,"WARNING: partial archive write. Archive IS FLAWED"); | |
742 | return(res); | |
743 | } | |
744 | ||
745 | /* | |
746 | * ar_rdsync() | |
747 | * Try to move past a bad spot on a flawed archive as needed to continue | |
748 | * I/O. Clears error flags to allow I/O to continue. | |
749 | * Return: | |
750 | * 0 when ok to try i/o again, -1 otherwise. | |
751 | */ | |
752 | ||
753 | #ifdef __STDC__ | |
754 | int | |
755 | ar_rdsync(void) | |
756 | #else | |
757 | int | |
758 | ar_rdsync() | |
759 | #endif | |
760 | { | |
761 | long fsbz; | |
762 | off_t cpos; | |
763 | off_t mpos; | |
764 | struct mtop mb; | |
765 | ||
766 | /* | |
767 | * Fail resync attempts at user request (done) or this is going to be | |
768 | * an update/append to a existing archive. if last i/o hit media end, | |
769 | * we need to go to the next volume not try a resync | |
770 | */ | |
771 | if ((done > 0) || (lstrval == 0)) | |
772 | return(-1); | |
773 | ||
774 | if ((act == APPND) || (act == ARCHIVE)) { | |
775 | paxwarn(1, "Cannot allow updates to an archive with flaws."); | |
776 | return(-1); | |
777 | } | |
778 | if (io_ok) | |
779 | did_io = 1; | |
780 | ||
781 | switch(artyp) { | |
782 | case ISTAPE: | |
783 | /* | |
784 | * if the last i/o was a successful data transfer, we assume | |
785 | * the fault is just a bad record on the tape that we are now | |
786 | * past. If we did not get any data since the last resync try | |
787 | * to move the tape foward one PHYSICAL record past any | |
788 | * damaged tape section. Some tape drives are stubborn and need | |
789 | * to be pushed. | |
790 | */ | |
791 | if (io_ok) { | |
792 | io_ok = 0; | |
793 | lstrval = 1; | |
794 | break; | |
795 | } | |
796 | mb.mt_op = MTFSR; | |
797 | mb.mt_count = 1; | |
798 | if (ioctl(arfd, MTIOCTOP, &mb) < 0) | |
799 | break; | |
800 | lstrval = 1; | |
801 | break; | |
802 | case ISREG: | |
803 | case ISCHR: | |
804 | case ISBLK: | |
805 | /* | |
806 | * try to step over the bad part of the device. | |
807 | */ | |
808 | io_ok = 0; | |
809 | if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG)) | |
810 | fsbz = BLKMULT; | |
811 | if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) | |
812 | break; | |
813 | mpos = fsbz - (cpos % (off_t)fsbz); | |
814 | if (lseek(arfd, mpos, SEEK_CUR) < 0) | |
815 | break; | |
816 | lstrval = 1; | |
817 | break; | |
818 | case ISPIPE: | |
819 | default: | |
820 | /* | |
821 | * cannot recover on these archive device types | |
822 | */ | |
823 | io_ok = 0; | |
824 | break; | |
825 | } | |
826 | if (lstrval <= 0) { | |
827 | paxwarn(1, "Unable to recover from an archive read failure."); | |
828 | return(-1); | |
829 | } | |
830 | paxwarn(0, "Attempting to recover from an archive read failure."); | |
831 | return(0); | |
832 | } | |
833 | ||
834 | /* | |
835 | * ar_fow() | |
836 | * Move the I/O position within the archive foward the specified number of | |
837 | * bytes as supported by the device. If we cannot move the requested | |
838 | * number of bytes, return the actual number of bytes moved in skipped. | |
839 | * Return: | |
840 | * 0 if moved the requested distance, -1 on complete failure, 1 on | |
841 | * partial move (the amount moved is in skipped) | |
842 | */ | |
843 | ||
844 | #ifdef __STDC__ | |
845 | int | |
846 | ar_fow(off_t sksz, off_t *skipped) | |
847 | #else | |
848 | int | |
849 | ar_fow(sksz, skipped) | |
850 | off_t sksz; | |
851 | off_t *skipped; | |
852 | #endif | |
853 | { | |
854 | off_t cpos; | |
855 | off_t mpos; | |
856 | ||
857 | *skipped = 0; | |
858 | if (sksz <= 0) | |
859 | return(0); | |
860 | ||
861 | /* | |
862 | * we cannot move foward at EOF or error | |
863 | */ | |
864 | if (lstrval <= 0) | |
865 | return(lstrval); | |
866 | ||
867 | /* | |
868 | * Safer to read forward on devices where it is hard to find the end of | |
869 | * the media without reading to it. With tapes we cannot be sure of the | |
870 | * number of physical blocks to skip (we do not know physical block | |
871 | * size at this point), so we must only read foward on tapes! | |
872 | */ | |
873 | if (artyp != ISREG) | |
874 | return(0); | |
875 | ||
876 | /* | |
877 | * figure out where we are in the archive | |
878 | */ | |
879 | if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) { | |
880 | /* | |
881 | * we can be asked to move farther than there are bytes in this | |
882 | * volume, if so, just go to file end and let normal buf_fill() | |
883 | * deal with the end of file (it will go to next volume by | |
884 | * itself) | |
885 | */ | |
886 | if ((mpos = cpos + sksz) > arsb.st_size) { | |
887 | *skipped = arsb.st_size - cpos; | |
888 | mpos = arsb.st_size; | |
889 | } else | |
890 | *skipped = sksz; | |
891 | if (lseek(arfd, mpos, SEEK_SET) >= 0) | |
892 | return(0); | |
893 | } | |
894 | syswarn(1, errno, "Foward positioning operation on archive failed"); | |
895 | lstrval = -1; | |
896 | return(-1); | |
897 | } | |
898 | ||
899 | /* | |
900 | * ar_rev() | |
901 | * move the i/o position within the archive backwards the specified byte | |
902 | * count as supported by the device. With tapes drives we RESET rdblksz to | |
903 | * the PHYSICAL blocksize. | |
904 | * NOTE: We should only be called to move backwards so we can rewrite the | |
905 | * last records (the trailer) of an archive (APPEND). | |
906 | * Return: | |
907 | * 0 if moved the requested distance, -1 on complete failure | |
908 | */ | |
909 | ||
910 | #ifdef __STDC__ | |
911 | int | |
912 | ar_rev(off_t sksz) | |
913 | #else | |
914 | int | |
915 | ar_rev(sksz) | |
916 | off_t sksz; | |
917 | #endif | |
918 | { | |
919 | off_t cpos; | |
920 | struct mtop mb; | |
921 | register int phyblk; | |
922 | ||
923 | /* | |
924 | * make sure we do not have try to reverse on a flawed archive | |
925 | */ | |
926 | if (lstrval < 0) | |
927 | return(lstrval); | |
928 | ||
929 | switch(artyp) { | |
930 | case ISPIPE: | |
931 | if (sksz <= 0) | |
932 | break; | |
933 | /* | |
934 | * cannot go backwards on these critters | |
935 | */ | |
936 | paxwarn(1, "Reverse positioning on pipes is not supported."); | |
937 | lstrval = -1; | |
938 | return(-1); | |
939 | case ISREG: | |
940 | case ISBLK: | |
941 | case ISCHR: | |
942 | default: | |
943 | if (sksz <= 0) | |
944 | break; | |
945 | ||
946 | /* | |
947 | * For things other than files, backwards movement has a very | |
948 | * high probability of failure as we really do not know the | |
949 | * true attributes of the device we are talking to (the device | |
950 | * may not even have the ability to lseek() in any direction). | |
951 | * First we figure out where we are in the archive. | |
952 | */ | |
953 | if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) { | |
954 | syswarn(1, errno, | |
955 | "Unable to obtain current archive byte offset"); | |
956 | lstrval = -1; | |
957 | return(-1); | |
958 | } | |
959 | ||
960 | /* | |
961 | * we may try to go backwards past the start when the archive | |
962 | * is only a single record. If this hapens and we are on a | |
963 | * multi volume archive, we need to go to the end of the | |
964 | * previous volume and continue our movement backwards from | |
965 | * there. | |
966 | */ | |
967 | if ((cpos -= sksz) < (off_t)0L) { | |
968 | if (arvol > 1) { | |
969 | /* | |
970 | * this should never happen | |
971 | */ | |
972 | paxwarn(1,"Reverse position on previous volume."); | |
973 | lstrval = -1; | |
974 | return(-1); | |
975 | } | |
976 | cpos = (off_t)0L; | |
977 | } | |
978 | if (lseek(arfd, cpos, SEEK_SET) < 0) { | |
979 | syswarn(1, errno, "Unable to seek archive backwards"); | |
980 | lstrval = -1; | |
981 | return(-1); | |
982 | } | |
983 | break; | |
984 | case ISTAPE: | |
985 | /* | |
986 | * Calculate and move the proper number of PHYSICAL tape | |
987 | * blocks. If the sksz is not an even multiple of the physical | |
988 | * tape size, we cannot do the move (this should never happen). | |
989 | * (We also cannot handler trailers spread over two vols). | |
990 | * get_phys() also makes sure we are in front of the filemark. | |
991 | */ | |
992 | if ((phyblk = get_phys()) <= 0) { | |
993 | lstrval = -1; | |
994 | return(-1); | |
995 | } | |
996 | ||
997 | /* | |
998 | * make sure future tape reads only go by physical tape block | |
999 | * size (set rdblksz to the real size). | |
1000 | */ | |
1001 | rdblksz = phyblk; | |
1002 | ||
1003 | /* | |
1004 | * if no movement is required, just return (we must be after | |
1005 | * get_phys() so the physical blocksize is properly set) | |
1006 | */ | |
1007 | if (sksz <= 0) | |
1008 | break; | |
1009 | ||
1010 | /* | |
1011 | * ok we have to move. Make sure the tape drive can do it. | |
1012 | */ | |
1013 | if (sksz % phyblk) { | |
1014 | paxwarn(1, | |
1015 | "Tape drive unable to backspace requested amount"); | |
1016 | lstrval = -1; | |
1017 | return(-1); | |
1018 | } | |
1019 | ||
1020 | /* | |
1021 | * move backwards the requested number of bytes | |
1022 | */ | |
1023 | mb.mt_op = MTBSR; | |
1024 | mb.mt_count = sksz/phyblk; | |
1025 | if (ioctl(arfd, MTIOCTOP, &mb) < 0) { | |
1026 | syswarn(1,errno, "Unable to backspace tape %d blocks.", | |
1027 | mb.mt_count); | |
1028 | lstrval = -1; | |
1029 | return(-1); | |
1030 | } | |
1031 | break; | |
1032 | } | |
1033 | lstrval = 1; | |
1034 | return(0); | |
1035 | } | |
1036 | ||
1037 | /* | |
1038 | * get_phys() | |
1039 | * Determine the physical block size on a tape drive. We need the physical | |
1040 | * block size so we know how many bytes we skip over when we move with | |
1041 | * mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when | |
1042 | * return. | |
1043 | * This is one really SLOW routine... | |
1044 | * Return: | |
1045 | * physical block size if ok (ok > 0), -1 otherwise | |
1046 | */ | |
1047 | ||
1048 | #ifdef __STDC__ | |
1049 | static int | |
1050 | get_phys(void) | |
1051 | #else | |
1052 | static int | |
1053 | get_phys() | |
1054 | #endif | |
1055 | { | |
1056 | register int padsz = 0; | |
1057 | register int res; | |
1058 | register int phyblk; | |
1059 | struct mtop mb; | |
1060 | char scbuf[MAXBLK]; | |
1061 | ||
1062 | /* | |
1063 | * move to the file mark, and then back up one record and read it. | |
1064 | * this should tell us the physical record size the tape is using. | |
1065 | */ | |
1066 | if (lstrval == 1) { | |
1067 | /* | |
1068 | * we know we are at file mark when we get back a 0 from | |
1069 | * read() | |
1070 | */ | |
1071 | while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) | |
1072 | padsz += res; | |
1073 | if (res < 0) { | |
1074 | syswarn(1, errno, "Unable to locate tape filemark."); | |
1075 | return(-1); | |
1076 | } | |
1077 | } | |
1078 | ||
1079 | /* | |
1080 | * move backwards over the file mark so we are at the end of the | |
1081 | * last record. | |
1082 | */ | |
1083 | mb.mt_op = MTBSF; | |
1084 | mb.mt_count = 1; | |
1085 | if (ioctl(arfd, MTIOCTOP, &mb) < 0) { | |
1086 | syswarn(1, errno, "Unable to backspace over tape filemark."); | |
1087 | return(-1); | |
1088 | } | |
1089 | ||
1090 | /* | |
1091 | * move backwards so we are in front of the last record and read it to | |
1092 | * get physical tape blocksize. | |
1093 | */ | |
1094 | mb.mt_op = MTBSR; | |
1095 | mb.mt_count = 1; | |
1096 | if (ioctl(arfd, MTIOCTOP, &mb) < 0) { | |
1097 | syswarn(1, errno, "Unable to backspace over last tape block."); | |
1098 | return(-1); | |
1099 | } | |
1100 | if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) { | |
1101 | syswarn(1, errno, "Cannot determine archive tape blocksize."); | |
1102 | return(-1); | |
1103 | } | |
1104 | ||
1105 | /* | |
1106 | * read foward to the file mark, then back up in front of the filemark | |
1107 | * (this is a bit paranoid, but should be safe to do). | |
1108 | */ | |
1109 | while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0) | |
1110 | ; | |
1111 | if (res < 0) { | |
1112 | syswarn(1, errno, "Unable to locate tape filemark."); | |
1113 | return(-1); | |
1114 | } | |
1115 | mb.mt_op = MTBSF; | |
1116 | mb.mt_count = 1; | |
1117 | if (ioctl(arfd, MTIOCTOP, &mb) < 0) { | |
1118 | syswarn(1, errno, "Unable to backspace over tape filemark."); | |
1119 | return(-1); | |
1120 | } | |
1121 | ||
1122 | /* | |
1123 | * set lstrval so we know that the filemark has not been seen | |
1124 | */ | |
1125 | lstrval = 1; | |
1126 | ||
1127 | /* | |
1128 | * return if there was no padding | |
1129 | */ | |
1130 | if (padsz == 0) | |
1131 | return(phyblk); | |
1132 | ||
1133 | /* | |
1134 | * make sure we can move backwards over the padding. (this should | |
1135 | * never fail). | |
1136 | */ | |
1137 | if (padsz % phyblk) { | |
1138 | paxwarn(1, "Tape drive unable to backspace requested amount"); | |
1139 | return(-1); | |
1140 | } | |
1141 | ||
1142 | /* | |
1143 | * move backwards over the padding so the head is where it was when | |
1144 | * we were first called (if required). | |
1145 | */ | |
1146 | mb.mt_op = MTBSR; | |
1147 | mb.mt_count = padsz/phyblk; | |
1148 | if (ioctl(arfd, MTIOCTOP, &mb) < 0) { | |
1149 | syswarn(1,errno,"Unable to backspace tape over %d pad blocks", | |
1150 | mb.mt_count); | |
1151 | return(-1); | |
1152 | } | |
1153 | return(phyblk); | |
1154 | } | |
1155 | ||
1156 | /* | |
1157 | * ar_next() | |
1158 | * prompts the user for the next volume in this archive. For some devices | |
1159 | * we may allow the media to be changed. Otherwise a new archive is | |
1160 | * prompted for. By pax spec, if there is no controlling tty or an eof is | |
1161 | * read on tty input, we must quit pax. | |
1162 | * Return: | |
1163 | * 0 when ready to continue, -1 when all done | |
1164 | */ | |
1165 | ||
1166 | #ifdef __STDC__ | |
1167 | int | |
1168 | ar_next(void) | |
1169 | #else | |
1170 | int | |
1171 | ar_next() | |
1172 | #endif | |
1173 | { | |
1174 | char buf[PAXPATHLEN+2]; | |
1175 | static int freeit = 0; | |
1176 | sigset_t o_mask; | |
1177 | ||
1178 | /* | |
1179 | * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so | |
1180 | * things like writing EOF etc will be done) (Watch out ar_close() can | |
1181 | * also be called via a signal handler, so we must prevent a race. | |
1182 | */ | |
1183 | if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0) | |
1184 | syswarn(0, errno, "Unable to set signal mask"); | |
1185 | ar_close(); | |
1186 | if (sigprocmask(SIG_SETMASK, &o_mask, NULL) < 0) | |
1187 | syswarn(0, errno, "Unable to restore signal mask"); | |
1188 | ||
1189 | if (done || !wr_trail || strcmp(NM_TAR, argv0) == 0) | |
1190 | return(-1); | |
1191 | ||
1192 | tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0); | |
1193 | ||
1194 | /* | |
1195 | * if i/o is on stdin or stdout, we cannot reopen it (we do not know | |
1196 | * the name), the user will be forced to type it in. | |
1197 | */ | |
1198 | if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG) | |
1199 | && (artyp != ISPIPE)) { | |
1200 | if (artyp == ISTAPE) { | |
1201 | tty_prnt("%s ready for archive tape volume: %d\n", | |
1202 | arcname, arvol); | |
1203 | tty_prnt("Load the NEXT TAPE on the tape drive"); | |
1204 | } else { | |
1205 | tty_prnt("%s ready for archive volume: %d\n", | |
1206 | arcname, arvol); | |
1207 | tty_prnt("Load the NEXT STORAGE MEDIA (if required)"); | |
1208 | } | |
1209 | ||
1210 | if ((act == ARCHIVE) || (act == APPND)) | |
1211 | tty_prnt(" and make sure it is WRITE ENABLED.\n"); | |
1212 | else | |
1213 | tty_prnt("\n"); | |
1214 | ||
1215 | for(;;) { | |
1216 | tty_prnt("Type \"y\" to continue, \".\" to quit %s,", | |
1217 | argv0); | |
1218 | tty_prnt(" or \"s\" to switch to new device.\nIf you"); | |
1219 | tty_prnt(" cannot change storage media, type \"s\"\n"); | |
1220 | tty_prnt("Is the device ready and online? > "); | |
1221 | ||
1222 | if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){ | |
1223 | done = 1; | |
1224 | lstrval = -1; | |
1225 | tty_prnt("Quitting %s!\n", argv0); | |
1226 | vfpart = 0; | |
1227 | return(-1); | |
1228 | } | |
1229 | ||
1230 | if ((buf[0] == '\0') || (buf[1] != '\0')) { | |
1231 | tty_prnt("%s unknown command, try again\n",buf); | |
1232 | continue; | |
1233 | } | |
1234 | ||
1235 | switch (buf[0]) { | |
1236 | case 'y': | |
1237 | case 'Y': | |
1238 | /* | |
1239 | * we are to continue with the same device | |
1240 | */ | |
1241 | if (ar_open(arcname) >= 0) | |
1242 | return(0); | |
1243 | tty_prnt("Cannot re-open %s, try again\n", | |
1244 | arcname); | |
1245 | continue; | |
1246 | case 's': | |
1247 | case 'S': | |
1248 | /* | |
1249 | * user wants to open a different device | |
1250 | */ | |
1251 | tty_prnt("Switching to a different archive\n"); | |
1252 | break; | |
1253 | default: | |
1254 | tty_prnt("%s unknown command, try again\n",buf); | |
1255 | continue; | |
1256 | } | |
1257 | break; | |
1258 | } | |
1259 | } else | |
1260 | tty_prnt("Ready for archive volume: %d\n", arvol); | |
1261 | ||
1262 | /* | |
1263 | * have to go to a different archive | |
1264 | */ | |
1265 | for (;;) { | |
1266 | tty_prnt("Input archive name or \".\" to quit %s.\n", argv0); | |
1267 | tty_prnt("Archive name > "); | |
1268 | ||
1269 | if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) { | |
1270 | done = 1; | |
1271 | lstrval = -1; | |
1272 | tty_prnt("Quitting %s!\n", argv0); | |
1273 | vfpart = 0; | |
1274 | return(-1); | |
1275 | } | |
1276 | if (buf[0] == '\0') { | |
1277 | tty_prnt("Empty file name, try again\n"); | |
1278 | continue; | |
1279 | } | |
1280 | if (!strcmp(buf, "..")) { | |
1281 | tty_prnt("Illegal file name: .. try again\n"); | |
1282 | continue; | |
1283 | } | |
1284 | if (strlen(buf) > PAXPATHLEN) { | |
1285 | tty_prnt("File name too long, try again\n"); | |
1286 | continue; | |
1287 | } | |
1288 | ||
1289 | /* | |
1290 | * try to open new archive | |
1291 | */ | |
1292 | if (ar_open(buf) >= 0) { | |
1293 | if (freeit) { | |
1294 | (void)free(arcname); | |
1295 | freeit = 0; | |
1296 | } | |
1297 | if ((arcname = strdup(buf)) == NULL) { | |
1298 | done = 1; | |
1299 | lstrval = -1; | |
1300 | paxwarn(0, "Cannot save archive name."); | |
1301 | return(-1); | |
1302 | } | |
1303 | freeit = 1; | |
1304 | break; | |
1305 | } | |
1306 | tty_prnt("Cannot open %s, try again\n", buf); | |
1307 | continue; | |
1308 | } | |
1309 | return(0); | |
1310 | } | |
1311 | ||
1312 | /* | |
1313 | * ar_start_gzip() | |
1314 | * starts the gzip compression/decompression process as a child, using magic | |
1315 | * to keep the fd the same in the calling function (parent). | |
1316 | */ | |
1317 | void | |
1318 | #ifdef __STDC__ | |
1319 | ar_start_gzip(int fd) | |
1320 | #else | |
1321 | ar_start_gzip(fd) | |
1322 | int fd; | |
1323 | #endif | |
1324 | { | |
1325 | pid_t pid; | |
1326 | int fds[2]; | |
1327 | char *gzip_flags=NULL; | |
1328 | ||
1329 | if (pipe(fds) < 0) | |
1330 | err(1, "could not pipe"); | |
1331 | pid = fork(); | |
1332 | if (pid < 0) | |
1333 | err(1, "could not fork"); | |
1334 | ||
1335 | /* parent */ | |
1336 | if (pid) { | |
1337 | switch (act) { | |
1338 | case ARCHIVE: | |
1339 | dup2(fds[1], fd); | |
1340 | break; | |
1341 | case LIST: | |
1342 | case EXTRACT: | |
1343 | dup2(fds[0], fd); | |
1344 | break; | |
1345 | default: | |
1346 | errx(1, "ar_start_gzip: impossible"); | |
1347 | } | |
1348 | close(fds[0]); | |
1349 | close(fds[1]); | |
1350 | } else { | |
1351 | switch (act) { | |
1352 | case ARCHIVE: | |
1353 | dup2(fds[0], STDIN_FILENO); | |
1354 | dup2(fd, STDOUT_FILENO); | |
1355 | gzip_flags = "-c"; | |
1356 | break; | |
1357 | case LIST: | |
1358 | case EXTRACT: | |
1359 | dup2(fds[1], STDOUT_FILENO); | |
1360 | dup2(fd, STDIN_FILENO); | |
1361 | gzip_flags = "-dc"; | |
1362 | break; | |
1363 | default: | |
1364 | errx(1, "ar_start_gzip: impossible"); | |
1365 | } | |
1366 | close(fds[0]); | |
1367 | close(fds[1]); | |
1368 | if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0) | |
1369 | err(1, "could not exec"); | |
1370 | /* NOTREACHED */ | |
1371 | } | |
1372 | } |