xref: /csrg-svn/bin/pax/ar_io.c (revision 57578)
157193Smuller /*-
257193Smuller  * Copyright (c) 1992 Keith Muller.
357193Smuller  * Copyright (c) 1992 The Regents of the University of California.
457193Smuller  * 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*57578Smuller static char sccsid[] = "@(#)ar_io.c	1.3 (Berkeley) 01/16/93";
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 */
4457193Smuller static int artyp;			/* 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 */
5257193Smuller static int phyblk; 			/* size of physical block on TAPE */
53*57578Smuller static int wr_trail = 1;		/* trailer was rewritten in append */
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
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;
8257193Smuller 	phyblk = did_io = io_ok = invld_rec = 0;
8357193Smuller 	flcnt = 0;
8457193Smuller 
8557193Smuller 	/*
8657193Smuller 	 * open based on overall operation mode
8757193Smuller 	 */
8857193Smuller 	switch (act) {
8957193Smuller 	case LIST:
9057193Smuller 	case EXTRACT:
9157193Smuller 		if (name == NULL) {
9257193Smuller 			arfd = STDIN_FILENO;
9357193Smuller 			arcname = STDN;
9457193Smuller 		} else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
9557535Smuller 			syswarn(0, errno, "Failed open to read on %s", name);
9657193Smuller 		break;
9757193Smuller 	case ARCHIVE:
9857193Smuller 		if (name == NULL) {
9957193Smuller 			arfd = STDOUT_FILENO;
10057193Smuller 			arcname = STDO;
10157193Smuller 		} else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
10257535Smuller 			syswarn(0, errno, "Failed open to write on %s", name);
10357193Smuller 		break;
10457193Smuller 	case APPND:
10557193Smuller 		if (name == NULL) {
10657193Smuller 			arfd = STDOUT_FILENO;
10757193Smuller 			arcname = STDO;
10857193Smuller 		} else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
10957535Smuller 			syswarn(0, errno, "Failed open to read/write on %s",
11057193Smuller 				name);
11157193Smuller 		break;
11257193Smuller 	case COPY:
11357193Smuller 		/*
11457193Smuller 		 * arfd not used in COPY mode
11557193Smuller 		 */
11657193Smuller 		arcname = "<NONE>";
11757193Smuller 		lstrval = 1;
11857193Smuller 		return(0);
11957193Smuller 	}
12057193Smuller 	if (arfd < 0)
12157193Smuller 		return(-1);
12257193Smuller 
12357193Smuller 	/*
12457193Smuller 	 * set up is based on device type
12557193Smuller 	 */
12657193Smuller 	if (fstat(arfd, &arsb) < 0) {
12757535Smuller 		syswarn(0, errno, "Failed stat on %s", arcname);
12857193Smuller 		return(-1);
12957193Smuller 	}
13057193Smuller 	if (S_ISDIR(arsb.st_mode)) {
13157535Smuller 		warn(0, "Cannot write an archive on top of a directory %s",
13257193Smuller 		    arcname);
13357193Smuller 		return(-1);
13457193Smuller 	}
13557193Smuller 	if (S_ISCHR(arsb.st_mode))
13657193Smuller 		artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
13757193Smuller 	else if (S_ISBLK(arsb.st_mode))
13857193Smuller 		artyp = ISBLK;
13957193Smuller 	else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
14057193Smuller 		artyp = ISPIPE;
14157193Smuller 	else
14257193Smuller 		artyp = ISREG;
14357193Smuller 
14457193Smuller 	/*
14557535Smuller 	 * if we are writing, we are done
14657193Smuller 	 */
14757193Smuller 	if (act == ARCHIVE) {
14857193Smuller 		blksz = rdblksz = wrblksz;
14957193Smuller 		lstrval = 1;
15057193Smuller 		return(0);
15157193Smuller 	}
15257193Smuller 
15357193Smuller 	/*
15457193Smuller 	 * set default blksz on read. APPNDs writes rdblksz on the last volume
15557193Smuller 	 * On all new archive volumes, we shift to wrblksz (if the user
15657193Smuller 	 * specified one, otherwize we will continue to use rdblksz). We
15757193Smuller 	 * must to set blocksize based on what kind of device the archive is
15857193Smuller 	 * stored.
15957193Smuller 	 */
16057193Smuller 	switch(artyp) {
16157193Smuller 	case ISTAPE:
16257193Smuller 		/*
16357193Smuller 		 * Tape drives come in at least two flavors. Those that support
16457193Smuller 		 * variable sized records and those that have fixed sized
16557193Smuller 		 * records. They must be treated differently. For tape drives
16657193Smuller 		 * that support variable sized records, we must make large
16757193Smuller 		 * reads to make sure we get the entire record, otherwise we
16857193Smuller 		 * will just get the first part of the record (up to size we
16957193Smuller 		 * asked). Tapes with fixed sized records may or may not return
17057193Smuller 		 * multiple records in a single read. We really do not care
17157193Smuller 		 * what the physical record size is UNLESS we are going to
17257193Smuller 		 * append. (We will need the physical block size to rewrite
17357193Smuller 		 * the trailer). Only when we are appending do we go to the
17457535Smuller 		 * effort to figure out the true PHYSICAL record size.
17557193Smuller 		 */
17657193Smuller 		blksz = rdblksz = MAXBLK;
17757193Smuller 		break;
17857193Smuller 	case ISPIPE:
17957193Smuller 	case ISBLK:
18057193Smuller 	case ISCHR:
18157193Smuller 		/*
18257193Smuller 		 * Blocksize is not a major issue with these devices (but must
18357193Smuller 		 * be kept a multiple of 512). If the user specified a write
18457193Smuller 		 * block size, we use that to read. Under append, we must
18557193Smuller 		 * always keep blksz == rdblksz. Otherwise we go ahead and use
18657193Smuller 		 * the device optimal blocksize as (and if) returned by stat
18757193Smuller 		 * and if it is within pax specs.
18857193Smuller 		 */
18957193Smuller 		if ((act == APPND) && wrblksz) {
19057193Smuller 			blksz = rdblksz = wrblksz;
19157193Smuller 			break;
19257193Smuller 		}
19357193Smuller 
19457193Smuller 		if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) &&
19557193Smuller 		    ((arsb.st_blksize % BLKMULT) == 0))
19657193Smuller 			rdblksz = arsb.st_blksize;
19757193Smuller 		else
19857193Smuller 			rdblksz = DEVBLK;
19957193Smuller 		/*
20057193Smuller 		 * For performance go for large reads when we can without harm
20157193Smuller 		 */
20257193Smuller 		if ((act == APPND) || (artyp == ISCHR))
20357193Smuller 			blksz = rdblksz;
20457193Smuller 		else
20557193Smuller 			blksz = MAXBLK;
20657193Smuller 		break;
20757193Smuller 	case ISREG:
20857193Smuller 		/*
20957193Smuller 		 * if the user specified wrblksz works, use it. Under appends
21057193Smuller 		 * we must always keep blksz == rdblksz
21157193Smuller 		 */
21257193Smuller 		if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){
21357193Smuller 			blksz = rdblksz = wrblksz;
21457193Smuller 			break;
21557193Smuller 		}
21657193Smuller 		/*
21757193Smuller 		 * See if we can find the blocking factor from the file size
21857193Smuller 		 */
21957193Smuller 		for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT)
22057193Smuller 			if ((arsb.st_size % rdblksz) == 0)
22157193Smuller 				break;
22257193Smuller 		/*
22357193Smuller 		 * When we cannont find a match, we may have a flawed archive.
22457193Smuller 		 */
22557193Smuller 		if (rdblksz <= 0)
22657193Smuller 			rdblksz = FILEBLK;
22757193Smuller 		/*
22857193Smuller 		 * for performance go for large reads when we can
22957193Smuller 		 */
23057193Smuller 		if (act == APPND)
23157193Smuller 			blksz = rdblksz;
23257193Smuller 		else
23357193Smuller 			blksz = MAXBLK;
23457193Smuller 		break;
23557193Smuller 	default:
23657193Smuller 		/*
23757193Smuller 		 * should never happen, worse case, slow...
23857193Smuller 		 */
23957193Smuller 		blksz = rdblksz = BLKMULT;
24057193Smuller 		break;
24157193Smuller 	}
24257193Smuller 	lstrval = 1;
24357193Smuller 	return(0);
24457193Smuller }
24557193Smuller 
24657193Smuller /*
24757193Smuller  * ar_close()
24857193Smuller  *	closes archive device, increments volume number, and prints i/o summary
24957193Smuller  */
25057193Smuller #if __STDC__
25157193Smuller void
25257193Smuller ar_close(void)
25357193Smuller #else
25457193Smuller void
25557193Smuller ar_close()
25657193Smuller #endif
25757193Smuller {
25857193Smuller 	FILE *outf;
25957193Smuller 
260*57578Smuller 	if (arfd < 0) {
261*57578Smuller 		did_io = io_ok = flcnt = 0;
262*57578Smuller 		return;
263*57578Smuller 	}
264*57578Smuller 
26557535Smuller 	if (act == LIST)
26657535Smuller 		outf = stdout;
26757535Smuller 	else
26857535Smuller 		outf = stderr;
26957535Smuller 
27057535Smuller 	/*
27157535Smuller 	 * Close archive file. This may take a LONG while on tapes (we may be
27257535Smuller 	 * forced to wait for the rewind to complete) so tell the user what is
27357535Smuller 	 * going on (this avoids the user hitting control-c thinking pax is
27457535Smuller 	 * broken).
27557535Smuller 	 */
276*57578Smuller 	if (vflag && (artyp == ISTAPE)) {
277*57578Smuller 		if (vfpart)
27857535Smuller 			(void)putc('\n', outf);
27957535Smuller 		(void)fputs("pax: Waiting for tape drive close to complete...",
28057535Smuller 		    outf);
28157535Smuller 		(void)fflush(outf);
28257535Smuller 	}
28357535Smuller 
28457193Smuller 	(void)close(arfd);
28557535Smuller 
286*57578Smuller 	if (vflag && (artyp == ISTAPE)) {
28757535Smuller 		(void)fputs("done.\n", outf);
288*57578Smuller 		vfpart = 0;
28957535Smuller 		(void)fflush(outf);
29057535Smuller 	}
29157193Smuller 	arfd = -1;
29257535Smuller 
29357193Smuller 	if (!io_ok && !did_io) {
29457193Smuller 		flcnt = 0;
29557193Smuller 		return;
29657193Smuller 	}
29757193Smuller 	did_io = io_ok = 0;
29857193Smuller 
29957193Smuller 	/*
30057193Smuller 	 * The volume number is only increased when the last device has data
30157535Smuller 	 * and we have already determined the archive format.
30257193Smuller 	 */
30357535Smuller 	if (frmt != NULL)
30457535Smuller 		++arvol;
30557535Smuller 
30657193Smuller 	if (!vflag) {
30757193Smuller 		flcnt = 0;
30857193Smuller 		return;
30957193Smuller 	}
31057193Smuller 
31157193Smuller 	/*
31257193Smuller 	 * Print out a summary of I/O for this archive volume.
31357193Smuller 	 */
31457193Smuller 	if (vfpart) {
31557193Smuller 		(void)putc('\n', outf);
31657193Smuller 		vfpart = 0;
31757193Smuller 	}
31857193Smuller 
31957535Smuller 	/*
32057535Smuller 	 * If we have not determined the format yet, we just say how many bytes
32157535Smuller 	 * we have skipped over looking for a header to id. there is no way we
32257535Smuller 	 * could have written anything yet.
32357535Smuller 	 */
32457535Smuller 	if (frmt == NULL) {
32557535Smuller #	ifdef NET2_STAT
32657535Smuller 		(void)fprintf(outf, "pax: unknown format, %lu bytes skipped.\n",
32757535Smuller #	else
32857535Smuller 		(void)fprintf(outf, "pax: unknown format, %qu bytes skipped.\n",
32957535Smuller #	endif
33057535Smuller 		    rdcnt);
33157535Smuller 		(void)fflush(outf);
33257535Smuller 		flcnt = 0;
33357535Smuller 		return;
33457535Smuller 	}
33557535Smuller 
33657193Smuller 	(void)fprintf(outf,
33757193Smuller #	ifdef NET2_STAT
33857535Smuller 	    "pax: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
33957193Smuller #	else
34057535Smuller 	    "pax: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
34157193Smuller #	endif
34257193Smuller 	    frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
34357193Smuller 	(void)fflush(outf);
34457193Smuller 	flcnt = 0;
34557193Smuller }
34657193Smuller 
34757193Smuller /*
34857193Smuller  * ar_set_wr()
349*57578Smuller  *	Set up device right before switching from read to write in an append.
350*57578Smuller  *	device dependent code (if required) to do this should be added here.
351*57578Smuller  *	For all archive devices we are already positioned at the place we want
352*57578Smuller  *	to start writing when this routine is called.
35357193Smuller  * Return:
35457193Smuller  *	0 if all ready to write, -1 otherwise
35557193Smuller  */
35657193Smuller 
35757193Smuller #if __STDC__
35857193Smuller int
35957193Smuller ar_set_wr(void)
36057193Smuller #else
36157193Smuller int
36257193Smuller ar_set_wr()
36357193Smuller #endif
36457193Smuller {
36557193Smuller 	off_t cpos;
36657193Smuller 
367*57578Smuller 	/*
368*57578Smuller 	 * we must make sure the trailer is rewritten on append, ar_next()
369*57578Smuller 	 * will stop us if the archive containing the trailer was not written
370*57578Smuller 	 */
371*57578Smuller 	wr_trail = 0;
372*57578Smuller 
37357193Smuller 	/*
37457193Smuller 	 * Add any device dependent code as required here
37557193Smuller 	 */
37657193Smuller 	if (artyp != ISREG)
37757193Smuller 		return(0);
37857193Smuller 	/*
37957535Smuller 	 * Ok we have an archive in a regular file. If we were rewriting a
38057535Smuller 	 * file, we must get rid of all the stuff after the current offset
38157535Smuller 	 * (it was not written by pax).
38257193Smuller 	 */
38357193Smuller 	if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) ||
384*57578Smuller 	    (ftruncate(arfd, cpos) < 0)) {
385*57578Smuller 		syswarn(1, errno, "Unable to truncate archive file");
38657193Smuller 		return(-1);
387*57578Smuller 	}
38857193Smuller 	return(0);
38957193Smuller }
39057193Smuller 
39157193Smuller /*
39257193Smuller  * ar_app_ok()
39357193Smuller  *	check if the last volume in the archive allows appends. We cannot check
39457193Smuller  *	this until we are ready to write since there is no spec that says all
39557193Smuller  *	volumes in a single archive have to be of the same type...
39657193Smuller  * Return:
39757193Smuller  *	0 if we can append, -1 otherwise.
39857193Smuller  */
39957193Smuller 
40057193Smuller #if __STDC__
40157193Smuller int
40257193Smuller ar_app_ok(void)
40357193Smuller #else
40457193Smuller int
40557193Smuller ar_app_ok()
40657193Smuller #endif
40757193Smuller {
40857193Smuller 	if (artyp == ISPIPE) {
40957193Smuller 		warn(1, "Cannot append to an archive obtained from a pipe.");
41057193Smuller 		return(-1);
41157193Smuller 	}
41257193Smuller 
41357193Smuller 	if (!invld_rec)
41457193Smuller 		return(0);
41557193Smuller 	warn(1,"Cannot append, device record size %d does not support pax spec",
41657193Smuller 		rdblksz);
41757193Smuller 	return(-1);
41857193Smuller }
41957193Smuller 
42057193Smuller /*
42157193Smuller  * ar_read()
42257193Smuller  *	read up to a specified number of bytes from the archive into the
42357193Smuller  *	supplied buffer. When dealing with tapes we may not always be able to
42457193Smuller  *	read what we want.
42557193Smuller  * Return:
42657193Smuller  *	Number of bytes in buffer. 0 for end of file, -1 for a read error.
42757193Smuller  */
42857193Smuller 
42957193Smuller #if __STDC__
43057193Smuller int
43157193Smuller ar_read(register char *buf, register int cnt)
43257193Smuller #else
43357193Smuller int
43457193Smuller ar_read(buf, cnt)
43557193Smuller 	register char *buf;
43657193Smuller 	register int cnt;
43757193Smuller #endif
43857193Smuller {
43957193Smuller 	register int res = 0;
44057193Smuller 
44157193Smuller 	/*
44257193Smuller 	 * if last i/o was in error, no more reads until reset or new volume
44357193Smuller 	 */
44457193Smuller 	if (lstrval <= 0)
44557193Smuller 		return(lstrval);
44657193Smuller 
44757193Smuller 	/*
44857193Smuller 	 * how we read must be based on device type
44957193Smuller 	 */
45057193Smuller 	switch (artyp) {
45157193Smuller 	case ISTAPE:
45257193Smuller 		if ((res = read(arfd, buf, cnt)) > 0) {
45357193Smuller 			/*
45457193Smuller 			 * CAUTION: tape systems may not always return the same
45557193Smuller 			 * sized records so we leave blksz == MAXBLK. The
45657193Smuller 			 * physical record size that a tape drive supports is
45757193Smuller 			 * very hard to determine in a uniform and portable
45857193Smuller 			 * manner.
45957193Smuller 			 */
46057193Smuller 			io_ok = 1;
46157193Smuller 			if (res != rdblksz) {
46257193Smuller 				/*
46357193Smuller 				 * Record size changed. If this is happens on
46457535Smuller 				 * any record after the first, we probably have
46557535Smuller 				 * a tape drive which has a fixed record size
46657535Smuller 				 * we are getting multiple records in a single
46757535Smuller 				 * read). Watch out for record blocking that
46857535Smuller 				 * violates pax spec (must be a multiple of
46957535Smuller 				 * BLKMULT).
47057193Smuller 				 */
47157193Smuller 				rdblksz = res;
47257193Smuller 				if (rdblksz % BLKMULT)
47357193Smuller 					invld_rec = 1;
47457193Smuller 			}
47557193Smuller 			return(res);
47657193Smuller 		}
47757193Smuller 		break;
47857193Smuller 	case ISREG:
47957193Smuller 	case ISBLK:
48057193Smuller 	case ISCHR:
48157193Smuller 	case ISPIPE:
48257193Smuller 	default:
48357193Smuller 		/*
48457193Smuller 		 * Files are so easy to deal with. These other things cannot
48557193Smuller 		 * be trusted at all. So when we are dealing with character
48657193Smuller 		 * devices and pipes we just take what they have ready for us
48757193Smuller 		 * and return. Trying to do anything else with them runs the
48857193Smuller 		 * risk of failure.
48957193Smuller 		 */
49057193Smuller 		if ((res = read(arfd, buf, cnt)) > 0) {
49157193Smuller 			io_ok = 1;
49257193Smuller 			return(res);
49357193Smuller 		}
49457193Smuller 		break;
49557193Smuller 	}
49657193Smuller 
49757193Smuller 	/*
49857193Smuller 	 * We are in trouble at this point, something is broken...
49957193Smuller 	 */
50057193Smuller 	lstrval = res;
50157193Smuller 	if (res < 0)
50257193Smuller 		syswarn(1, errno, "Failed read on archive volume %d", arvol);
50357193Smuller 	else
50457193Smuller 		warn(0, "End of archive volume %d reached", arvol);
50557193Smuller 	return(res);
50657193Smuller }
50757193Smuller 
50857193Smuller /*
50957193Smuller  * ar_write()
51057193Smuller  *	Write a specified number of bytes in supplied buffer to the archive
51157193Smuller  *	device so it appears as a single "block". Deals with errors and tries
51257193Smuller  *	to recover when faced with short writes.
51357193Smuller  * Return:
51457193Smuller  *	Number of bytes written. 0 indicates end of volume reached and with no
51557193Smuller  *	flaws (as best that can be detected). A -1 indicates an unrecoverable
51657193Smuller  *	error in the archive occured.
51757193Smuller  */
51857193Smuller 
51957193Smuller #if __STDC__
52057193Smuller int
52157193Smuller ar_write(register char *buf, register int bsz)
52257193Smuller #else
52357193Smuller int
52457193Smuller ar_write(buf, bsz)
52557193Smuller 	register char *buf;
52657193Smuller 	register int bsz;
52757193Smuller #endif
52857193Smuller {
52957193Smuller 	register int res;
53057193Smuller 	off_t cpos;
53157193Smuller 
53257193Smuller 	/*
53357193Smuller 	 * do not allow pax to create a "bad" archive. Once a write fails on
53457193Smuller 	 * an archive volume prevent further writes to it.
53557193Smuller 	 */
53657193Smuller 	if (lstrval <= 0)
53757193Smuller 		return(lstrval);
53857193Smuller 
53957193Smuller 	if ((res = write(arfd, buf, bsz)) == bsz) {
540*57578Smuller 		wr_trail = 1;
54157193Smuller 		io_ok = 1;
54257193Smuller 		return(bsz);
54357193Smuller 	}
54457193Smuller 	/*
54557193Smuller 	 * write broke, see what we can do with it. We try to send any partial
54657535Smuller 	 * writes that may violate pax spec to the next archive volume.
54757193Smuller 	 */
54857193Smuller 	if (res < 0)
54957193Smuller 		lstrval = res;
55057193Smuller 	else
55157193Smuller 		lstrval = 0;
55257193Smuller 
55357193Smuller 	switch (artyp) {
55457193Smuller 	case ISREG:
55557193Smuller 		if ((res > 0) && (res % BLKMULT)) {
55657193Smuller 			/*
55757193Smuller 		 	 * try to fix up partial writes which are not BLKMULT
55857193Smuller 			 * in size by forcing the runt record to next archive
55957193Smuller 			 * volume
56057193Smuller 		 	 */
56157193Smuller 			if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
56257193Smuller 				break;
56357193Smuller 			cpos -= (off_t)res;
56457193Smuller 			if (ftruncate(arfd, cpos) < 0)
56557193Smuller 				break;
56657193Smuller 			res = lstrval = 0;
56757193Smuller 			break;
56857193Smuller 		}
56957193Smuller 		if (res >= 0)
57057193Smuller 			break;
57157193Smuller 		/*
57257193Smuller 		 * if file is out of space, handle it like a return of 0
57357193Smuller 		 */
57457193Smuller 		if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT))
57557193Smuller 			res = lstrval = 0;
57657193Smuller 		break;
57757193Smuller 	case ISTAPE:
57857193Smuller 	case ISCHR:
57957193Smuller 	case ISBLK:
58057193Smuller 		if (res >= 0)
58157193Smuller 			break;
58257193Smuller 		if (errno == EACCES) {
58357193Smuller 			warn(0, "Write failed, archive is write protected.");
58457193Smuller 			res = lstrval = 0;
58557193Smuller 			return(0);
58657193Smuller 		}
58757193Smuller 		/*
58857193Smuller 		 * see if we reached the end of media, if so force a change to
58957193Smuller 		 * the next volume
59057193Smuller 		 */
59157193Smuller 		if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO))
59257193Smuller 			res = lstrval = 0;
59357193Smuller 		break;
59457193Smuller 	case ISPIPE:
59557193Smuller 	default:
59657193Smuller 		/*
59757193Smuller 		 * we cannot fix errors to these devices
59857193Smuller 		 */
59957193Smuller 		break;
60057193Smuller 	}
60157193Smuller 
60257193Smuller 	/*
60357193Smuller 	 * Better tell the user the bad news...
60457535Smuller 	 * if this is a block aligned archive format, we may have a bad archive
60557535Smuller 	 * if the format wants the header to start at a BLKMULT boundry. While
60657193Smuller 	 * we can deal with the mis-aligned data, it violates spec and other
60757193Smuller 	 * archive readers will likely fail. if the format is not block
60857535Smuller 	 * aligned, the user may be lucky (and the archive is ok).
60957193Smuller 	 */
610*57578Smuller 	if (res >= 0) {
611*57578Smuller 		if (res > 0)
612*57578Smuller 			wr_trail = 1;
61357193Smuller 		io_ok = 1;
614*57578Smuller 	}
615*57578Smuller 
616*57578Smuller 	/*
617*57578Smuller 	 * If we were trying to rewrite the trailer and it didn't work, we
618*57578Smuller 	 * must quit right away.
619*57578Smuller 	 */
620*57578Smuller 	if (!wr_trail && (res <= 0)) {
621*57578Smuller 		warn(1,"Unable to append, trailer re-write failed. Quitting.");
622*57578Smuller 		return(res);
623*57578Smuller 	}
624*57578Smuller 
625*57578Smuller 	if (res == 0)
62657193Smuller 		warn(0, "End of archive volume %d reached", arvol);
62757193Smuller 	else if (res < 0)
62857193Smuller 		syswarn(1, errno, "Failed write to archive volume: %d", arvol);
62957193Smuller 	else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0))
63057193Smuller 		warn(0,"WARNING: partial archive write. Archive MAY BE FLAWED");
63157193Smuller 	else
63257193Smuller 		warn(1,"WARNING: partial archive write. Archive IS FLAWED");
63357193Smuller 	return(res);
63457193Smuller }
63557193Smuller 
63657193Smuller /*
63757193Smuller  * ar_rdsync()
63857193Smuller  *	Try to move past a bad spot on a flawed archive as needed to continue
63957193Smuller  *	I/O. Clears error flags to allow I/O to continue.
64057193Smuller  * Return:
64157193Smuller  *	0 when ok to try i/o again, -1 otherwise.
64257193Smuller  */
64357193Smuller 
64457193Smuller #if __STDC__
64557193Smuller int
64657193Smuller ar_rdsync(void)
64757193Smuller #else
64857193Smuller int
64957193Smuller ar_rdsync()
65057193Smuller #endif
65157193Smuller {
65257193Smuller 	long fsbz;
65357193Smuller 	off_t cpos;
65457193Smuller 	off_t mpos;
65557193Smuller         struct mtop mb;
65657193Smuller 
65757193Smuller 	/*
65857193Smuller 	 * Fail resync attempts at user request (done) or this is going to be
65957193Smuller 	 * an update/append to a existing archive. if last i/o hit media end,
66057193Smuller 	 * we need to go to the next volume not try a resync
66157193Smuller 	 */
66257193Smuller 	if ((done > 0) || (lstrval == 0))
66357193Smuller 		return(-1);
66457193Smuller 
66557193Smuller 	if ((act == APPND) || (act == ARCHIVE)) {
66657193Smuller 		warn(1, "Cannot allow updates to an archive with flaws.");
66757193Smuller 		return(-1);
66857193Smuller 	}
66957193Smuller 	if (io_ok)
67057193Smuller 		did_io = 1;
67157193Smuller 
67257193Smuller 	switch(artyp) {
67357193Smuller 	case ISTAPE:
67457193Smuller 		/*
67557193Smuller 		 * if the last i/o was a successful data transfer, we assume
67657193Smuller 		 * the fault is just a bad record on the tape that we are now
67757193Smuller 		 * past. If we did not get any data since the last resync try
67857193Smuller 		 * to move the tape foward one PHYSICAL record past any
67957193Smuller 		 * damaged tape section. Some tape drives are stubborn and need
68057193Smuller 		 * to be pushed.
68157193Smuller 		 */
68257193Smuller 		if (io_ok) {
68357193Smuller 			io_ok = 0;
68457193Smuller 			lstrval = 1;
68557193Smuller 			break;
68657193Smuller 		}
68757193Smuller 		mb.mt_op = MTFSR;
68857193Smuller 		mb.mt_count = 1;
68957193Smuller 		if (ioctl(arfd, MTIOCTOP, &mb) < 0)
69057193Smuller 			break;
69157193Smuller 		lstrval = 1;
69257193Smuller 		break;
69357193Smuller 	case ISREG:
69457193Smuller 	case ISCHR:
69557193Smuller 	case ISBLK:
69657193Smuller 		/*
69757193Smuller 		 * try to step over the bad part of the device.
69857193Smuller 		 */
69957193Smuller 		io_ok = 0;
70057193Smuller 		if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
70157193Smuller 			fsbz = BLKMULT;
70257193Smuller 		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
70357193Smuller 			break;
70457193Smuller 		mpos = fsbz - (cpos % (off_t)fsbz);
70557193Smuller 		if (lseek(arfd, mpos, SEEK_CUR) < 0)
70657193Smuller 			break;
70757193Smuller 		lstrval = 1;
70857193Smuller 		break;
70957193Smuller 	case ISPIPE:
71057193Smuller 	default:
71157193Smuller 		/*
71257193Smuller 		 * cannot recover on these archive device types
71357193Smuller 		 */
71457193Smuller 		io_ok = 0;
71557193Smuller 		break;
71657193Smuller 	}
71757193Smuller 	if (lstrval <= 0) {
71857535Smuller 		warn(1, "Unable to recover from an archive read failure.");
71957193Smuller 		return(-1);
72057193Smuller 	}
72157193Smuller 	warn(0, "Attempting to recover from an archive read failure.");
72257193Smuller 	return(0);
72357193Smuller }
72457193Smuller 
72557193Smuller /*
72657193Smuller  * ar_fow()
72757193Smuller  *	Move the I/O position within the archive foward the specified number of
72857193Smuller  *	bytes as supported by the device. If we cannot move the requested
72957193Smuller  *	number of bytes, return the actual number of bytes moved in skipped.
73057193Smuller  * Return:
73157193Smuller  *	0 if moved the requested distance, -1 on complete failure, 1 on
73257193Smuller  *	partial move (the amount moved is in skipped)
73357193Smuller  */
73457193Smuller 
73557193Smuller #if __STDC__
73657193Smuller int
73757193Smuller ar_fow(off_t sksz, off_t *skipped)
73857193Smuller #else
73957193Smuller int
74057193Smuller ar_fow(sksz, skipped)
74157193Smuller 	off_t sksz;
74257193Smuller 	off_t *skipped;
74357193Smuller #endif
74457193Smuller {
74557193Smuller 	off_t cpos;
74657193Smuller 	off_t mpos;
74757193Smuller 
74857193Smuller 	*skipped = 0;
74957193Smuller 	if (sksz <= 0)
75057193Smuller 		return(0);
75157193Smuller 
75257193Smuller 	/*
75357193Smuller 	 * we cannot move foward at EOF or error
75457193Smuller 	 */
75557193Smuller 	if (lstrval <= 0)
75657193Smuller 		return(lstrval);
75757193Smuller 
75857193Smuller 	/*
75957193Smuller 	 * Safer to read forward on devices where it is hard to find the end of
76057193Smuller 	 * the media without reading to it. With tapes we cannot be sure of the
76157193Smuller 	 * number of physical blocks to skip (we do not know physical block
76257193Smuller 	 * size at this point), so we must only read foward on tapes!
76357193Smuller 	 */
76457193Smuller 	if (artyp != ISREG)
76557193Smuller 		return(0);
76657193Smuller 
76757193Smuller 	/*
76857193Smuller 	 * figure out where we are in the archive
76957193Smuller 	 */
77057193Smuller 	if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
77157193Smuller 		/*
77257193Smuller 	 	 * we can be asked to move farther than there are bytes in this
77357193Smuller 		 * volume, if so, just go to file end and let normal buf_fill()
77457193Smuller 		 * deal with the end of file (it will go to next volume by
77557193Smuller 		 * itself)
77657193Smuller 	 	 */
77757193Smuller 		if ((mpos = cpos + sksz) > arsb.st_size) {
77857193Smuller 			*skipped = arsb.st_size - cpos;
77957193Smuller 			mpos = arsb.st_size;
78057193Smuller 		} else
78157193Smuller 			*skipped = sksz;
78257193Smuller 		if (lseek(arfd, mpos, SEEK_SET) >= 0)
78357193Smuller 			return(0);
78457193Smuller 	}
78557193Smuller 	syswarn(1, errno, "Foward positioning operation on archive failed");
78657193Smuller 	lstrval = -1;
78757193Smuller 	return(-1);
78857193Smuller }
78957193Smuller 
79057193Smuller /*
79157193Smuller  * ar_rev()
79257193Smuller  *	move the i/o position within the archive backwards the specified byte
79357193Smuller  *	count as supported by the device. With tapes drives we RESET rdblksz to
79457193Smuller  *	the PHYSICAL blocksize.
79557193Smuller  *	NOTE: We should only be called to move backwards so we can rewrite the
79657193Smuller  *	last records (the trailer) of an archive (APPEND).
79757193Smuller  * Return:
79857193Smuller  *	0 if moved the requested distance, -1 on complete failure
79957193Smuller  */
80057193Smuller 
80157193Smuller #if __STDC__
80257193Smuller int
80357193Smuller ar_rev(off_t sksz)
80457193Smuller #else
80557193Smuller int
80657193Smuller ar_rev(sksz)
80757193Smuller 	off_t sksz;
80857193Smuller #endif
80957193Smuller {
81057193Smuller 	off_t cpos;
81157193Smuller         struct mtop mb;
81257193Smuller 
81357193Smuller 	/*
814*57578Smuller 	 * make sure we do not have try to reverse on a flawed archive
81557193Smuller 	 */
81657193Smuller 	if (lstrval < 0)
81757193Smuller 		return(lstrval);
81857193Smuller 
81957193Smuller 	switch(artyp) {
82057193Smuller 	case ISPIPE:
821*57578Smuller 		if (sksz <= 0)
822*57578Smuller 			break;
82357193Smuller 		/*
82457193Smuller 		 * cannot go backwards on these critters
82557193Smuller 		 */
826*57578Smuller 		warn(1, "Reverse positioning on pipes is not supported.");
827*57578Smuller 		lstrval = -1;
828*57578Smuller 		return(-1);
82957193Smuller 	case ISREG:
83057193Smuller 	case ISBLK:
83157193Smuller 	case ISCHR:
83257193Smuller 	default:
833*57578Smuller 		if (sksz <= 0)
834*57578Smuller 			break;
835*57578Smuller 
83657193Smuller 		/*
83757193Smuller 		 * For things other than files, backwards movement has a very
83857193Smuller 		 * high probability of failure as we really do not know the
83957193Smuller 		 * true attributes of the device we are talking to (the device
84057193Smuller 		 * may not even have the ability to lseek() in any direction).
841*57578Smuller 		 * First we figure out where we are in the archive.
84257193Smuller 		 */
843*57578Smuller 		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) {
844*57578Smuller 			syswarn(1, errno,
845*57578Smuller 			   "Unable to obtain current archive byte offset");
846*57578Smuller 			lstrval = -1;
847*57578Smuller 			return(-1);
848*57578Smuller 		}
84957193Smuller 
85057193Smuller 		/*
85157193Smuller 		 * we may try to go backwards past the start when the archive
85257193Smuller 		 * is only a single record. If this hapens and we are on a
85357193Smuller 		 * multi volume archive, we need to go to the end of the
85457193Smuller 		 * previous volume and continue our movement backwards from
855*57578Smuller 		 * there.
85657193Smuller 		 */
85757193Smuller 		if ((cpos -= sksz) < (off_t)0L) {
85857193Smuller 			if (arvol > 1) {
859*57578Smuller 				/*
860*57578Smuller 				 * this should never happen
861*57578Smuller 				 */
862*57578Smuller 				warn(1,"Reverse position on previous volume.");
86357193Smuller 				lstrval = -1;
86457193Smuller 				return(-1);
86557193Smuller 			}
86657193Smuller 			cpos = (off_t)0L;
86757193Smuller 		}
868*57578Smuller 		if (lseek(arfd, cpos, SEEK_SET) < 0) {
869*57578Smuller 			syswarn(1, errno, "Unable to seek archive backwards");
870*57578Smuller 			lstrval = -1;
871*57578Smuller 			return(-1);
872*57578Smuller 		}
873*57578Smuller 		break;
87457193Smuller 	case ISTAPE:
87557193Smuller 		/*
87657193Smuller 	 	 * Calculate and move the proper number of PHYSICAL tape
877*57578Smuller 		 * blocks. If the sksz is not an even multiple of the physical
87857193Smuller 		 * tape size, we cannot do the move (this should never happen).
87957193Smuller 		 * (We also cannot handler trailers spread over two vols).
880*57578Smuller 		 * get_phys() also makes sure we are in front of the filemark.
88157193Smuller 	 	 */
88257193Smuller 		if (get_phys() < 0) {
883*57578Smuller 			lstrval = -1;
884*57578Smuller 			return(-1);
88557193Smuller 		}
88657193Smuller 
887*57578Smuller 		/*
888*57578Smuller 		 * make sure future tape reads only go by physical tape block
889*57578Smuller 		 * size (set rdblksz to the real size).
890*57578Smuller 		 */
891*57578Smuller 		rdblksz = phyblk;
892*57578Smuller 
893*57578Smuller 		/*
894*57578Smuller 		 * if no movement is required, just return (we must be after
895*57578Smuller 		 * get_phys() so the physical blocksize is properly set)
896*57578Smuller 		 */
897*57578Smuller 		if (sksz <= 0)
898*57578Smuller 			break;
899*57578Smuller 
900*57578Smuller 		/*
901*57578Smuller 		 * ok we have to move. Make sure the tape drive can do it.
902*57578Smuller 		 */
90357193Smuller 		if (sksz % phyblk) {
904*57578Smuller 			warn(1,
905*57578Smuller 			    "Tape drive unable to backspace requested amount");
90657193Smuller 			lstrval = -1;
90757193Smuller 			return(-1);
90857193Smuller 		}
90957193Smuller 
910*57578Smuller 		/*
911*57578Smuller 		 * move backwards the requested number of bytes
912*57578Smuller 		 */
91357193Smuller 		mb.mt_op = MTBSR;
91457193Smuller 		mb.mt_count = sksz/phyblk;
915*57578Smuller 		if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
916*57578Smuller 			syswarn(1,errno, "Unable to backspace tape %d blocks.",
917*57578Smuller 			    mb.mt_count);
918*57578Smuller 			lstrval = -1;
919*57578Smuller 			return(-1);
920*57578Smuller 		}
921*57578Smuller 		break;
92257193Smuller 	}
923*57578Smuller 	lstrval = 1;
924*57578Smuller 	return(0);
92557193Smuller }
92657193Smuller 
92757193Smuller /*
92857193Smuller  * get_phys()
929*57578Smuller  *	Determine the physical block size on a tape drive. We need the physical
930*57578Smuller  *	block size so we know how many bytes we skip over when we move with
931*57578Smuller  *	mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
932*57578Smuller  *	return.
933*57578Smuller  *	This is one really SLOW routine...
93457193Smuller  * Return:
93557193Smuller  *	0 if ok, -1 otherwise
93657193Smuller  */
93757193Smuller 
93857193Smuller #if __STDC__
93957193Smuller static int
94057193Smuller get_phys(void)
94157193Smuller #else
94257193Smuller static int
94357193Smuller get_phys()
94457193Smuller #endif
94557193Smuller {
946*57578Smuller 	register int padsz = 0;
94757535Smuller 	register int res;
94857535Smuller 	struct mtop mb;
949*57578Smuller 	char scbuf[MAXBLK];
95057193Smuller 
95157193Smuller 	/*
952*57578Smuller 	 * move to the file mark, and then back up one record and read it.
953*57578Smuller 	 * this should tell us the physical record size the tape is using.
954*57578Smuller 	 */
955*57578Smuller 	if (lstrval == 1) {
956*57578Smuller 		/*
957*57578Smuller 		 * we know we are at file mark when we get back a 0 from
958*57578Smuller 		 * read()
959*57578Smuller 		 */
960*57578Smuller 		while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
961*57578Smuller 			padsz += res;
962*57578Smuller 		if (res < 0) {
963*57578Smuller 			syswarn(1, errno, "Unable to locate tape filemark.");
964*57578Smuller 			return(-1);
965*57578Smuller 		}
966*57578Smuller 	}
96757193Smuller 
968*57578Smuller 	/*
969*57578Smuller 	 * move backwards over the file mark so we are at the end of the
970*57578Smuller 	 * last record.
971*57578Smuller 	 */
972*57578Smuller 	mb.mt_op = MTBSF;
97357193Smuller 	mb.mt_count = 1;
974*57578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
975*57578Smuller 		syswarn(1, errno, "Unable to backspace over tape filemark.");
97657193Smuller 		return(-1);
97757535Smuller 	}
97857193Smuller 
97957193Smuller 	/*
980*57578Smuller 	 * move backwards so we are in front of the last record and read it to
981*57578Smuller 	 * get physical tape blocksize.
98257193Smuller 	 */
983*57578Smuller 	mb.mt_op = MTBSR;
984*57578Smuller 	mb.mt_count = 1;
985*57578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
986*57578Smuller 		syswarn(1, errno, "Unable to backspace over last tape block.");
98757193Smuller 		return(-1);
988*57578Smuller 	}
989*57578Smuller 	if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) {
990*57578Smuller 		syswarn(1, errno, "Cannot determine archive tape blocksize.");
991*57578Smuller 		return(-1);
992*57578Smuller 	}
99357535Smuller 
99457535Smuller 	/*
995*57578Smuller 	 * read foward to the file mark, then back up in front of the filemark
996*57578Smuller 	 * (this is a bit paranoid, but should be safe to do).
99757535Smuller 	 */
998*57578Smuller 	while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
999*57578Smuller 		;
1000*57578Smuller 	if (res < 0) {
1001*57578Smuller 		syswarn(1, errno, "Unable to locate tape filemark.");
100257535Smuller 		return(-1);
1003*57578Smuller 	}
1004*57578Smuller 	mb.mt_op = MTBSF;
1005*57578Smuller 	mb.mt_count = 1;
1006*57578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
1007*57578Smuller 		syswarn(1, errno, "Unable to backspace over tape filemark.");
1008*57578Smuller 		return(-1);
1009*57578Smuller 	}
101057535Smuller 
101157535Smuller 	/*
1012*57578Smuller 	 * set lstrval so we know that the filemark has not been seen
101357535Smuller 	 */
1014*57578Smuller 	lstrval = 1;
1015*57578Smuller 
1016*57578Smuller 	/*
1017*57578Smuller 	 * return if there was no padding
1018*57578Smuller 	 */
1019*57578Smuller 	if (padsz == 0)
102057535Smuller 		return(0);
102157535Smuller 
102257535Smuller 	/*
1023*57578Smuller 	 * make sure we can move backwards over the padding. (this should
1024*57578Smuller 	 * never fail).
102557535Smuller 	 */
1026*57578Smuller 	if (padsz % phyblk) {
1027*57578Smuller 		warn(1, "Tape drive unable to backspace requested amount");
102857535Smuller 		return(-1);
1029*57578Smuller 	}
103057535Smuller 
103157535Smuller 	/*
1032*57578Smuller 	 * move backwards over the padding so the head is where it was when
1033*57578Smuller 	 * we were first called (if required).
103457535Smuller 	 */
1035*57578Smuller 	mb.mt_op = MTBSR;
1036*57578Smuller 	mb.mt_count = padsz/phyblk;
1037*57578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
1038*57578Smuller 		syswarn(1,errno,"Unable to backspace tape over %d pad blocks",
1039*57578Smuller 		    mb.mt_count);
104057535Smuller 		return(-1);
1041*57578Smuller 	}
104257193Smuller 	return(0);
104357193Smuller }
104457193Smuller 
104557193Smuller /*
104657193Smuller  * ar_next()
104757535Smuller  *	prompts the user for the next volume in this archive. For some devices
104857535Smuller  *	we may allow the media to be changed. Otherwise a new archive is
104957535Smuller  *	prompted for. By pax spec, if there is no controlling tty or an eof is
105057535Smuller  *	read on tty input, we must quit pax.
105157193Smuller  * Return:
105257193Smuller  *	0 when ready to continue, -1 when all done
105357193Smuller  */
105457193Smuller 
105557193Smuller #if __STDC__
105657193Smuller int
105757193Smuller ar_next(void)
105857193Smuller #else
105957193Smuller int
106057193Smuller ar_next()
106157193Smuller #endif
106257193Smuller {
106357193Smuller 	char buf[PAXPATHLEN+2];
106457193Smuller 	static int freeit = 0;
106557193Smuller 	sigset_t o_mask;
106657193Smuller 
106757193Smuller 	/*
106857535Smuller 	 * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so
106957193Smuller 	 * things like writing EOF etc will be done) (Watch out ar_close() can
107057535Smuller 	 * also be called via a signal handler, so we must prevent a race.
107157193Smuller 	 */
107257193Smuller 	if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0)
107357535Smuller 		syswarn(0, errno, "Unable to set signal mask");
107457193Smuller 	ar_close();
107557193Smuller 	if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0)
107657535Smuller 		syswarn(0, errno, "Unable to restore signal mask");
107757193Smuller 
1078*57578Smuller 	if (done || !wr_trail)
107957193Smuller 		return(-1);
108057193Smuller 
108157193Smuller 	tty_prnt("\nATTENTION! Pax archive volume change required.\n");
108257193Smuller 
108357193Smuller 	/*
108457193Smuller 	 * if i/o is on stdin or stdout, we cannot reopen it (we do not know
108557535Smuller 	 * the name), the user will be forced to type it in.
108657193Smuller 	 */
108757193Smuller 	if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG)
108857193Smuller 	    && (artyp != ISPIPE)) {
108957193Smuller 		if (artyp == ISTAPE) {
109057193Smuller 			tty_prnt("%s ready for archive tape volume: %d\n",
109157193Smuller 				arcname, arvol);
109257193Smuller 			tty_prnt("Load the NEXT TAPE on the tape drive");
109357193Smuller 		} else {
109457193Smuller 			tty_prnt("%s ready for archive volume: %d\n",
109557193Smuller 				arcname, arvol);
109657193Smuller 			tty_prnt("Load the NEXT STORAGE MEDIA (if required)");
109757193Smuller 		}
109857193Smuller 
109957193Smuller 		if ((act == ARCHIVE) || (act == APPND))
110057193Smuller 			tty_prnt(" and make sure it is WRITE ENABLED.\n");
110157193Smuller 		else
110257193Smuller 			tty_prnt("\n");
110357193Smuller 
110457193Smuller 		for(;;) {
110557193Smuller 			tty_prnt("Type \"y\" to continue, \".\" to quit pax,");
110657193Smuller 			tty_prnt(" or \"s\" to switch to new device.\nIf you");
110757193Smuller 			tty_prnt(" cannot change storage media, type \"s\"\n");
110857193Smuller 			tty_prnt("Is the device ready and online? > ");
110957193Smuller 
111057193Smuller 			if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){
111157193Smuller 				done = 1;
111257193Smuller 				lstrval = -1;
111357193Smuller 				tty_prnt("Quitting pax!\n");
111457193Smuller 				vfpart = 0;
111557193Smuller 				return(-1);
111657193Smuller 			}
111757193Smuller 
111857193Smuller 			if ((buf[0] == '\0') || (buf[1] != '\0')) {
111957193Smuller 				tty_prnt("%s unknown command, try again\n",buf);
112057193Smuller 				continue;
112157193Smuller 			}
112257193Smuller 
112357193Smuller 			switch (buf[0]) {
112457193Smuller 			case 'y':
112557193Smuller 			case 'Y':
112657193Smuller 				/*
112757193Smuller 				 * we are to continue with the same device
112857193Smuller 				 */
112957193Smuller 				if (ar_open(arcname) >= 0)
113057193Smuller 					return(0);
113157193Smuller 				tty_prnt("Cannot re-open %s, try again\n",
113257193Smuller 					arcname);
113357193Smuller 				continue;
113457193Smuller 			case 's':
113557193Smuller 			case 'S':
113657193Smuller 				/*
113757193Smuller 				 * user wants to open a different device
113857193Smuller 				 */
113957193Smuller 				tty_prnt("Switching to a different archive\n");
114057193Smuller 				break;
114157193Smuller 			default:
114257193Smuller 				tty_prnt("%s unknown command, try again\n",buf);
114357193Smuller 				continue;
114457193Smuller 			}
114557193Smuller 			break;
114657193Smuller 		}
114757193Smuller 	} else
114857193Smuller 		tty_prnt("Ready for archive volume: %d\n", arvol);
114957193Smuller 
115057193Smuller 	/*
115157193Smuller 	 * have to go to a different archive
115257193Smuller 	 */
115357193Smuller 	for (;;) {
115457193Smuller 		tty_prnt("Input archive name or \".\" to quit pax.\n");
115557193Smuller 		tty_prnt("Archive name > ");
115657193Smuller 
115757193Smuller 		if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) {
115857193Smuller 			done = 1;
115957193Smuller 			lstrval = -1;
116057193Smuller 			tty_prnt("Quitting pax!\n");
116157193Smuller 			vfpart = 0;
116257193Smuller 			return(-1);
116357193Smuller 		}
116457193Smuller 		if (buf[0] == '\0') {
116557193Smuller 			tty_prnt("Empty file name, try again\n");
116657193Smuller 			continue;
116757193Smuller 		}
116857193Smuller                 if (!strcmp(buf, "..")) {
116957193Smuller                         tty_prnt("Illegal file name: .. try again\n");
117057193Smuller                         continue;
117157193Smuller                 }
117257193Smuller 		if (strlen(buf) > PAXPATHLEN) {
117357193Smuller 			tty_prnt("File name too long, try again\n");
117457193Smuller 			continue;
117557193Smuller 		}
117657193Smuller 
117757193Smuller 		/*
117857193Smuller 		 * try to open new archive
117957193Smuller 		 */
118057193Smuller 		if (ar_open(buf) >= 0) {
118157193Smuller 			if (freeit) {
118257193Smuller 				(void)free(arcname);
118357193Smuller 				freeit = 0;
118457193Smuller 			}
118557193Smuller 			if ((arcname = strdup(buf)) == NULL) {
118657193Smuller 				done = 1;
118757193Smuller 				lstrval = -1;
118857535Smuller 				warn(0, "Cannot save archive name.");
118957193Smuller 				return(-1);
119057193Smuller 			}
119157193Smuller 			freeit = 1;
119257193Smuller 			break;
119357193Smuller 		}
119457193Smuller 		tty_prnt("Cannot open %s, try again\n", buf);
119557193Smuller 		continue;
119657193Smuller 	}
119757193Smuller 	return(0);
119857193Smuller }
1199