xref: /csrg-svn/bin/pax/ar_io.c (revision 57584)
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*57584Smuller static char sccsid[] = "@(#)ar_io.c	1.4 (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 */
44*57584Smuller 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 */
5257193Smuller static int phyblk; 			/* size of physical block on TAPE */
5357578Smuller static int wr_trail = 1;		/* trailer was rewritten in append */
54*57584Smuller static int can_unlnk = 0;		/* do we unlink null archives?  */
5557193Smuller char *arcname;                  	/* printable name of archive */
5657193Smuller 
5757193Smuller static int get_phys __P((void));
5857193Smuller extern sigset_t s_mask;
5957193Smuller 
6057193Smuller /*
6157193Smuller  * ar_open()
6257193Smuller  *	Opens the next archive volume. Determines the type of the device and
6357193Smuller  *	sets up block sizes as required by the archive device and the format.
6457193Smuller  *	Note: we may be called with name == NULL on the first open only.
6557193Smuller  * Return:
6657193Smuller  *	-1 on failure, 0 otherwise
6757193Smuller  */
6857193Smuller 
6957193Smuller #if __STDC__
7057193Smuller int
7157193Smuller ar_open(char *name)
7257193Smuller #else
7357193Smuller int
7457193Smuller ar_open(name)
7557193Smuller 	char *name;
7657193Smuller #endif
7757193Smuller {
7857193Smuller         struct mtget mb;
7957193Smuller 
8057193Smuller 	if (arfd != -1)
8157193Smuller 		(void)close(arfd);
8257193Smuller 	arfd = -1;
83*57584Smuller 	can_unlnk = phyblk = did_io = io_ok = invld_rec = 0;
84*57584Smuller 	artyp = ISREG;
8557193Smuller 	flcnt = 0;
8657193Smuller 
8757193Smuller 	/*
8857193Smuller 	 * open based on overall operation mode
8957193Smuller 	 */
9057193Smuller 	switch (act) {
9157193Smuller 	case LIST:
9257193Smuller 	case EXTRACT:
9357193Smuller 		if (name == NULL) {
9457193Smuller 			arfd = STDIN_FILENO;
9557193Smuller 			arcname = STDN;
9657193Smuller 		} else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
9757535Smuller 			syswarn(0, errno, "Failed open to read on %s", name);
9857193Smuller 		break;
9957193Smuller 	case ARCHIVE:
10057193Smuller 		if (name == NULL) {
10157193Smuller 			arfd = STDOUT_FILENO;
10257193Smuller 			arcname = STDO;
10357193Smuller 		} else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
10457535Smuller 			syswarn(0, errno, "Failed open to write on %s", name);
105*57584Smuller 		else
106*57584Smuller 			can_unlnk = 1;
10757193Smuller 		break;
10857193Smuller 	case APPND:
10957193Smuller 		if (name == NULL) {
11057193Smuller 			arfd = STDOUT_FILENO;
11157193Smuller 			arcname = STDO;
11257193Smuller 		} else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
11357535Smuller 			syswarn(0, errno, "Failed open to read/write on %s",
11457193Smuller 				name);
11557193Smuller 		break;
11657193Smuller 	case COPY:
11757193Smuller 		/*
11857193Smuller 		 * arfd not used in COPY mode
11957193Smuller 		 */
12057193Smuller 		arcname = "<NONE>";
12157193Smuller 		lstrval = 1;
12257193Smuller 		return(0);
12357193Smuller 	}
12457193Smuller 	if (arfd < 0)
12557193Smuller 		return(-1);
12657193Smuller 
12757193Smuller 	/*
12857193Smuller 	 * set up is based on device type
12957193Smuller 	 */
13057193Smuller 	if (fstat(arfd, &arsb) < 0) {
13157535Smuller 		syswarn(0, errno, "Failed stat on %s", arcname);
132*57584Smuller 		(void)close(arfd);
133*57584Smuller 		arfd = -1;
134*57584Smuller 		can_unlnk = 0;
13557193Smuller 		return(-1);
13657193Smuller 	}
13757193Smuller 	if (S_ISDIR(arsb.st_mode)) {
13857535Smuller 		warn(0, "Cannot write an archive on top of a directory %s",
13957193Smuller 		    arcname);
140*57584Smuller 		(void)close(arfd);
141*57584Smuller 		arfd = -1;
142*57584Smuller 		can_unlnk = 0;
14357193Smuller 		return(-1);
14457193Smuller 	}
145*57584Smuller 
14657193Smuller 	if (S_ISCHR(arsb.st_mode))
14757193Smuller 		artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
14857193Smuller 	else if (S_ISBLK(arsb.st_mode))
14957193Smuller 		artyp = ISBLK;
15057193Smuller 	else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
15157193Smuller 		artyp = ISPIPE;
15257193Smuller 	else
15357193Smuller 		artyp = ISREG;
15457193Smuller 
15557193Smuller 	/*
156*57584Smuller 	 * make sure we beyond any doubt that we only can unlink regular files
157*57584Smuller 	 * we created
158*57584Smuller 	 */
159*57584Smuller 	if (artyp != ISREG)
160*57584Smuller 		can_unlnk = 0;
161*57584Smuller 	/*
16257535Smuller 	 * if we are writing, we are done
16357193Smuller 	 */
16457193Smuller 	if (act == ARCHIVE) {
16557193Smuller 		blksz = rdblksz = wrblksz;
16657193Smuller 		lstrval = 1;
16757193Smuller 		return(0);
16857193Smuller 	}
16957193Smuller 
17057193Smuller 	/*
17157193Smuller 	 * set default blksz on read. APPNDs writes rdblksz on the last volume
17257193Smuller 	 * On all new archive volumes, we shift to wrblksz (if the user
17357193Smuller 	 * specified one, otherwize we will continue to use rdblksz). We
17457193Smuller 	 * must to set blocksize based on what kind of device the archive is
17557193Smuller 	 * stored.
17657193Smuller 	 */
17757193Smuller 	switch(artyp) {
17857193Smuller 	case ISTAPE:
17957193Smuller 		/*
18057193Smuller 		 * Tape drives come in at least two flavors. Those that support
18157193Smuller 		 * variable sized records and those that have fixed sized
18257193Smuller 		 * records. They must be treated differently. For tape drives
18357193Smuller 		 * that support variable sized records, we must make large
18457193Smuller 		 * reads to make sure we get the entire record, otherwise we
18557193Smuller 		 * will just get the first part of the record (up to size we
18657193Smuller 		 * asked). Tapes with fixed sized records may or may not return
18757193Smuller 		 * multiple records in a single read. We really do not care
18857193Smuller 		 * what the physical record size is UNLESS we are going to
18957193Smuller 		 * append. (We will need the physical block size to rewrite
19057193Smuller 		 * the trailer). Only when we are appending do we go to the
19157535Smuller 		 * effort to figure out the true PHYSICAL record size.
19257193Smuller 		 */
19357193Smuller 		blksz = rdblksz = MAXBLK;
19457193Smuller 		break;
19557193Smuller 	case ISPIPE:
19657193Smuller 	case ISBLK:
19757193Smuller 	case ISCHR:
19857193Smuller 		/*
19957193Smuller 		 * Blocksize is not a major issue with these devices (but must
20057193Smuller 		 * be kept a multiple of 512). If the user specified a write
20157193Smuller 		 * block size, we use that to read. Under append, we must
20257193Smuller 		 * always keep blksz == rdblksz. Otherwise we go ahead and use
20357193Smuller 		 * the device optimal blocksize as (and if) returned by stat
20457193Smuller 		 * and if it is within pax specs.
20557193Smuller 		 */
20657193Smuller 		if ((act == APPND) && wrblksz) {
20757193Smuller 			blksz = rdblksz = wrblksz;
20857193Smuller 			break;
20957193Smuller 		}
21057193Smuller 
21157193Smuller 		if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) &&
21257193Smuller 		    ((arsb.st_blksize % BLKMULT) == 0))
21357193Smuller 			rdblksz = arsb.st_blksize;
21457193Smuller 		else
21557193Smuller 			rdblksz = DEVBLK;
21657193Smuller 		/*
21757193Smuller 		 * For performance go for large reads when we can without harm
21857193Smuller 		 */
21957193Smuller 		if ((act == APPND) || (artyp == ISCHR))
22057193Smuller 			blksz = rdblksz;
22157193Smuller 		else
22257193Smuller 			blksz = MAXBLK;
22357193Smuller 		break;
22457193Smuller 	case ISREG:
22557193Smuller 		/*
22657193Smuller 		 * if the user specified wrblksz works, use it. Under appends
22757193Smuller 		 * we must always keep blksz == rdblksz
22857193Smuller 		 */
22957193Smuller 		if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){
23057193Smuller 			blksz = rdblksz = wrblksz;
23157193Smuller 			break;
23257193Smuller 		}
23357193Smuller 		/*
23457193Smuller 		 * See if we can find the blocking factor from the file size
23557193Smuller 		 */
23657193Smuller 		for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT)
23757193Smuller 			if ((arsb.st_size % rdblksz) == 0)
23857193Smuller 				break;
23957193Smuller 		/*
24057193Smuller 		 * When we cannont find a match, we may have a flawed archive.
24157193Smuller 		 */
24257193Smuller 		if (rdblksz <= 0)
24357193Smuller 			rdblksz = FILEBLK;
24457193Smuller 		/*
24557193Smuller 		 * for performance go for large reads when we can
24657193Smuller 		 */
24757193Smuller 		if (act == APPND)
24857193Smuller 			blksz = rdblksz;
24957193Smuller 		else
25057193Smuller 			blksz = MAXBLK;
25157193Smuller 		break;
25257193Smuller 	default:
25357193Smuller 		/*
25457193Smuller 		 * should never happen, worse case, slow...
25557193Smuller 		 */
25657193Smuller 		blksz = rdblksz = BLKMULT;
25757193Smuller 		break;
25857193Smuller 	}
25957193Smuller 	lstrval = 1;
26057193Smuller 	return(0);
26157193Smuller }
26257193Smuller 
26357193Smuller /*
26457193Smuller  * ar_close()
26557193Smuller  *	closes archive device, increments volume number, and prints i/o summary
26657193Smuller  */
26757193Smuller #if __STDC__
26857193Smuller void
26957193Smuller ar_close(void)
27057193Smuller #else
27157193Smuller void
27257193Smuller ar_close()
27357193Smuller #endif
27457193Smuller {
27557193Smuller 	FILE *outf;
27657193Smuller 
27757578Smuller 	if (arfd < 0) {
27857578Smuller 		did_io = io_ok = flcnt = 0;
27957578Smuller 		return;
28057578Smuller 	}
28157578Smuller 
28257535Smuller 	if (act == LIST)
28357535Smuller 		outf = stdout;
28457535Smuller 	else
28557535Smuller 		outf = stderr;
28657535Smuller 
28757535Smuller 	/*
28857535Smuller 	 * Close archive file. This may take a LONG while on tapes (we may be
28957535Smuller 	 * forced to wait for the rewind to complete) so tell the user what is
29057535Smuller 	 * going on (this avoids the user hitting control-c thinking pax is
29157535Smuller 	 * broken).
29257535Smuller 	 */
29357578Smuller 	if (vflag && (artyp == ISTAPE)) {
29457578Smuller 		if (vfpart)
29557535Smuller 			(void)putc('\n', outf);
29657535Smuller 		(void)fputs("pax: Waiting for tape drive close to complete...",
29757535Smuller 		    outf);
29857535Smuller 		(void)fflush(outf);
29957535Smuller 	}
30057535Smuller 
301*57584Smuller 	/*
302*57584Smuller 	 * if nothing was written to the archive (and we created it), we remove
303*57584Smuller 	 * it
304*57584Smuller 	 */
305*57584Smuller 	if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) &&
306*57584Smuller 	    (arsb.st_size == 0)) {
307*57584Smuller 		(void)unlink(arcname);
308*57584Smuller 		can_unlnk = 0;
309*57584Smuller 	}
310*57584Smuller 
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
35357535Smuller 		(void)fprintf(outf, "pax: unknown format, %lu bytes skipped.\n",
35457535Smuller #	else
35557535Smuller 		(void)fprintf(outf, "pax: unknown format, %qu bytes skipped.\n",
35657535Smuller #	endif
35757535Smuller 		    rdcnt);
35857535Smuller 		(void)fflush(outf);
35957535Smuller 		flcnt = 0;
36057535Smuller 		return;
36157535Smuller 	}
36257535Smuller 
36357193Smuller 	(void)fprintf(outf,
36457193Smuller #	ifdef NET2_STAT
36557535Smuller 	    "pax: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
36657193Smuller #	else
36757535Smuller 	    "pax: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
36857193Smuller #	endif
36957193Smuller 	    frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
37057193Smuller 	(void)fflush(outf);
37157193Smuller 	flcnt = 0;
37257193Smuller }
37357193Smuller 
37457193Smuller /*
37557193Smuller  * ar_set_wr()
37657578Smuller  *	Set up device right before switching from read to write in an append.
37757578Smuller  *	device dependent code (if required) to do this should be added here.
37857578Smuller  *	For all archive devices we are already positioned at the place we want
37957578Smuller  *	to start writing when this routine is called.
38057193Smuller  * Return:
38157193Smuller  *	0 if all ready to write, -1 otherwise
38257193Smuller  */
38357193Smuller 
38457193Smuller #if __STDC__
38557193Smuller int
38657193Smuller ar_set_wr(void)
38757193Smuller #else
38857193Smuller int
38957193Smuller ar_set_wr()
39057193Smuller #endif
39157193Smuller {
39257193Smuller 	off_t cpos;
39357193Smuller 
39457578Smuller 	/*
39557578Smuller 	 * we must make sure the trailer is rewritten on append, ar_next()
39657578Smuller 	 * will stop us if the archive containing the trailer was not written
39757578Smuller 	 */
39857578Smuller 	wr_trail = 0;
39957578Smuller 
40057193Smuller 	/*
40157193Smuller 	 * Add any device dependent code as required here
40257193Smuller 	 */
40357193Smuller 	if (artyp != ISREG)
40457193Smuller 		return(0);
40557193Smuller 	/*
40657535Smuller 	 * Ok we have an archive in a regular file. If we were rewriting a
40757535Smuller 	 * file, we must get rid of all the stuff after the current offset
40857535Smuller 	 * (it was not written by pax).
40957193Smuller 	 */
41057193Smuller 	if (((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) ||
41157578Smuller 	    (ftruncate(arfd, cpos) < 0)) {
41257578Smuller 		syswarn(1, errno, "Unable to truncate archive file");
41357193Smuller 		return(-1);
41457578Smuller 	}
41557193Smuller 	return(0);
41657193Smuller }
41757193Smuller 
41857193Smuller /*
41957193Smuller  * ar_app_ok()
42057193Smuller  *	check if the last volume in the archive allows appends. We cannot check
42157193Smuller  *	this until we are ready to write since there is no spec that says all
42257193Smuller  *	volumes in a single archive have to be of the same type...
42357193Smuller  * Return:
42457193Smuller  *	0 if we can append, -1 otherwise.
42557193Smuller  */
42657193Smuller 
42757193Smuller #if __STDC__
42857193Smuller int
42957193Smuller ar_app_ok(void)
43057193Smuller #else
43157193Smuller int
43257193Smuller ar_app_ok()
43357193Smuller #endif
43457193Smuller {
43557193Smuller 	if (artyp == ISPIPE) {
43657193Smuller 		warn(1, "Cannot append to an archive obtained from a pipe.");
43757193Smuller 		return(-1);
43857193Smuller 	}
43957193Smuller 
44057193Smuller 	if (!invld_rec)
44157193Smuller 		return(0);
44257193Smuller 	warn(1,"Cannot append, device record size %d does not support pax spec",
44357193Smuller 		rdblksz);
44457193Smuller 	return(-1);
44557193Smuller }
44657193Smuller 
44757193Smuller /*
44857193Smuller  * ar_read()
44957193Smuller  *	read up to a specified number of bytes from the archive into the
45057193Smuller  *	supplied buffer. When dealing with tapes we may not always be able to
45157193Smuller  *	read what we want.
45257193Smuller  * Return:
45357193Smuller  *	Number of bytes in buffer. 0 for end of file, -1 for a read error.
45457193Smuller  */
45557193Smuller 
45657193Smuller #if __STDC__
45757193Smuller int
45857193Smuller ar_read(register char *buf, register int cnt)
45957193Smuller #else
46057193Smuller int
46157193Smuller ar_read(buf, cnt)
46257193Smuller 	register char *buf;
46357193Smuller 	register int cnt;
46457193Smuller #endif
46557193Smuller {
46657193Smuller 	register int res = 0;
46757193Smuller 
46857193Smuller 	/*
46957193Smuller 	 * if last i/o was in error, no more reads until reset or new volume
47057193Smuller 	 */
47157193Smuller 	if (lstrval <= 0)
47257193Smuller 		return(lstrval);
47357193Smuller 
47457193Smuller 	/*
47557193Smuller 	 * how we read must be based on device type
47657193Smuller 	 */
47757193Smuller 	switch (artyp) {
47857193Smuller 	case ISTAPE:
47957193Smuller 		if ((res = read(arfd, buf, cnt)) > 0) {
48057193Smuller 			/*
48157193Smuller 			 * CAUTION: tape systems may not always return the same
48257193Smuller 			 * sized records so we leave blksz == MAXBLK. The
48357193Smuller 			 * physical record size that a tape drive supports is
48457193Smuller 			 * very hard to determine in a uniform and portable
48557193Smuller 			 * manner.
48657193Smuller 			 */
48757193Smuller 			io_ok = 1;
48857193Smuller 			if (res != rdblksz) {
48957193Smuller 				/*
49057193Smuller 				 * Record size changed. If this is happens on
49157535Smuller 				 * any record after the first, we probably have
49257535Smuller 				 * a tape drive which has a fixed record size
49357535Smuller 				 * we are getting multiple records in a single
49457535Smuller 				 * read). Watch out for record blocking that
49557535Smuller 				 * violates pax spec (must be a multiple of
49657535Smuller 				 * BLKMULT).
49757193Smuller 				 */
49857193Smuller 				rdblksz = res;
49957193Smuller 				if (rdblksz % BLKMULT)
50057193Smuller 					invld_rec = 1;
50157193Smuller 			}
50257193Smuller 			return(res);
50357193Smuller 		}
50457193Smuller 		break;
50557193Smuller 	case ISREG:
50657193Smuller 	case ISBLK:
50757193Smuller 	case ISCHR:
50857193Smuller 	case ISPIPE:
50957193Smuller 	default:
51057193Smuller 		/*
51157193Smuller 		 * Files are so easy to deal with. These other things cannot
51257193Smuller 		 * be trusted at all. So when we are dealing with character
51357193Smuller 		 * devices and pipes we just take what they have ready for us
51457193Smuller 		 * and return. Trying to do anything else with them runs the
51557193Smuller 		 * risk of failure.
51657193Smuller 		 */
51757193Smuller 		if ((res = read(arfd, buf, cnt)) > 0) {
51857193Smuller 			io_ok = 1;
51957193Smuller 			return(res);
52057193Smuller 		}
52157193Smuller 		break;
52257193Smuller 	}
52357193Smuller 
52457193Smuller 	/*
52557193Smuller 	 * We are in trouble at this point, something is broken...
52657193Smuller 	 */
52757193Smuller 	lstrval = res;
52857193Smuller 	if (res < 0)
52957193Smuller 		syswarn(1, errno, "Failed read on archive volume %d", arvol);
53057193Smuller 	else
53157193Smuller 		warn(0, "End of archive volume %d reached", arvol);
53257193Smuller 	return(res);
53357193Smuller }
53457193Smuller 
53557193Smuller /*
53657193Smuller  * ar_write()
53757193Smuller  *	Write a specified number of bytes in supplied buffer to the archive
53857193Smuller  *	device so it appears as a single "block". Deals with errors and tries
53957193Smuller  *	to recover when faced with short writes.
54057193Smuller  * Return:
54157193Smuller  *	Number of bytes written. 0 indicates end of volume reached and with no
54257193Smuller  *	flaws (as best that can be detected). A -1 indicates an unrecoverable
54357193Smuller  *	error in the archive occured.
54457193Smuller  */
54557193Smuller 
54657193Smuller #if __STDC__
54757193Smuller int
54857193Smuller ar_write(register char *buf, register int bsz)
54957193Smuller #else
55057193Smuller int
55157193Smuller ar_write(buf, bsz)
55257193Smuller 	register char *buf;
55357193Smuller 	register int bsz;
55457193Smuller #endif
55557193Smuller {
55657193Smuller 	register int res;
55757193Smuller 	off_t cpos;
55857193Smuller 
55957193Smuller 	/*
56057193Smuller 	 * do not allow pax to create a "bad" archive. Once a write fails on
56157193Smuller 	 * an archive volume prevent further writes to it.
56257193Smuller 	 */
56357193Smuller 	if (lstrval <= 0)
56457193Smuller 		return(lstrval);
56557193Smuller 
56657193Smuller 	if ((res = write(arfd, buf, bsz)) == bsz) {
56757578Smuller 		wr_trail = 1;
56857193Smuller 		io_ok = 1;
56957193Smuller 		return(bsz);
57057193Smuller 	}
57157193Smuller 	/*
57257193Smuller 	 * write broke, see what we can do with it. We try to send any partial
57357535Smuller 	 * writes that may violate pax spec to the next archive volume.
57457193Smuller 	 */
57557193Smuller 	if (res < 0)
57657193Smuller 		lstrval = res;
57757193Smuller 	else
57857193Smuller 		lstrval = 0;
57957193Smuller 
58057193Smuller 	switch (artyp) {
58157193Smuller 	case ISREG:
58257193Smuller 		if ((res > 0) && (res % BLKMULT)) {
58357193Smuller 			/*
58457193Smuller 		 	 * try to fix up partial writes which are not BLKMULT
58557193Smuller 			 * in size by forcing the runt record to next archive
58657193Smuller 			 * volume
58757193Smuller 		 	 */
58857193Smuller 			if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
58957193Smuller 				break;
59057193Smuller 			cpos -= (off_t)res;
59157193Smuller 			if (ftruncate(arfd, cpos) < 0)
59257193Smuller 				break;
59357193Smuller 			res = lstrval = 0;
59457193Smuller 			break;
59557193Smuller 		}
59657193Smuller 		if (res >= 0)
59757193Smuller 			break;
59857193Smuller 		/*
59957193Smuller 		 * if file is out of space, handle it like a return of 0
60057193Smuller 		 */
60157193Smuller 		if ((errno == ENOSPC) || (errno == EFBIG) || (errno == EDQUOT))
60257193Smuller 			res = lstrval = 0;
60357193Smuller 		break;
60457193Smuller 	case ISTAPE:
60557193Smuller 	case ISCHR:
60657193Smuller 	case ISBLK:
60757193Smuller 		if (res >= 0)
60857193Smuller 			break;
60957193Smuller 		if (errno == EACCES) {
61057193Smuller 			warn(0, "Write failed, archive is write protected.");
61157193Smuller 			res = lstrval = 0;
61257193Smuller 			return(0);
61357193Smuller 		}
61457193Smuller 		/*
61557193Smuller 		 * see if we reached the end of media, if so force a change to
61657193Smuller 		 * the next volume
61757193Smuller 		 */
61857193Smuller 		if ((errno == ENOSPC) || (errno == EIO) || (errno == ENXIO))
61957193Smuller 			res = lstrval = 0;
62057193Smuller 		break;
62157193Smuller 	case ISPIPE:
62257193Smuller 	default:
62357193Smuller 		/*
62457193Smuller 		 * we cannot fix errors to these devices
62557193Smuller 		 */
62657193Smuller 		break;
62757193Smuller 	}
62857193Smuller 
62957193Smuller 	/*
63057193Smuller 	 * Better tell the user the bad news...
63157535Smuller 	 * if this is a block aligned archive format, we may have a bad archive
63257535Smuller 	 * if the format wants the header to start at a BLKMULT boundry. While
63357193Smuller 	 * we can deal with the mis-aligned data, it violates spec and other
63457193Smuller 	 * archive readers will likely fail. if the format is not block
63557535Smuller 	 * aligned, the user may be lucky (and the archive is ok).
63657193Smuller 	 */
63757578Smuller 	if (res >= 0) {
63857578Smuller 		if (res > 0)
63957578Smuller 			wr_trail = 1;
64057193Smuller 		io_ok = 1;
64157578Smuller 	}
64257578Smuller 
64357578Smuller 	/*
64457578Smuller 	 * If we were trying to rewrite the trailer and it didn't work, we
64557578Smuller 	 * must quit right away.
64657578Smuller 	 */
64757578Smuller 	if (!wr_trail && (res <= 0)) {
64857578Smuller 		warn(1,"Unable to append, trailer re-write failed. Quitting.");
64957578Smuller 		return(res);
65057578Smuller 	}
65157578Smuller 
65257578Smuller 	if (res == 0)
65357193Smuller 		warn(0, "End of archive volume %d reached", arvol);
65457193Smuller 	else if (res < 0)
65557193Smuller 		syswarn(1, errno, "Failed write to archive volume: %d", arvol);
65657193Smuller 	else if (!frmt->blkalgn || ((res % frmt->blkalgn) == 0))
65757193Smuller 		warn(0,"WARNING: partial archive write. Archive MAY BE FLAWED");
65857193Smuller 	else
65957193Smuller 		warn(1,"WARNING: partial archive write. Archive IS FLAWED");
66057193Smuller 	return(res);
66157193Smuller }
66257193Smuller 
66357193Smuller /*
66457193Smuller  * ar_rdsync()
66557193Smuller  *	Try to move past a bad spot on a flawed archive as needed to continue
66657193Smuller  *	I/O. Clears error flags to allow I/O to continue.
66757193Smuller  * Return:
66857193Smuller  *	0 when ok to try i/o again, -1 otherwise.
66957193Smuller  */
67057193Smuller 
67157193Smuller #if __STDC__
67257193Smuller int
67357193Smuller ar_rdsync(void)
67457193Smuller #else
67557193Smuller int
67657193Smuller ar_rdsync()
67757193Smuller #endif
67857193Smuller {
67957193Smuller 	long fsbz;
68057193Smuller 	off_t cpos;
68157193Smuller 	off_t mpos;
68257193Smuller         struct mtop mb;
68357193Smuller 
68457193Smuller 	/*
68557193Smuller 	 * Fail resync attempts at user request (done) or this is going to be
68657193Smuller 	 * an update/append to a existing archive. if last i/o hit media end,
68757193Smuller 	 * we need to go to the next volume not try a resync
68857193Smuller 	 */
68957193Smuller 	if ((done > 0) || (lstrval == 0))
69057193Smuller 		return(-1);
69157193Smuller 
69257193Smuller 	if ((act == APPND) || (act == ARCHIVE)) {
69357193Smuller 		warn(1, "Cannot allow updates to an archive with flaws.");
69457193Smuller 		return(-1);
69557193Smuller 	}
69657193Smuller 	if (io_ok)
69757193Smuller 		did_io = 1;
69857193Smuller 
69957193Smuller 	switch(artyp) {
70057193Smuller 	case ISTAPE:
70157193Smuller 		/*
70257193Smuller 		 * if the last i/o was a successful data transfer, we assume
70357193Smuller 		 * the fault is just a bad record on the tape that we are now
70457193Smuller 		 * past. If we did not get any data since the last resync try
70557193Smuller 		 * to move the tape foward one PHYSICAL record past any
70657193Smuller 		 * damaged tape section. Some tape drives are stubborn and need
70757193Smuller 		 * to be pushed.
70857193Smuller 		 */
70957193Smuller 		if (io_ok) {
71057193Smuller 			io_ok = 0;
71157193Smuller 			lstrval = 1;
71257193Smuller 			break;
71357193Smuller 		}
71457193Smuller 		mb.mt_op = MTFSR;
71557193Smuller 		mb.mt_count = 1;
71657193Smuller 		if (ioctl(arfd, MTIOCTOP, &mb) < 0)
71757193Smuller 			break;
71857193Smuller 		lstrval = 1;
71957193Smuller 		break;
72057193Smuller 	case ISREG:
72157193Smuller 	case ISCHR:
72257193Smuller 	case ISBLK:
72357193Smuller 		/*
72457193Smuller 		 * try to step over the bad part of the device.
72557193Smuller 		 */
72657193Smuller 		io_ok = 0;
72757193Smuller 		if (((fsbz = arsb.st_blksize) <= 0) || (artyp != ISREG))
72857193Smuller 			fsbz = BLKMULT;
72957193Smuller 		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
73057193Smuller 			break;
73157193Smuller 		mpos = fsbz - (cpos % (off_t)fsbz);
73257193Smuller 		if (lseek(arfd, mpos, SEEK_CUR) < 0)
73357193Smuller 			break;
73457193Smuller 		lstrval = 1;
73557193Smuller 		break;
73657193Smuller 	case ISPIPE:
73757193Smuller 	default:
73857193Smuller 		/*
73957193Smuller 		 * cannot recover on these archive device types
74057193Smuller 		 */
74157193Smuller 		io_ok = 0;
74257193Smuller 		break;
74357193Smuller 	}
74457193Smuller 	if (lstrval <= 0) {
74557535Smuller 		warn(1, "Unable to recover from an archive read failure.");
74657193Smuller 		return(-1);
74757193Smuller 	}
74857193Smuller 	warn(0, "Attempting to recover from an archive read failure.");
74957193Smuller 	return(0);
75057193Smuller }
75157193Smuller 
75257193Smuller /*
75357193Smuller  * ar_fow()
75457193Smuller  *	Move the I/O position within the archive foward the specified number of
75557193Smuller  *	bytes as supported by the device. If we cannot move the requested
75657193Smuller  *	number of bytes, return the actual number of bytes moved in skipped.
75757193Smuller  * Return:
75857193Smuller  *	0 if moved the requested distance, -1 on complete failure, 1 on
75957193Smuller  *	partial move (the amount moved is in skipped)
76057193Smuller  */
76157193Smuller 
76257193Smuller #if __STDC__
76357193Smuller int
76457193Smuller ar_fow(off_t sksz, off_t *skipped)
76557193Smuller #else
76657193Smuller int
76757193Smuller ar_fow(sksz, skipped)
76857193Smuller 	off_t sksz;
76957193Smuller 	off_t *skipped;
77057193Smuller #endif
77157193Smuller {
77257193Smuller 	off_t cpos;
77357193Smuller 	off_t mpos;
77457193Smuller 
77557193Smuller 	*skipped = 0;
77657193Smuller 	if (sksz <= 0)
77757193Smuller 		return(0);
77857193Smuller 
77957193Smuller 	/*
78057193Smuller 	 * we cannot move foward at EOF or error
78157193Smuller 	 */
78257193Smuller 	if (lstrval <= 0)
78357193Smuller 		return(lstrval);
78457193Smuller 
78557193Smuller 	/*
78657193Smuller 	 * Safer to read forward on devices where it is hard to find the end of
78757193Smuller 	 * the media without reading to it. With tapes we cannot be sure of the
78857193Smuller 	 * number of physical blocks to skip (we do not know physical block
78957193Smuller 	 * size at this point), so we must only read foward on tapes!
79057193Smuller 	 */
79157193Smuller 	if (artyp != ISREG)
79257193Smuller 		return(0);
79357193Smuller 
79457193Smuller 	/*
79557193Smuller 	 * figure out where we are in the archive
79657193Smuller 	 */
79757193Smuller 	if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
79857193Smuller 		/*
79957193Smuller 	 	 * we can be asked to move farther than there are bytes in this
80057193Smuller 		 * volume, if so, just go to file end and let normal buf_fill()
80157193Smuller 		 * deal with the end of file (it will go to next volume by
80257193Smuller 		 * itself)
80357193Smuller 	 	 */
80457193Smuller 		if ((mpos = cpos + sksz) > arsb.st_size) {
80557193Smuller 			*skipped = arsb.st_size - cpos;
80657193Smuller 			mpos = arsb.st_size;
80757193Smuller 		} else
80857193Smuller 			*skipped = sksz;
80957193Smuller 		if (lseek(arfd, mpos, SEEK_SET) >= 0)
81057193Smuller 			return(0);
81157193Smuller 	}
81257193Smuller 	syswarn(1, errno, "Foward positioning operation on archive failed");
81357193Smuller 	lstrval = -1;
81457193Smuller 	return(-1);
81557193Smuller }
81657193Smuller 
81757193Smuller /*
81857193Smuller  * ar_rev()
81957193Smuller  *	move the i/o position within the archive backwards the specified byte
82057193Smuller  *	count as supported by the device. With tapes drives we RESET rdblksz to
82157193Smuller  *	the PHYSICAL blocksize.
82257193Smuller  *	NOTE: We should only be called to move backwards so we can rewrite the
82357193Smuller  *	last records (the trailer) of an archive (APPEND).
82457193Smuller  * Return:
82557193Smuller  *	0 if moved the requested distance, -1 on complete failure
82657193Smuller  */
82757193Smuller 
82857193Smuller #if __STDC__
82957193Smuller int
83057193Smuller ar_rev(off_t sksz)
83157193Smuller #else
83257193Smuller int
83357193Smuller ar_rev(sksz)
83457193Smuller 	off_t sksz;
83557193Smuller #endif
83657193Smuller {
83757193Smuller 	off_t cpos;
83857193Smuller         struct mtop mb;
83957193Smuller 
84057193Smuller 	/*
84157578Smuller 	 * make sure we do not have try to reverse on a flawed archive
84257193Smuller 	 */
84357193Smuller 	if (lstrval < 0)
84457193Smuller 		return(lstrval);
84557193Smuller 
84657193Smuller 	switch(artyp) {
84757193Smuller 	case ISPIPE:
84857578Smuller 		if (sksz <= 0)
84957578Smuller 			break;
85057193Smuller 		/*
85157193Smuller 		 * cannot go backwards on these critters
85257193Smuller 		 */
85357578Smuller 		warn(1, "Reverse positioning on pipes is not supported.");
85457578Smuller 		lstrval = -1;
85557578Smuller 		return(-1);
85657193Smuller 	case ISREG:
85757193Smuller 	case ISBLK:
85857193Smuller 	case ISCHR:
85957193Smuller 	default:
86057578Smuller 		if (sksz <= 0)
86157578Smuller 			break;
86257578Smuller 
86357193Smuller 		/*
86457193Smuller 		 * For things other than files, backwards movement has a very
86557193Smuller 		 * high probability of failure as we really do not know the
86657193Smuller 		 * true attributes of the device we are talking to (the device
86757193Smuller 		 * may not even have the ability to lseek() in any direction).
86857578Smuller 		 * First we figure out where we are in the archive.
86957193Smuller 		 */
87057578Smuller 		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) {
87157578Smuller 			syswarn(1, errno,
87257578Smuller 			   "Unable to obtain current archive byte offset");
87357578Smuller 			lstrval = -1;
87457578Smuller 			return(-1);
87557578Smuller 		}
87657193Smuller 
87757193Smuller 		/*
87857193Smuller 		 * we may try to go backwards past the start when the archive
87957193Smuller 		 * is only a single record. If this hapens and we are on a
88057193Smuller 		 * multi volume archive, we need to go to the end of the
88157193Smuller 		 * previous volume and continue our movement backwards from
88257578Smuller 		 * there.
88357193Smuller 		 */
88457193Smuller 		if ((cpos -= sksz) < (off_t)0L) {
88557193Smuller 			if (arvol > 1) {
88657578Smuller 				/*
88757578Smuller 				 * this should never happen
88857578Smuller 				 */
88957578Smuller 				warn(1,"Reverse position on previous volume.");
89057193Smuller 				lstrval = -1;
89157193Smuller 				return(-1);
89257193Smuller 			}
89357193Smuller 			cpos = (off_t)0L;
89457193Smuller 		}
89557578Smuller 		if (lseek(arfd, cpos, SEEK_SET) < 0) {
89657578Smuller 			syswarn(1, errno, "Unable to seek archive backwards");
89757578Smuller 			lstrval = -1;
89857578Smuller 			return(-1);
89957578Smuller 		}
90057578Smuller 		break;
90157193Smuller 	case ISTAPE:
90257193Smuller 		/*
90357193Smuller 	 	 * Calculate and move the proper number of PHYSICAL tape
90457578Smuller 		 * blocks. If the sksz is not an even multiple of the physical
90557193Smuller 		 * tape size, we cannot do the move (this should never happen).
90657193Smuller 		 * (We also cannot handler trailers spread over two vols).
90757578Smuller 		 * get_phys() also makes sure we are in front of the filemark.
90857193Smuller 	 	 */
90957193Smuller 		if (get_phys() < 0) {
91057578Smuller 			lstrval = -1;
91157578Smuller 			return(-1);
91257193Smuller 		}
91357193Smuller 
91457578Smuller 		/*
91557578Smuller 		 * make sure future tape reads only go by physical tape block
91657578Smuller 		 * size (set rdblksz to the real size).
91757578Smuller 		 */
91857578Smuller 		rdblksz = phyblk;
91957578Smuller 
92057578Smuller 		/*
92157578Smuller 		 * if no movement is required, just return (we must be after
92257578Smuller 		 * get_phys() so the physical blocksize is properly set)
92357578Smuller 		 */
92457578Smuller 		if (sksz <= 0)
92557578Smuller 			break;
92657578Smuller 
92757578Smuller 		/*
92857578Smuller 		 * ok we have to move. Make sure the tape drive can do it.
92957578Smuller 		 */
93057193Smuller 		if (sksz % phyblk) {
93157578Smuller 			warn(1,
93257578Smuller 			    "Tape drive unable to backspace requested amount");
93357193Smuller 			lstrval = -1;
93457193Smuller 			return(-1);
93557193Smuller 		}
93657193Smuller 
93757578Smuller 		/*
93857578Smuller 		 * move backwards the requested number of bytes
93957578Smuller 		 */
94057193Smuller 		mb.mt_op = MTBSR;
94157193Smuller 		mb.mt_count = sksz/phyblk;
94257578Smuller 		if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
94357578Smuller 			syswarn(1,errno, "Unable to backspace tape %d blocks.",
94457578Smuller 			    mb.mt_count);
94557578Smuller 			lstrval = -1;
94657578Smuller 			return(-1);
94757578Smuller 		}
94857578Smuller 		break;
94957193Smuller 	}
95057578Smuller 	lstrval = 1;
95157578Smuller 	return(0);
95257193Smuller }
95357193Smuller 
95457193Smuller /*
95557193Smuller  * get_phys()
95657578Smuller  *	Determine the physical block size on a tape drive. We need the physical
95757578Smuller  *	block size so we know how many bytes we skip over when we move with
95857578Smuller  *	mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
95957578Smuller  *	return.
96057578Smuller  *	This is one really SLOW routine...
96157193Smuller  * Return:
96257193Smuller  *	0 if ok, -1 otherwise
96357193Smuller  */
96457193Smuller 
96557193Smuller #if __STDC__
96657193Smuller static int
96757193Smuller get_phys(void)
96857193Smuller #else
96957193Smuller static int
97057193Smuller get_phys()
97157193Smuller #endif
97257193Smuller {
97357578Smuller 	register int padsz = 0;
97457535Smuller 	register int res;
97557535Smuller 	struct mtop mb;
97657578Smuller 	char scbuf[MAXBLK];
97757193Smuller 
97857193Smuller 	/*
97957578Smuller 	 * move to the file mark, and then back up one record and read it.
98057578Smuller 	 * this should tell us the physical record size the tape is using.
98157578Smuller 	 */
98257578Smuller 	if (lstrval == 1) {
98357578Smuller 		/*
98457578Smuller 		 * we know we are at file mark when we get back a 0 from
98557578Smuller 		 * read()
98657578Smuller 		 */
98757578Smuller 		while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
98857578Smuller 			padsz += res;
98957578Smuller 		if (res < 0) {
99057578Smuller 			syswarn(1, errno, "Unable to locate tape filemark.");
99157578Smuller 			return(-1);
99257578Smuller 		}
99357578Smuller 	}
99457193Smuller 
99557578Smuller 	/*
99657578Smuller 	 * move backwards over the file mark so we are at the end of the
99757578Smuller 	 * last record.
99857578Smuller 	 */
99957578Smuller 	mb.mt_op = MTBSF;
100057193Smuller 	mb.mt_count = 1;
100157578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
100257578Smuller 		syswarn(1, errno, "Unable to backspace over tape filemark.");
100357193Smuller 		return(-1);
100457535Smuller 	}
100557193Smuller 
100657193Smuller 	/*
100757578Smuller 	 * move backwards so we are in front of the last record and read it to
100857578Smuller 	 * get physical tape blocksize.
100957193Smuller 	 */
101057578Smuller 	mb.mt_op = MTBSR;
101157578Smuller 	mb.mt_count = 1;
101257578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
101357578Smuller 		syswarn(1, errno, "Unable to backspace over last tape block.");
101457193Smuller 		return(-1);
101557578Smuller 	}
101657578Smuller 	if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) {
101757578Smuller 		syswarn(1, errno, "Cannot determine archive tape blocksize.");
101857578Smuller 		return(-1);
101957578Smuller 	}
102057535Smuller 
102157535Smuller 	/*
102257578Smuller 	 * read foward to the file mark, then back up in front of the filemark
102357578Smuller 	 * (this is a bit paranoid, but should be safe to do).
102457535Smuller 	 */
102557578Smuller 	while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
102657578Smuller 		;
102757578Smuller 	if (res < 0) {
102857578Smuller 		syswarn(1, errno, "Unable to locate tape filemark.");
102957535Smuller 		return(-1);
103057578Smuller 	}
103157578Smuller 	mb.mt_op = MTBSF;
103257578Smuller 	mb.mt_count = 1;
103357578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
103457578Smuller 		syswarn(1, errno, "Unable to backspace over tape filemark.");
103557578Smuller 		return(-1);
103657578Smuller 	}
103757535Smuller 
103857535Smuller 	/*
103957578Smuller 	 * set lstrval so we know that the filemark has not been seen
104057535Smuller 	 */
104157578Smuller 	lstrval = 1;
104257578Smuller 
104357578Smuller 	/*
104457578Smuller 	 * return if there was no padding
104557578Smuller 	 */
104657578Smuller 	if (padsz == 0)
104757535Smuller 		return(0);
104857535Smuller 
104957535Smuller 	/*
105057578Smuller 	 * make sure we can move backwards over the padding. (this should
105157578Smuller 	 * never fail).
105257535Smuller 	 */
105357578Smuller 	if (padsz % phyblk) {
105457578Smuller 		warn(1, "Tape drive unable to backspace requested amount");
105557535Smuller 		return(-1);
105657578Smuller 	}
105757535Smuller 
105857535Smuller 	/*
105957578Smuller 	 * move backwards over the padding so the head is where it was when
106057578Smuller 	 * we were first called (if required).
106157535Smuller 	 */
106257578Smuller 	mb.mt_op = MTBSR;
106357578Smuller 	mb.mt_count = padsz/phyblk;
106457578Smuller 	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {
106557578Smuller 		syswarn(1,errno,"Unable to backspace tape over %d pad blocks",
106657578Smuller 		    mb.mt_count);
106757535Smuller 		return(-1);
106857578Smuller 	}
106957193Smuller 	return(0);
107057193Smuller }
107157193Smuller 
107257193Smuller /*
107357193Smuller  * ar_next()
107457535Smuller  *	prompts the user for the next volume in this archive. For some devices
107557535Smuller  *	we may allow the media to be changed. Otherwise a new archive is
107657535Smuller  *	prompted for. By pax spec, if there is no controlling tty or an eof is
107757535Smuller  *	read on tty input, we must quit pax.
107857193Smuller  * Return:
107957193Smuller  *	0 when ready to continue, -1 when all done
108057193Smuller  */
108157193Smuller 
108257193Smuller #if __STDC__
108357193Smuller int
108457193Smuller ar_next(void)
108557193Smuller #else
108657193Smuller int
108757193Smuller ar_next()
108857193Smuller #endif
108957193Smuller {
109057193Smuller 	char buf[PAXPATHLEN+2];
109157193Smuller 	static int freeit = 0;
109257193Smuller 	sigset_t o_mask;
109357193Smuller 
109457193Smuller 	/*
109557535Smuller 	 * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so
109657193Smuller 	 * things like writing EOF etc will be done) (Watch out ar_close() can
109757535Smuller 	 * also be called via a signal handler, so we must prevent a race.
109857193Smuller 	 */
109957193Smuller 	if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0)
110057535Smuller 		syswarn(0, errno, "Unable to set signal mask");
110157193Smuller 	ar_close();
110257193Smuller 	if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0)
110357535Smuller 		syswarn(0, errno, "Unable to restore signal mask");
110457193Smuller 
110557578Smuller 	if (done || !wr_trail)
110657193Smuller 		return(-1);
110757193Smuller 
110857193Smuller 	tty_prnt("\nATTENTION! Pax archive volume change required.\n");
110957193Smuller 
111057193Smuller 	/*
111157193Smuller 	 * if i/o is on stdin or stdout, we cannot reopen it (we do not know
111257535Smuller 	 * the name), the user will be forced to type it in.
111357193Smuller 	 */
111457193Smuller 	if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG)
111557193Smuller 	    && (artyp != ISPIPE)) {
111657193Smuller 		if (artyp == ISTAPE) {
111757193Smuller 			tty_prnt("%s ready for archive tape volume: %d\n",
111857193Smuller 				arcname, arvol);
111957193Smuller 			tty_prnt("Load the NEXT TAPE on the tape drive");
112057193Smuller 		} else {
112157193Smuller 			tty_prnt("%s ready for archive volume: %d\n",
112257193Smuller 				arcname, arvol);
112357193Smuller 			tty_prnt("Load the NEXT STORAGE MEDIA (if required)");
112457193Smuller 		}
112557193Smuller 
112657193Smuller 		if ((act == ARCHIVE) || (act == APPND))
112757193Smuller 			tty_prnt(" and make sure it is WRITE ENABLED.\n");
112857193Smuller 		else
112957193Smuller 			tty_prnt("\n");
113057193Smuller 
113157193Smuller 		for(;;) {
113257193Smuller 			tty_prnt("Type \"y\" to continue, \".\" to quit pax,");
113357193Smuller 			tty_prnt(" or \"s\" to switch to new device.\nIf you");
113457193Smuller 			tty_prnt(" cannot change storage media, type \"s\"\n");
113557193Smuller 			tty_prnt("Is the device ready and online? > ");
113657193Smuller 
113757193Smuller 			if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){
113857193Smuller 				done = 1;
113957193Smuller 				lstrval = -1;
114057193Smuller 				tty_prnt("Quitting pax!\n");
114157193Smuller 				vfpart = 0;
114257193Smuller 				return(-1);
114357193Smuller 			}
114457193Smuller 
114557193Smuller 			if ((buf[0] == '\0') || (buf[1] != '\0')) {
114657193Smuller 				tty_prnt("%s unknown command, try again\n",buf);
114757193Smuller 				continue;
114857193Smuller 			}
114957193Smuller 
115057193Smuller 			switch (buf[0]) {
115157193Smuller 			case 'y':
115257193Smuller 			case 'Y':
115357193Smuller 				/*
115457193Smuller 				 * we are to continue with the same device
115557193Smuller 				 */
115657193Smuller 				if (ar_open(arcname) >= 0)
115757193Smuller 					return(0);
115857193Smuller 				tty_prnt("Cannot re-open %s, try again\n",
115957193Smuller 					arcname);
116057193Smuller 				continue;
116157193Smuller 			case 's':
116257193Smuller 			case 'S':
116357193Smuller 				/*
116457193Smuller 				 * user wants to open a different device
116557193Smuller 				 */
116657193Smuller 				tty_prnt("Switching to a different archive\n");
116757193Smuller 				break;
116857193Smuller 			default:
116957193Smuller 				tty_prnt("%s unknown command, try again\n",buf);
117057193Smuller 				continue;
117157193Smuller 			}
117257193Smuller 			break;
117357193Smuller 		}
117457193Smuller 	} else
117557193Smuller 		tty_prnt("Ready for archive volume: %d\n", arvol);
117657193Smuller 
117757193Smuller 	/*
117857193Smuller 	 * have to go to a different archive
117957193Smuller 	 */
118057193Smuller 	for (;;) {
118157193Smuller 		tty_prnt("Input archive name or \".\" to quit pax.\n");
118257193Smuller 		tty_prnt("Archive name > ");
118357193Smuller 
118457193Smuller 		if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) {
118557193Smuller 			done = 1;
118657193Smuller 			lstrval = -1;
118757193Smuller 			tty_prnt("Quitting pax!\n");
118857193Smuller 			vfpart = 0;
118957193Smuller 			return(-1);
119057193Smuller 		}
119157193Smuller 		if (buf[0] == '\0') {
119257193Smuller 			tty_prnt("Empty file name, try again\n");
119357193Smuller 			continue;
119457193Smuller 		}
119557193Smuller                 if (!strcmp(buf, "..")) {
119657193Smuller                         tty_prnt("Illegal file name: .. try again\n");
119757193Smuller                         continue;
119857193Smuller                 }
119957193Smuller 		if (strlen(buf) > PAXPATHLEN) {
120057193Smuller 			tty_prnt("File name too long, try again\n");
120157193Smuller 			continue;
120257193Smuller 		}
120357193Smuller 
120457193Smuller 		/*
120557193Smuller 		 * try to open new archive
120657193Smuller 		 */
120757193Smuller 		if (ar_open(buf) >= 0) {
120857193Smuller 			if (freeit) {
120957193Smuller 				(void)free(arcname);
121057193Smuller 				freeit = 0;
121157193Smuller 			}
121257193Smuller 			if ((arcname = strdup(buf)) == NULL) {
121357193Smuller 				done = 1;
121457193Smuller 				lstrval = -1;
121557535Smuller 				warn(0, "Cannot save archive name.");
121657193Smuller 				return(-1);
121757193Smuller 			}
121857193Smuller 			freeit = 1;
121957193Smuller 			break;
122057193Smuller 		}
122157193Smuller 		tty_prnt("Cannot open %s, try again\n", buf);
122257193Smuller 		continue;
122357193Smuller 	}
122457193Smuller 	return(0);
122557193Smuller }
1226