157193Smuller /*-
257193Smuller * Copyright (c) 1992 Keith Muller.
360675Sbostic * Copyright (c) 1992, 1993
460675Sbostic * The Regents of the University of California. All rights reserved.
557193Smuller *
657193Smuller * This code is derived from software contributed to Berkeley by
757193Smuller * Keith Muller of the University of California, San Diego.
857193Smuller *
957193Smuller * %sccs.include.redist.c%
1057193Smuller */
1157193Smuller
1257193Smuller #ifndef lint
13*66890Sbostic static char sccsid[] = "@(#)ar_io.c 8.2 (Berkeley) 04/18/94";
1457193Smuller #endif /* not lint */
1557193Smuller
1657193Smuller #include <sys/types.h>
1757193Smuller #include <sys/time.h>
1857193Smuller #include <sys/stat.h>
1957193Smuller #include <sys/ioctl.h>
2057193Smuller #include <sys/mtio.h>
2157193Smuller #include <sys/param.h>
2257193Smuller #include <signal.h>
2357193Smuller #include <string.h>
2457193Smuller #include <fcntl.h>
2557193Smuller #include <unistd.h>
2657193Smuller #include <stdio.h>
2757193Smuller #include <ctype.h>
2857193Smuller #include <errno.h>
2957193Smuller #include <stdlib.h>
3057193Smuller #include "pax.h"
3157193Smuller #include "extern.h"
3257193Smuller
3357193Smuller /*
3457535Smuller * Routines which deal directly with the archive I/O device/file.
3557193Smuller */
3657193Smuller
3757193Smuller #define DMOD 0666 /* default mode of created archives */
3857193Smuller #define EXT_MODE O_RDONLY /* open mode for list/extract */
3957193Smuller #define AR_MODE (O_WRONLY | O_CREAT | O_TRUNC) /* mode for archive */
4057193Smuller #define APP_MODE O_RDWR /* mode for append */
4157193Smuller #define STDO "<STDOUT>" /* psuedo name for stdout */
4257193Smuller #define STDN "<STDIN>" /* psuedo name for stdin */
4357193Smuller static int arfd = -1; /* archive file descriptor */
4457584Smuller static int artyp = ISREG; /* archive type: file/FIFO/tape */
4557193Smuller static int arvol = 1; /* archive volume number */
4657193Smuller static int lstrval = -1; /* return value from last i/o */
4757193Smuller static int io_ok; /* i/o worked on volume after resync */
4857535Smuller static int did_io; /* did i/o ever occur on volume? */
4957193Smuller static int done; /* set via tty termination */
5057193Smuller static struct stat arsb; /* stat of archive device at open */
5157193Smuller static int invld_rec; /* tape has out of spec record size */
5257578Smuller static int wr_trail = 1; /* trailer was rewritten in append */
5357584Smuller static int can_unlnk = 0; /* do we unlink null archives? */
5457193Smuller char *arcname; /* printable name of archive */
5557193Smuller
5657193Smuller static int get_phys __P((void));
5757193Smuller extern sigset_t s_mask;
5857193Smuller
5957193Smuller /*
6057193Smuller * ar_open()
6157193Smuller * Opens the next archive volume. Determines the type of the device and
6257193Smuller * sets up block sizes as required by the archive device and the format.
6357193Smuller * Note: we may be called with name == NULL on the first open only.
6457193Smuller * Return:
6557193Smuller * -1 on failure, 0 otherwise
6657193Smuller */
6757193Smuller
6857193Smuller #if __STDC__
6957193Smuller int
ar_open(char * name)7057193Smuller ar_open(char *name)
7157193Smuller #else
7257193Smuller int
7357193Smuller ar_open(name)
7457193Smuller char *name;
7557193Smuller #endif
7657193Smuller {
7757193Smuller struct mtget mb;
7857193Smuller
7957193Smuller if (arfd != -1)
8057193Smuller (void)close(arfd);
8157193Smuller arfd = -1;
8257794Smuller can_unlnk = did_io = io_ok = invld_rec = 0;
8357584Smuller artyp = ISREG;
8457193Smuller flcnt = 0;
8557193Smuller
8657193Smuller /*
8757193Smuller * open based on overall operation mode
8857193Smuller */
8957193Smuller switch (act) {
9057193Smuller case LIST:
9157193Smuller case EXTRACT:
9257193Smuller if (name == NULL) {
9357193Smuller arfd = STDIN_FILENO;
9457193Smuller arcname = STDN;
9557193Smuller } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
9657535Smuller syswarn(0, errno, "Failed open to read on %s", name);
9757193Smuller break;
9857193Smuller case ARCHIVE:
9957193Smuller if (name == NULL) {
10057193Smuller arfd = STDOUT_FILENO;
10157193Smuller arcname = STDO;
10257193Smuller } else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
10357535Smuller syswarn(0, errno, "Failed open to write on %s", name);
10457584Smuller else
10557584Smuller can_unlnk = 1;
10657193Smuller break;
10757193Smuller case APPND:
10857193Smuller if (name == NULL) {
10957193Smuller arfd = STDOUT_FILENO;
11057193Smuller arcname = STDO;
11157193Smuller } else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
11257535Smuller syswarn(0, errno, "Failed open to read/write on %s",
11357193Smuller name);
11457193Smuller break;
11557193Smuller case COPY:
11657193Smuller /*
11757193Smuller * arfd not used in COPY mode
11857193Smuller */
11957193Smuller arcname = "<NONE>";
12057193Smuller lstrval = 1;
12157193Smuller return(0);
12257193Smuller }
12357193Smuller if (arfd < 0)
12457193Smuller return(-1);
12557193Smuller
12657193Smuller /*
12757193Smuller * set up is based on device type
12857193Smuller */
12957193Smuller if (fstat(arfd, &arsb) < 0) {
13057535Smuller syswarn(0, errno, "Failed stat on %s", arcname);
13157584Smuller (void)close(arfd);
13257584Smuller arfd = -1;
13357584Smuller can_unlnk = 0;
13457193Smuller return(-1);
13557193Smuller }
13657193Smuller if (S_ISDIR(arsb.st_mode)) {
13757535Smuller warn(0, "Cannot write an archive on top of a directory %s",
13857193Smuller arcname);
13957584Smuller (void)close(arfd);
14057584Smuller arfd = -1;
14157584Smuller can_unlnk = 0;
14257193Smuller return(-1);
14357193Smuller }
14457584Smuller
14557193Smuller if (S_ISCHR(arsb.st_mode))
14657193Smuller artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
14757193Smuller else if (S_ISBLK(arsb.st_mode))
14857193Smuller artyp = ISBLK;
14957193Smuller else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
15057193Smuller artyp = ISPIPE;
15157193Smuller else
15257193Smuller artyp = ISREG;
15357193Smuller
15457193Smuller /*
15557584Smuller * make sure we beyond any doubt that we only can unlink regular files
15657584Smuller * we created
15757584Smuller */
15857584Smuller if (artyp != ISREG)
15957584Smuller can_unlnk = 0;
16057584Smuller /*
16157535Smuller * if we are writing, we are done
16257193Smuller */
16357193Smuller if (act == ARCHIVE) {
16457193Smuller blksz = rdblksz = wrblksz;
16557193Smuller lstrval = 1;
16657193Smuller return(0);
16757193Smuller }
16857193Smuller
16957193Smuller /*
17057193Smuller * set default blksz on read. APPNDs writes rdblksz on the last volume
17157193Smuller * On all new archive volumes, we shift to wrblksz (if the user
17257193Smuller * specified one, otherwize we will continue to use rdblksz). We
17357193Smuller * must to set blocksize based on what kind of device the archive is
17457193Smuller * stored.
17557193Smuller */
17657193Smuller switch(artyp) {
17757193Smuller case ISTAPE:
17857193Smuller /*
17957193Smuller * Tape drives come in at least two flavors. Those that support
18057193Smuller * variable sized records and those that have fixed sized
18157193Smuller * records. They must be treated differently. For tape drives
18257193Smuller * that support variable sized records, we must make large
18357193Smuller * reads to make sure we get the entire record, otherwise we
18457193Smuller * will just get the first part of the record (up to size we
18557193Smuller * asked). Tapes with fixed sized records may or may not return
18657193Smuller * multiple records in a single read. We really do not care
18757193Smuller * what the physical record size is UNLESS we are going to
18857193Smuller * append. (We will need the physical block size to rewrite
18957193Smuller * the trailer). Only when we are appending do we go to the
19057535Smuller * effort to figure out the true PHYSICAL record size.
19157193Smuller */
19257193Smuller blksz = rdblksz = MAXBLK;
19357193Smuller break;
19457193Smuller case ISPIPE:
19557193Smuller case ISBLK:
19657193Smuller case ISCHR:
19757193Smuller /*
19857193Smuller * Blocksize is not a major issue with these devices (but must
19957193Smuller * be kept a multiple of 512). If the user specified a write
20057193Smuller * block size, we use that to read. Under append, we must
20157193Smuller * always keep blksz == rdblksz. Otherwise we go ahead and use
20257193Smuller * the device optimal blocksize as (and if) returned by stat
20357193Smuller * and if it is within pax specs.
20457193Smuller */
20557193Smuller if ((act == APPND) && wrblksz) {
20657193Smuller blksz = rdblksz = wrblksz;
20757193Smuller break;
20857193Smuller }
20957193Smuller
21057193Smuller if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) &&
21157193Smuller ((arsb.st_blksize % BLKMULT) == 0))
21257193Smuller rdblksz = arsb.st_blksize;
21357193Smuller else
21457193Smuller rdblksz = DEVBLK;
21557193Smuller /*
21657193Smuller * For performance go for large reads when we can without harm
21757193Smuller */
21857193Smuller if ((act == APPND) || (artyp == ISCHR))
21957193Smuller blksz = rdblksz;
22057193Smuller else
22157193Smuller blksz = MAXBLK;
22257193Smuller break;
22357193Smuller case ISREG:
22457193Smuller /*
22557193Smuller * if the user specified wrblksz works, use it. Under appends
22657193Smuller * we must always keep blksz == rdblksz
22757193Smuller */
22857193Smuller if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){
22957193Smuller blksz = rdblksz = wrblksz;
23057193Smuller break;
23157193Smuller }
23257193Smuller /*
23357193Smuller * See if we can find the blocking factor from the file size
23457193Smuller */
23557193Smuller for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT)
23657193Smuller if ((arsb.st_size % rdblksz) == 0)
23757193Smuller break;
23857193Smuller /*
23957193Smuller * When we cannont find a match, we may have a flawed archive.
24057193Smuller */
24157193Smuller if (rdblksz <= 0)
24257193Smuller rdblksz = FILEBLK;
24357193Smuller /*
24457193Smuller * for performance go for large reads when we can
24557193Smuller */
24657193Smuller if (act == APPND)
24757193Smuller blksz = rdblksz;
24857193Smuller else
24957193Smuller blksz = MAXBLK;
25057193Smuller break;
25157193Smuller default:
25257193Smuller /*
25357193Smuller * should never happen, worse case, slow...
25457193Smuller */
25557193Smuller blksz = rdblksz = BLKMULT;
25657193Smuller break;
25757193Smuller }
25857193Smuller lstrval = 1;
25957193Smuller return(0);
26057193Smuller }
26157193Smuller
26257193Smuller /*
26357193Smuller * ar_close()
26457193Smuller * closes archive device, increments volume number, and prints i/o summary
26557193Smuller */
26657193Smuller #if __STDC__
26757193Smuller void
ar_close(void)26857193Smuller ar_close(void)
26957193Smuller #else
27057193Smuller void
27157193Smuller ar_close()
27257193Smuller #endif
27357193Smuller {
27457193Smuller FILE *outf;
27557193Smuller
27657578Smuller if (arfd < 0) {
27757578Smuller did_io = io_ok = flcnt = 0;
27857578Smuller return;
27957578Smuller }
28057578Smuller
28157535Smuller if (act == LIST)
28257535Smuller outf = stdout;
28357535Smuller else
28457535Smuller outf = stderr;
28557535Smuller
28657535Smuller /*
28757535Smuller * Close archive file. This may take a LONG while on tapes (we may be
28857535Smuller * forced to wait for the rewind to complete) so tell the user what is
28957535Smuller * going on (this avoids the user hitting control-c thinking pax is
29057535Smuller * broken).
29157535Smuller */
29257578Smuller if (vflag && (artyp == ISTAPE)) {
29357578Smuller if (vfpart)
29457535Smuller (void)putc('\n', outf);
295*66890Sbostic (void)fprintf(outf,
296*66890Sbostic "%s: Waiting for tape drive close to complete...",
297*66890Sbostic argv0);
29857535Smuller (void)fflush(outf);
29957535Smuller }
30057535Smuller
30157584Smuller /*
30257584Smuller * if nothing was written to the archive (and we created it), we remove
30357584Smuller * it
30457584Smuller */
30557584Smuller if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) &&
30657584Smuller (arsb.st_size == 0)) {
30757584Smuller (void)unlink(arcname);
30857584Smuller can_unlnk = 0;
30957584Smuller }
31057584Smuller
31157193Smuller (void)close(arfd);
31257535Smuller
31357578Smuller if (vflag && (artyp == ISTAPE)) {
31457535Smuller (void)fputs("done.\n", outf);
31557578Smuller vfpart = 0;
31657535Smuller (void)fflush(outf);
31757535Smuller }
31857193Smuller arfd = -1;
31957535Smuller
32057193Smuller if (!io_ok && !did_io) {
32157193Smuller flcnt = 0;
32257193Smuller return;
32357193Smuller }
32457193Smuller did_io = io_ok = 0;
32557193Smuller
32657193Smuller /*
32757193Smuller * The volume number is only increased when the last device has data
32857535Smuller * and we have already determined the archive format.
32957193Smuller */
33057535Smuller if (frmt != NULL)
33157535Smuller ++arvol;
33257535Smuller
33357193Smuller if (!vflag) {
33457193Smuller flcnt = 0;
33557193Smuller return;
33657193Smuller }
33757193Smuller
33857193Smuller /*
33957193Smuller * Print out a summary of I/O for this archive volume.
34057193Smuller */
34157193Smuller if (vfpart) {
34257193Smuller (void)putc('\n', outf);
34357193Smuller vfpart = 0;
34457193Smuller }
34557193Smuller
34657535Smuller /*
34757535Smuller * If we have not determined the format yet, we just say how many bytes
34857535Smuller * we have skipped over looking for a header to id. there is no way we
34957535Smuller * could have written anything yet.
35057535Smuller */
35157535Smuller if (frmt == NULL) {
35257535Smuller # ifdef NET2_STAT
353*66890Sbostic (void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n",
35457535Smuller # else
355*66890Sbostic (void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n",
35657535Smuller # endif
357*66890Sbostic argv0, rdcnt);
35857535Smuller (void)fflush(outf);
35957535Smuller flcnt = 0;
36057535Smuller return;
36157535Smuller }
36257535Smuller
36357193Smuller (void)fprintf(outf,
36457193Smuller # ifdef NET2_STAT
365*66890Sbostic "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
36657193Smuller # else
367*66890Sbostic "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
36857193Smuller # endif
369*66890Sbostic argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
37057193Smuller (void)fflush(outf);
37157193Smuller flcnt = 0;
37257193Smuller }
37357193Smuller
37457193Smuller /*
37558651Smuller * ar_drain()
37658651Smuller * drain any archive format independent padding from an archive read
37758651Smuller * from a socket or a pipe. This is to prevent the process on the
37858651Smuller * other side of the pipe from getting a SIGPIPE (pax will stop
37958651Smuller * reading an archive once a format dependent trailer is detected).
38058651Smuller */
38158651Smuller #if __STDC__
38258651Smuller void
ar_drain(void)38358651Smuller ar_drain(void)
38458651Smuller #else
38558651Smuller void
38658651Smuller ar_drain()
38758651Smuller #endif
38858651Smuller {
38958651Smuller register int res;
39058651Smuller char drbuf[MAXBLK];
39158651Smuller
39258651Smuller /*
39358651Smuller * we only drain from a pipe/socket. Other devices can be closed
39458651Smuller * without reading up to end of file. We sure hope that pipe is closed
39558651Smuller * on the other side so we will get an EOF.
39658651Smuller */
39758651Smuller if ((artyp != ISPIPE) || (lstrval <= 0))
39858651Smuller return;
39958651Smuller
40058651Smuller /*
40158651Smuller * keep reading until pipe is drained
40258651Smuller */
40358651Smuller while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0)
40458651Smuller ;
40558651Smuller lstrval = res;
40658651Smuller }
40758651Smuller
40858651Smuller /*
40957193Smuller * ar_set_wr()
41057578Smuller * Set up device right before switching from read to write in an append.
41157578Smuller * device dependent code (if required) to do this should be added here.
41257578Smuller * For all archive devices we are already positioned at the place we want
41357578Smuller * to start writing when this routine is called.
41457193Smuller * Return:
41557193Smuller * 0 if all ready to write, -1 otherwise
41657193Smuller */
41757193Smuller
41857193Smuller #if __STDC__
41957193Smuller int
ar_set_wr(void)42057193Smuller ar_set_wr(void)
42157193Smuller #else
42257193Smuller int
42357193Smuller ar_set_wr()
42457193Smuller #endif
42557193Smuller {
42657193Smuller off_t cpos;
42757193Smuller
42857578Smuller /*
42957578Smuller * we must make sure the trailer is rewritten on append, ar_next()
43057578Smuller * will stop us if the archive containing the trailer was not written
43157578Smuller */
43257578Smuller wr_trail = 0;
43357578Smuller
43457193Smuller /*
43557193Smuller * Add any device dependent code as required here
43657193Smuller */
43757193Smuller if (artyp != ISREG)
43857193Smuller return(0);
43957193Smuller /*
44057535Smuller * Ok we have an archive in a regular file. If we were rewriting a
44157535Smuller * file, we must get rid of all the stuff after the current offset
44257535Smuller * (it was not written by pax).
44357193Smuller */
44457193Smuller if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) ||
44557578Smuller (ftruncate(arfd, cpos) < 0)) {
44657578Smuller syswarn(1, errno, "Unable to truncate archive file");
44757193Smuller return(-1);
44857578Smuller }
44957193Smuller return(0);
45057193Smuller }
45157193Smuller
45257193Smuller /*
45357193Smuller * ar_app_ok()
45457193Smuller * check if the last volume in the archive allows appends. We cannot check
45557193Smuller * this until we are ready to write since there is no spec that says all
45657193Smuller * volumes in a single archive have to be of the same type...
45757193Smuller * Return:
45857193Smuller * 0 if we can append, -1 otherwise.
45957193Smuller */
46057193Smuller
46157193Smuller #if __STDC__
46257193Smuller int
ar_app_ok(void)46357193Smuller ar_app_ok(void)
46457193Smuller #else
46557193Smuller int
46657193Smuller ar_app_ok()
46757193Smuller #endif
46857193Smuller {
46957193Smuller if (artyp == ISPIPE) {
47057193Smuller warn(1, "Cannot append to an archive obtained from a pipe.");
47157193Smuller return(-1);
47257193Smuller }
47357193Smuller
47457193Smuller if (!invld_rec)
47557193Smuller return(0);
476*66890Sbostic warn(1,"Cannot append, device record size %d does not support %s spec",
477*66890Sbostic rdblksz, argv0);
47857193Smuller return(-1);
47957193Smuller }
48057193Smuller
48157193Smuller /*
48257193Smuller * ar_read()
48357193Smuller * read up to a specified number of bytes from the archive into the
48457193Smuller * supplied buffer. When dealing with tapes we may not always be able to
48557193Smuller * read what we want.
48657193Smuller * Return:
48757193Smuller * Number of bytes in buffer. 0 for end of file, -1 for a read error.
48857193Smuller */
48957193Smuller
49057193Smuller #if __STDC__
49157193Smuller int
ar_read(register char * buf,register int cnt)49257193Smuller ar_read(register char *buf, register int cnt)
49357193Smuller #else
49457193Smuller int
49557193Smuller ar_read(buf, cnt)
49657193Smuller register char *buf;
49757193Smuller register int cnt;
49857193Smuller #endif
49957193Smuller {
50057193Smuller register int res = 0;
50157193Smuller
50257193Smuller /*
50357193Smuller * if last i/o was in error, no more reads until reset or new volume
50457193Smuller */
50557193Smuller if (lstrval <= 0)
50657193Smuller return(lstrval);
50757193Smuller
50857193Smuller /*
50957193Smuller * how we read must be based on device type
51057193Smuller */
51157193Smuller switch (artyp) {
51257193Smuller case ISTAPE:
51357193Smuller if ((res = read(arfd, buf, cnt)) > 0) {
51457193Smuller /*
51557193Smuller * CAUTION: tape systems may not always return the same
51657193Smuller * sized records so we leave blksz == MAXBLK. The
51757193Smuller * physical record size that a tape drive supports is
51857193Smuller * very hard to determine in a uniform and portable
51957193Smuller * manner.
52057193Smuller */
52157193Smuller io_ok = 1;
52257193Smuller if (res != rdblksz) {
52357193Smuller /*
52457193Smuller * Record size changed. If this is happens on
52557535Smuller * any record after the first, we probably have
52657535Smuller * a tape drive which has a fixed record size
52757535Smuller * we are getting multiple records in a single
52857535Smuller * read). Watch out for record blocking that
52957535Smuller * violates pax spec (must be a multiple of
53057535Smuller * BLKMULT).
53157193Smuller */
53257193Smuller rdblksz = res;
53357193Smuller if (rdblksz % BLKMULT)
53457193Smuller invld_rec = 1;
53557193Smuller }
53657193Smuller return(res);
53757193Smuller }
53857193Smuller break;
53957193Smuller case ISREG:
54057193Smuller case ISBLK:
54157193Smuller case ISCHR:
54257193Smuller case ISPIPE:
54357193Smuller default:
54457193Smuller /*
54557193Smuller * Files are so easy to deal with. These other things cannot
54657193Smuller * be trusted at all. So when we are dealing with character
54757193Smuller * devices and pipes we just take what they have ready for us
54857193Smuller * and return. Trying to do anything else with them runs the
54957193Smuller * risk of failure.
55057193Smuller */
55157193Smuller if ((res = read(arfd, buf, cnt)) > 0) {
55257193Smuller io_ok = 1;
55357193Smuller return(res);
55457193Smuller }
55557193Smuller break;
55657193Smuller }
55757193Smuller
55857193Smuller /*
55957193Smuller * We are in trouble at this point, something is broken...
56057193Smuller */
56157193Smuller lstrval = res;
56257193Smuller if (res < 0)
56357193Smuller syswarn(1, errno, "Failed read on archive volume %d", arvol);
56457193Smuller else
56557193Smuller warn(0, "End of archive volume %d reached", arvol);
56657193Smuller return(res);
56757193Smuller }
56857193Smuller
56957193Smuller /*
57057193Smuller * ar_write()
57157193Smuller * Write a specified number of bytes in supplied buffer to the archive
57257193Smuller * device so it appears as a single "block". Deals with errors and tries
57357193Smuller * to recover when faced with short writes.
57457193Smuller * Return:
57557193Smuller * Number of bytes written. 0 indicates end of volume reached and with no
57657193Smuller * flaws (as best that can be detected). A -1 indicates an unrecoverable
57757193Smuller * error in the archive occured.
57857193Smuller */
57957193Smuller
58057193Smuller #if __STDC__
58157193Smuller int
ar_write(register char * buf,register int bsz)58257193Smuller ar_write(register char *buf, register int bsz)
58357193Smuller #else
58457193Smuller int
58557193Smuller ar_write(buf, bsz)
58657193Smuller register char *buf;
58757193Smuller register int bsz;
58857193Smuller #endif
58957193Smuller {
59057193Smuller register int res;
59157193Smuller off_t cpos;
59257193Smuller
59357193Smuller /*
59457193Smuller * do not allow pax to create a "bad" archive. Once a write fails on
59557193Smuller * an archive volume prevent further writes to it.
59657193Smuller */
59757193Smuller if (lstrval <= 0)
59857193Smuller return(lstrval);
59957193Smuller
60057193Smuller if ((res = write(arfd, buf, bsz)) == bsz) {
60157578Smuller wr_trail = 1;
60257193Smuller io_ok = 1;
60357193Smuller return(bsz);
60457193Smuller }
60557193Smuller /*
60657193Smuller * write broke, see what we can do with it. We try to send any partial
60757535Smuller * writes that may violate pax spec to the next archive volume.
60857193Smuller */
60957193Smuller if (res < 0)
61057193Smuller lstrval = res;
61157193Smuller else
61257193Smuller lstrval = 0;
61357193Smuller
61457193Smuller switch (artyp) {
61557193Smuller case ISREG:
61657193Smuller if ((res > 0) && (res % BLKMULT)) {
61757193Smuller /*
61857193Smuller * try to fix up partial writes which are not BLKMULT
61957193Smuller * in size by forcing the runt record to next archive
62057193Smuller * volume
62157193Smuller */
62257193Smuller if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
62357193Smuller break;
62457193Smuller cpos -= (off_t)res;
62557193Smuller if (ftruncate(arfd, cpos) < 0)
62657193Smuller break;
62757193Smuller res = lstrval = 0;
62857193Smuller break;
62957193Smuller }
63057193Smuller if (res >= 0)
63157193Smuller break;
63257193Smuller /*
63357193Smuller * if file is out of space, handle it like a return of 0
63457193Smuller */
63557193Smuller if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT))
63657193Smuller res = lstrval = 0;
63757193Smuller break;
63857193Smuller case ISTAPE:
63957193Smuller case ISCHR:
64057193Smuller case ISBLK:
64157193Smuller if (res >= 0)
64257193Smuller break;
64357193Smuller if (errno == EACCES) {
64457193Smuller warn(0, "Write failed, archive is write protected.");
64557193Smuller res = lstrval = 0;
64657193Smuller return(0);
64757193Smuller }
64857193Smuller /*
64957193Smuller * see if we reached the end of media, if so force a change to
65057193Smuller * the next volume
65157193Smuller */
65257193Smuller if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO))
65357193Smuller res = lstrval = 0;
65457193Smuller break;
65557193Smuller case ISPIPE:
65657193Smuller default:
65757193Smuller /*
65857193Smuller * we cannot fix errors to these devices
65957193Smuller */
66057193Smuller break;
66157193Smuller }
66257193Smuller
66357193Smuller /*
66457193Smuller * Better tell the user the bad news...
66557535Smuller * if this is a block aligned archive format, we may have a bad archive
66657535Smuller * if the format wants the header to start at a BLKMULT boundry. While
66757193Smuller * we can deal with the mis-aligned data, it violates spec and other
66857193Smuller * archive readers will likely fail. if the format is not block
66957535Smuller * aligned, the user may be lucky (and the archive is ok).
67057193Smuller */
67157578Smuller if (res >= 0) {
67257578Smuller if (res > 0)
67357578Smuller wr_trail = 1;
67457193Smuller io_ok = 1;
67557578Smuller }
67657578Smuller
67757578Smuller /*
67857578Smuller * If we were trying to rewrite the trailer and it didn't work, we
67957578Smuller * must quit right away.
68057578Smuller */
68157578Smuller if (!wr_trail && (res <= 0)) {
68257578Smuller warn(1,"Unable to append, trailer re-write failed. Quitting.");
68357578Smuller return(res);
68457578Smuller }
68557578Smuller
68657578Smuller if (res == 0)
68757193Smuller warn(0, "End of archive volume %d reached", arvol);
68857193Smuller else if (res < 0)
68957193Smuller syswarn(1, errno, "Failed write to archive volume: %d", arvol);
69057193Smuller else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0))
69157193Smuller warn(0,"WARNING: partial archive write. Archive MAY BE FLAWED");
69257193Smuller else
69357193Smuller warn(1,"WARNING: partial archive write. Archive IS FLAWED");
69457193Smuller return(res);
69557193Smuller }
69657193Smuller
69757193Smuller /*
69857193Smuller * ar_rdsync()
69957193Smuller * Try to move past a bad spot on a flawed archive as needed to continue
70057193Smuller * I/O. Clears error flags to allow I/O to continue.
70157193Smuller * Return:
70257193Smuller * 0 when ok to try i/o again, -1 otherwise.
70357193Smuller */
70457193Smuller
70557193Smuller #if __STDC__
70657193Smuller int
ar_rdsync(void)70757193Smuller ar_rdsync(void)
70857193Smuller #else
70957193Smuller int
71057193Smuller ar_rdsync()
71157193Smuller #endif
71257193Smuller {
71357193Smuller long fsbz;
71457193Smuller off_t cpos;
71557193Smuller off_t mpos;
71657193Smuller struct mtop mb;
71757193Smuller
71857193Smuller /*
71957193Smuller * Fail resync attempts at user request (done) or this is going to be
72057193Smuller * an update/append to a existing archive. if last i/o hit media end,
72157193Smuller * we need to go to the next volume not try a resync
72257193Smuller */
72357193Smuller if ((done > 0) || (lstrval == 0))
72457193Smuller return(-1);
72557193Smuller
72657193Smuller if ((act == APPND) || (act == ARCHIVE)) {
72757193Smuller warn(1, "Cannot allow updates to an archive with flaws.");
72857193Smuller return(-1);
72957193Smuller }
73057193Smuller if (io_ok)
73157193Smuller did_io = 1;
73257193Smuller
73357193Smuller switch(artyp) {
73457193Smuller case ISTAPE:
73557193Smuller /*
73657193Smuller * if the last i/o was a successful data transfer, we assume
73757193Smuller * the fault is just a bad record on the tape that we are now
73857193Smuller * past. If we did not get any data since the last resync try
73957193Smuller * to move the tape foward one PHYSICAL record past any
74057193Smuller * damaged tape section. Some tape drives are stubborn and need
74157193Smuller * to be pushed.
74257193Smuller */
74357193Smuller if (io_ok) {
74457193Smuller io_ok = 0;
74557193Smuller lstrval = 1;
74657193Smuller break;
74757193Smuller }
74857193Smuller mb.mt_op = MTFSR;
74957193Smuller mb.mt_count = 1;
75057193Smuller if (ioctl(arfd, MTIOCTOP, &mb) < 0)
75157193Smuller break;
75257193Smuller lstrval = 1;
75357193Smuller break;
75457193Smuller case ISREG:
75557193Smuller case ISCHR:
75657193Smuller case ISBLK:
75757193Smuller /*
75857193Smuller * try to step over the bad part of the device.
75957193Smuller */
76057193Smuller io_ok = 0;
76157193Smuller if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
76257193Smuller fsbz = BLKMULT;
76357193Smuller if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
76457193Smuller break;
76557193Smuller mpos = fsbz - (cpos % (off_t)fsbz);
76657193Smuller if (lseek(arfd, mpos, SEEK_CUR) < 0)
76757193Smuller break;
76857193Smuller lstrval = 1;
76957193Smuller break;
77057193Smuller case ISPIPE:
77157193Smuller default:
77257193Smuller /*
77357193Smuller * cannot recover on these archive device types
77457193Smuller */
77557193Smuller io_ok = 0;
77657193Smuller break;
77757193Smuller }
77857193Smuller if (lstrval <= 0) {
77957535Smuller warn(1, "Unable to recover from an archive read failure.");
78057193Smuller return(-1);
78157193Smuller }
78257193Smuller warn(0, "Attempting to recover from an archive read failure.");
78357193Smuller return(0);
78457193Smuller }
78557193Smuller
78657193Smuller /*
78757193Smuller * ar_fow()
78857193Smuller * Move the I/O position within the archive foward the specified number of
78957193Smuller * bytes as supported by the device. If we cannot move the requested
79057193Smuller * number of bytes, return the actual number of bytes moved in skipped.
79157193Smuller * Return:
79257193Smuller * 0 if moved the requested distance, -1 on complete failure, 1 on
79357193Smuller * partial move (the amount moved is in skipped)
79457193Smuller */
79557193Smuller
79657193Smuller #if __STDC__
79757193Smuller int
ar_fow(off_t sksz,off_t * skipped)79857193Smuller ar_fow(off_t sksz, off_t *skipped)
79957193Smuller #else
80057193Smuller int
80157193Smuller ar_fow(sksz, skipped)
80257193Smuller off_t sksz;
80357193Smuller off_t *skipped;
80457193Smuller #endif
80557193Smuller {
80657193Smuller off_t cpos;
80757193Smuller off_t mpos;
80857193Smuller
80957193Smuller *skipped = 0;
81057193Smuller if (sksz <= 0)
81157193Smuller return(0);
81257193Smuller
81357193Smuller /*
81457193Smuller * we cannot move foward at EOF or error
81557193Smuller */
81657193Smuller if (lstrval <= 0)
81757193Smuller return(lstrval);
81857193Smuller
81957193Smuller /*
82057193Smuller * Safer to read forward on devices where it is hard to find the end of
82157193Smuller * the media without reading to it. With tapes we cannot be sure of the
82257193Smuller * number of physical blocks to skip (we do not know physical block
82357193Smuller * size at this point), so we must only read foward on tapes!
82457193Smuller */
82557193Smuller if (artyp != ISREG)
82657193Smuller return(0);
82757193Smuller
82857193Smuller /*
82957193Smuller * figure out where we are in the archive
83057193Smuller */
83157193Smuller if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
83257193Smuller /*
83357193Smuller * we can be asked to move farther than there are bytes in this
83457193Smuller * volume, if so, just go to file end and let normal buf_fill()
83557193Smuller * deal with the end of file (it will go to next volume by
83657193Smuller * itself)
83757193Smuller */
83857193Smuller if ((mpos = cpos + sksz) > arsb.st_size) {
83957193Smuller *skipped = arsb.st_size - cpos;
84057193Smuller mpos = arsb.st_size;
84157193Smuller } else
84257193Smuller *skipped = sksz;
84357193Smuller if (lseek(arfd, mpos, SEEK_SET) >= 0)
84457193Smuller return(0);
84557193Smuller }
84657193Smuller syswarn(1, errno, "Foward positioning operation on archive failed");
84757193Smuller lstrval = -1;
84857193Smuller return(-1);
84957193Smuller }
85057193Smuller
85157193Smuller /*
85257193Smuller * ar_rev()
85357193Smuller * move the i/o position within the archive backwards the specified byte
85457193Smuller * count as supported by the device. With tapes drives we RESET rdblksz to
85557193Smuller * the PHYSICAL blocksize.
85657193Smuller * NOTE: We should only be called to move backwards so we can rewrite the
85757193Smuller * last records (the trailer) of an archive (APPEND).
85857193Smuller * Return:
85957193Smuller * 0 if moved the requested distance, -1 on complete failure
86057193Smuller */
86157193Smuller
86257193Smuller #if __STDC__
86357193Smuller int
ar_rev(off_t sksz)86457193Smuller ar_rev(off_t sksz)
86557193Smuller #else
86657193Smuller int
86757193Smuller ar_rev(sksz)
86857193Smuller off_t sksz;
86957193Smuller #endif
87057193Smuller {
87157193Smuller off_t cpos;
87257193Smuller struct mtop mb;
873*66890Sbostic register int phyblk;
87457193Smuller
87557193Smuller /*
87657578Smuller * make sure we do not have try to reverse on a flawed archive
87757193Smuller */
87857193Smuller if (lstrval < 0)
87957193Smuller return(lstrval);
88057193Smuller
88157193Smuller switch(artyp) {
88257193Smuller case ISPIPE:
88357578Smuller if (sksz <= 0)
88457578Smuller break;
88557193Smuller /*
88657193Smuller * cannot go backwards on these critters
88757193Smuller */
88857578Smuller warn(1, "Reverse positioning on pipes is not supported.");
88957578Smuller lstrval = -1;
89057578Smuller return(-1);
89157193Smuller case ISREG:
89257193Smuller case ISBLK:
89357193Smuller case ISCHR:
89457193Smuller default:
89557578Smuller if (sksz <= 0)
89657578Smuller break;
89757578Smuller
89857193Smuller /*
89957193Smuller * For things other than files, backwards movement has a very
90057193Smuller * high probability of failure as we really do not know the
90157193Smuller * true attributes of the device we are talking to (the device
90257193Smuller * may not even have the ability to lseek() in any direction).
90357578Smuller * First we figure out where we are in the archive.
90457193Smuller */
90557578Smuller if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) {
90657578Smuller syswarn(1, errno,
90757578Smuller "Unable to obtain current archive byte offset");
90857578Smuller lstrval = -1;
90957578Smuller return(-1);
91057578Smuller }
91157193Smuller
91257193Smuller /*
91357193Smuller * we may try to go backwards past the start when the archive
91457193Smuller * is only a single record. If this hapens and we are on a
91557193Smuller * multi volume archive, we need to go to the end of the
91657193Smuller * previous volume and continue our movement backwards from
91757578Smuller * there.
91857193Smuller */
91957193Smuller if ((cpos -= sksz) < (off_t)0L) {
92057193Smuller if (arvol > 1) {
92157578Smuller /*
92257578Smuller * this should never happen
92357578Smuller */
92457578Smuller warn(1,"Reverse position on previous volume.");
92557193Smuller lstrval = -1;
92657193Smuller return(-1);
92757193Smuller }
92857193Smuller cpos = (off_t)0L;
92957193Smuller }
93057578Smuller if (lseek(arfd, cpos, SEEK_SET) < 0) {
93157578Smuller syswarn(1, errno, "Unable to seek archive backwards");
93257578Smuller lstrval = -1;
93357578Smuller return(-1);
93457578Smuller }
93557578Smuller break;
93657193Smuller case ISTAPE:
93757193Smuller /*
93857193Smuller * Calculate and move the proper number of PHYSICAL tape
93957578Smuller * blocks. If the sksz is not an even multiple of the physical
94057193Smuller * tape size, we cannot do the move (this should never happen).
94157193Smuller * (We also cannot handler trailers spread over two vols).
94257578Smuller * get_phys() also makes sure we are in front of the filemark.
94357193Smuller */
94457794Smuller if ((phyblk = get_phys()) <= 0) {
94557578Smuller lstrval = -1;
94657578Smuller return(-1);
94757193Smuller }
94857193Smuller
94957578Smuller /*
95057578Smuller * make sure future tape reads only go by physical tape block
95157578Smuller * size (set rdblksz to the real size).
95257578Smuller */
95357578Smuller rdblksz = phyblk;
95457578Smuller
95557578Smuller /*
95657578Smuller * if no movement is required, just return (we must be after
95757578Smuller * get_phys() so the physical blocksize is properly set)
95857578Smuller */
95957578Smuller if (sksz <= 0)
96057578Smuller break;
96157578Smuller
96257578Smuller /*
96357578Smuller * ok we have to move. Make sure the tape drive can do it.
96457578Smuller */
96557193Smuller if (sksz % phyblk) {
96657578Smuller warn(1,
96757578Smuller "Tape drive unable to backspace requested amount");
96857193Smuller lstrval = -1;
96957193Smuller return(-1);
97057193Smuller }
97157193Smuller
97257578Smuller /*
97357578Smuller * move backwards the requested number of bytes
97457578Smuller */
97557193Smuller mb.mt_op = MTBSR;
97657193Smuller mb.mt_count = sksz/phyblk;
97757578Smuller if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
97857578Smuller syswarn(1,errno, "Unable to backspace tape %d blocks.",
97957578Smuller mb.mt_count);
98057578Smuller lstrval = -1;
98157578Smuller return(-1);
98257578Smuller }
98357578Smuller break;
98457193Smuller }
98557578Smuller lstrval = 1;
98657578Smuller return(0);
98757193Smuller }
98857193Smuller
98957193Smuller /*
99057193Smuller * get_phys()
99157578Smuller * Determine the physical block size on a tape drive. We need the physical
99257578Smuller * block size so we know how many bytes we skip over when we move with
99357578Smuller * mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
99457578Smuller * return.
99557578Smuller * This is one really SLOW routine...
99657193Smuller * Return:
99757794Smuller * physical block size if ok (ok > 0), -1 otherwise
99857193Smuller */
99957193Smuller
100057193Smuller #if __STDC__
100157193Smuller static int
get_phys(void)100257193Smuller get_phys(void)
100357193Smuller #else
100457193Smuller static int
100557193Smuller get_phys()
100657193Smuller #endif
100757193Smuller {
100857578Smuller register int padsz = 0;
100957535Smuller register int res;
101057794Smuller register int phyblk;
101157535Smuller struct mtop mb;
101257578Smuller char scbuf[MAXBLK];
101357193Smuller
101457193Smuller /*
101557578Smuller * move to the file mark, and then back up one record and read it.
101657578Smuller * this should tell us the physical record size the tape is using.
101757578Smuller */
101857578Smuller if (lstrval == 1) {
101957578Smuller /*
102057578Smuller * we know we are at file mark when we get back a 0 from
102157578Smuller * read()
102257578Smuller */
102357578Smuller while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
102457578Smuller padsz += res;
102557578Smuller if (res < 0) {
102657578Smuller syswarn(1, errno, "Unable to locate tape filemark.");
102757578Smuller return(-1);
102857578Smuller }
102957578Smuller }
103057193Smuller
103157578Smuller /*
103257578Smuller * move backwards over the file mark so we are at the end of the
103357578Smuller * last record.
103457578Smuller */
103557578Smuller mb.mt_op = MTBSF;
103657193Smuller mb.mt_count = 1;
103757578Smuller if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
103857578Smuller syswarn(1, errno, "Unable to backspace over tape filemark.");
103957193Smuller return(-1);
104057535Smuller }
104157193Smuller
104257193Smuller /*
104357578Smuller * move backwards so we are in front of the last record and read it to
104457578Smuller * get physical tape blocksize.
104557193Smuller */
104657578Smuller mb.mt_op = MTBSR;
104757578Smuller mb.mt_count = 1;
104857578Smuller if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
104957578Smuller syswarn(1, errno, "Unable to backspace over last tape block.");
105057193Smuller return(-1);
105157578Smuller }
105257578Smuller if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) {
105357578Smuller syswarn(1, errno, "Cannot determine archive tape blocksize.");
105457578Smuller return(-1);
105557578Smuller }
105657535Smuller
105757535Smuller /*
105857578Smuller * read foward to the file mark, then back up in front of the filemark
105957578Smuller * (this is a bit paranoid, but should be safe to do).
106057535Smuller */
106157578Smuller while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
106257578Smuller ;
106357578Smuller if (res < 0) {
106457578Smuller syswarn(1, errno, "Unable to locate tape filemark.");
106557535Smuller return(-1);
106657578Smuller }
106757578Smuller mb.mt_op = MTBSF;
106857578Smuller mb.mt_count = 1;
106957578Smuller if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
107057578Smuller syswarn(1, errno, "Unable to backspace over tape filemark.");
107157578Smuller return(-1);
107257578Smuller }
107357535Smuller
107457535Smuller /*
107557578Smuller * set lstrval so we know that the filemark has not been seen
107657535Smuller */
107757578Smuller lstrval = 1;
107857578Smuller
107957578Smuller /*
108057578Smuller * return if there was no padding
108157578Smuller */
108257578Smuller if (padsz == 0)
108357794Smuller return(phyblk);
108457535Smuller
108557535Smuller /*
108657578Smuller * make sure we can move backwards over the padding. (this should
108757578Smuller * never fail).
108857535Smuller */
108957578Smuller if (padsz % phyblk) {
109057578Smuller warn(1, "Tape drive unable to backspace requested amount");
109157535Smuller return(-1);
109257578Smuller }
109357535Smuller
109457535Smuller /*
109557578Smuller * move backwards over the padding so the head is where it was when
109657578Smuller * we were first called (if required).
109757535Smuller */
109857578Smuller mb.mt_op = MTBSR;
109957578Smuller mb.mt_count = padsz/phyblk;
110057578Smuller if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
110157578Smuller syswarn(1,errno,"Unable to backspace tape over %d pad blocks",
110257578Smuller mb.mt_count);
110357535Smuller return(-1);
110457578Smuller }
110557794Smuller return(phyblk);
110657193Smuller }
110757193Smuller
110857193Smuller /*
110957193Smuller * ar_next()
111057535Smuller * prompts the user for the next volume in this archive. For some devices
111157535Smuller * we may allow the media to be changed. Otherwise a new archive is
111257535Smuller * prompted for. By pax spec, if there is no controlling tty or an eof is
111357535Smuller * read on tty input, we must quit pax.
111457193Smuller * Return:
111557193Smuller * 0 when ready to continue, -1 when all done
111657193Smuller */
111757193Smuller
111857193Smuller #if __STDC__
111957193Smuller int
ar_next(void)112057193Smuller ar_next(void)
112157193Smuller #else
112257193Smuller int
112357193Smuller ar_next()
112457193Smuller #endif
112557193Smuller {
112657193Smuller char buf[PAXPATHLEN+2];
112757193Smuller static int freeit = 0;
112857193Smuller sigset_t o_mask;
112957193Smuller
113057193Smuller /*
113157535Smuller * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so
113257193Smuller * things like writing EOF etc will be done) (Watch out ar_close() can
113357535Smuller * also be called via a signal handler, so we must prevent a race.
113457193Smuller */
113557193Smuller if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0)
113657535Smuller syswarn(0, errno, "Unable to set signal mask");
113757193Smuller ar_close();
113857193Smuller if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0)
113957535Smuller syswarn(0, errno, "Unable to restore signal mask");
114057193Smuller
114157578Smuller if (done || !wr_trail)
114257193Smuller return(-1);
114357193Smuller
1144*66890Sbostic tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
114557193Smuller
114657193Smuller /*
114757193Smuller * if i/o is on stdin or stdout, we cannot reopen it (we do not know
114857535Smuller * the name), the user will be forced to type it in.
114957193Smuller */
115057193Smuller if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG)
115157193Smuller && (artyp != ISPIPE)) {
115257193Smuller if (artyp == ISTAPE) {
115357193Smuller tty_prnt("%s ready for archive tape volume: %d\n",
115457193Smuller arcname, arvol);
115557193Smuller tty_prnt("Load the NEXT TAPE on the tape drive");
115657193Smuller } else {
115757193Smuller tty_prnt("%s ready for archive volume: %d\n",
115857193Smuller arcname, arvol);
115957193Smuller tty_prnt("Load the NEXT STORAGE MEDIA (if required)");
116057193Smuller }
116157193Smuller
116257193Smuller if ((act == ARCHIVE) || (act == APPND))
116357193Smuller tty_prnt(" and make sure it is WRITE ENABLED.\n");
116457193Smuller else
116557193Smuller tty_prnt("\n");
116657193Smuller
116757193Smuller for(;;) {
1168*66890Sbostic tty_prnt("Type \"y\" to continue, \".\" to quit %s,",
1169*66890Sbostic argv0);
117057193Smuller tty_prnt(" or \"s\" to switch to new device.\nIf you");
117157193Smuller tty_prnt(" cannot change storage media, type \"s\"\n");
117257193Smuller tty_prnt("Is the device ready and online? > ");
117357193Smuller
117457193Smuller if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){
117557193Smuller done = 1;
117657193Smuller lstrval = -1;
1177*66890Sbostic tty_prnt("Quitting %s!\n", argv0);
117857193Smuller vfpart = 0;
117957193Smuller return(-1);
118057193Smuller }
118157193Smuller
118257193Smuller if ((buf[0] == '\0') || (buf[1] != '\0')) {
118357193Smuller tty_prnt("%s unknown command, try again\n",buf);
118457193Smuller continue;
118557193Smuller }
118657193Smuller
118757193Smuller switch (buf[0]) {
118857193Smuller case 'y':
118957193Smuller case 'Y':
119057193Smuller /*
119157193Smuller * we are to continue with the same device
119257193Smuller */
119357193Smuller if (ar_open(arcname) >= 0)
119457193Smuller return(0);
119557193Smuller tty_prnt("Cannot re-open %s, try again\n",
119657193Smuller arcname);
119757193Smuller continue;
119857193Smuller case 's':
119957193Smuller case 'S':
120057193Smuller /*
120157193Smuller * user wants to open a different device
120257193Smuller */
120357193Smuller tty_prnt("Switching to a different archive\n");
120457193Smuller break;
120557193Smuller default:
120657193Smuller tty_prnt("%s unknown command, try again\n",buf);
120757193Smuller continue;
120857193Smuller }
120957193Smuller break;
121057193Smuller }
121157193Smuller } else
121257193Smuller tty_prnt("Ready for archive volume: %d\n", arvol);
121357193Smuller
121457193Smuller /*
121557193Smuller * have to go to a different archive
121657193Smuller */
121757193Smuller for (;;) {
1218*66890Sbostic tty_prnt("Input archive name or \".\" to quit %s.\n", argv0);
121957193Smuller tty_prnt("Archive name > ");
122057193Smuller
122157193Smuller if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) {
122257193Smuller done = 1;
122357193Smuller lstrval = -1;
1224*66890Sbostic tty_prnt("Quitting %s!\n", argv0);
122557193Smuller vfpart = 0;
122657193Smuller return(-1);
122757193Smuller }
122857193Smuller if (buf[0] == '\0') {
122957193Smuller tty_prnt("Empty file name, try again\n");
123057193Smuller continue;
123157193Smuller }
123257193Smuller if (!strcmp(buf, "..")) {
123357193Smuller tty_prnt("Illegal file name: .. try again\n");
123457193Smuller continue;
123557193Smuller }
123657193Smuller if (strlen(buf) > PAXPATHLEN) {
123757193Smuller tty_prnt("File name too long, try again\n");
123857193Smuller continue;
123957193Smuller }
124057193Smuller
124157193Smuller /*
124257193Smuller * try to open new archive
124357193Smuller */
124457193Smuller if (ar_open(buf) >= 0) {
124557193Smuller if (freeit) {
124657193Smuller (void)free(arcname);
124757193Smuller freeit = 0;
124857193Smuller }
124957193Smuller if ((arcname = strdup(buf)) == NULL) {
125057193Smuller done = 1;
125157193Smuller lstrval = -1;
125257535Smuller warn(0, "Cannot save archive name.");
125357193Smuller return(-1);
125457193Smuller }
125557193Smuller freeit = 1;
125657193Smuller break;
125757193Smuller }
125857193Smuller tty_prnt("Cannot open %s, try again\n", buf);
125957193Smuller continue;
126057193Smuller }
126157193Smuller return(0);
126257193Smuller }
1263