Beispiel #1
0
int
_rmtopendev(char *path, int oflags, int dflags, char **realpath)
{
#ifdef RMT
	if (host)
		return rmtopen(path, oflags);
#endif
	return opendev(path, oflags, dflags, realpath);
}
Beispiel #2
0
/*
 *	Create a file from scratch.  Looks just like creat(2) to the caller.
 */
int
rmtcreat(const char *path, mode_t mode)
{

	_DIAGASSERT(path != NULL);

	if (remdev(path)) {
		return rmtopen(path, O_WRONLY | O_CREAT, mode);
	} else {
		return open(path, O_CREAT | O_TRUNC | O_WRONLY, mode);
	}
}
Beispiel #3
0
/*
 * Prompt user to load a new dump volume.
 * "Nextvol" is the next suggested volume to use.
 * This suggested volume is enforced when doing full
 * or incremental restores, but can be overridden by
 * the user when only extracting a subset of the files.
 */
void
getvol(long nextvol)
{
	int64_t prevtapea;
	long i, newvol, savecnt;
	union u_spcl tmpspcl;
#	define tmpbuf tmpspcl.s_spcl
	char buf[TP_BSIZE];

	if (nextvol == 1) {
		tapesread = 0;
		gettingfile = 0;
	}
	prevtapea = tapeaddr;
	savecnt = blksread;
	if (pipein) {
		if (nextvol != 1) {
			panic("Changing volumes on pipe input?\n");
			/* Avoid looping if we couldn't ask the user. */
			if (yflag || ferror(terminal) || feof(terminal))
				done(1);
		}
		if (volno == 1)
			return;
		goto gethdr;
	}
again:
	if (pipein)
		done(1); /* pipes do not get a second chance */
	if (command == 'R' || command == 'r' || curfile.action != SKIP)
		newvol = nextvol;
	else
		newvol = 0;
	while (newvol <= 0) {
		if (tapesread == 0) {
			fprintf(stderr, "%s%s%s%s%s%s%s",
			    "You have not read any tapes yet.\n",
			    "If you are extracting just a few files,",
			    " start with the last volume\n",
			    "and work towards the first; restore",
			    " can quickly skip tapes that\n",
			    "have no further files to extract.",
			    " Otherwise, begin with volume 1.\n");
		} else {
			fprintf(stderr, "You have read volumes");
			strcpy(buf, ": ");
			for (i = 0; i < 32; i++)
				if (tapesread & (1 << i)) {
					fprintf(stderr, "%s%ld", buf, i + 1);
					strcpy(buf, ", ");
				}
			fprintf(stderr, "\n");
		}
		do	{
			fprintf(stderr, "Specify next volume #: ");
			(void) fflush(stderr);
			if (fgets(buf, BUFSIZ, terminal) == NULL)
				done(1);
		} while (buf[0] == '\n');
		newvol = atoi(buf);
		if (newvol <= 0) {
			fprintf(stderr,
			    "Volume numbers are positive numerics\n");
		}
	}
	if (newvol == volno) {
		tapesread |= 1 << (volno - 1);
		return;
	}
	closemt();
	fprintf(stderr, "Mount tape volume %ld\n", newvol);
	fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
	fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
	(void) fflush(stderr);
	if (fgets(buf, BUFSIZ, terminal) == NULL)
		done(1);
	if (!strcmp(buf, "none\n")) {
		terminateinput();
		return;
	}
	if (buf[0] != '\n') {
		(void) strcpy(magtape, buf);
		magtape[strlen(magtape) - 1] = '\0';
	}
	if (pipecmdin) {
		char volno[sizeof("2147483647")];

		(void)sprintf(volno, "%ld", newvol);
		if (setenv("RESTORE_VOLUME", volno, 1) == -1) {
			fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
			    strerror(errno));
			done(1);
		}
		popenfp = popen(magtape, "r");
		mt = popenfp ? fileno(popenfp) : -1;
	} else
#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
		mt = open(magtape, O_RDONLY, 0);

	if (mt == -1) {
		fprintf(stderr, "Cannot open %s\n", magtape);
		volno = -1;
		goto again;
	}
gethdr:
	volno = newvol;
	setdumpnum();
	FLUSHTAPEBUF();
	if (gethead(&tmpbuf) == FAIL) {
		dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		fprintf(stderr, "tape is not dump tape\n");
		volno = 0;
		goto again;
	}
	if (tmpbuf.c_volume != volno) {
		fprintf(stderr, "Wrong volume (%jd)\n",
		    (intmax_t)tmpbuf.c_volume);
		volno = 0;
		goto again;
	}
	if (_time64_to_time(tmpbuf.c_date) != dumpdate ||
	    _time64_to_time(tmpbuf.c_ddate) != dumptime) {
		time_t t = _time64_to_time(tmpbuf.c_date);
		fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t));
		fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
		volno = 0;
		goto again;
	}
	tapesread |= 1 << (volno - 1);
	blksread = savecnt;
 	/*
 	 * If continuing from the previous volume, skip over any
 	 * blocks read already at the end of the previous volume.
 	 *
 	 * If coming to this volume at random, skip to the beginning
 	 * of the next record.
 	 */
	dprintf(stdout, "last rec %jd, tape starts with %jd\n",
	    (intmax_t)prevtapea, (intmax_t)tmpbuf.c_tapea);
 	if (tmpbuf.c_type == TS_TAPE) {
 		if (curfile.action != USING) {
			/*
			 * XXX Dump incorrectly sets c_count to 1 in the
			 * volume header of the first tape, so ignore
			 * c_count when volno == 1.
			 */
			if (volno != 1)
				for (i = tmpbuf.c_count; i > 0; i--)
					readtape(buf);
 		} else if (tmpbuf.c_tapea <= prevtapea) {
			/*
			 * Normally the value of c_tapea in the volume
			 * header is the record number of the header itself.
			 * However in the volume header following an EOT-
			 * terminated tape, it is the record number of the
			 * first continuation data block (dump bug?).
			 *
			 * The next record we want is `prevtapea + 1'.
			 */
 			i = prevtapea + 1 - tmpbuf.c_tapea;
			dprintf(stderr, "Skipping %ld duplicate record%s.\n",
				i, i > 1 ? "s" : "");
 			while (--i >= 0)
 				readtape(buf);
 		}
 	}
	if (curfile.action == USING) {
		if (volno == 1)
			panic("active file into volume 1\n");
		return;
	}
	(void) gethead(&spcl);
	findinode(&spcl);
	if (gettingfile) {
		gettingfile = 0;
		longjmp(restart, 1);
	}
}
Beispiel #4
0
/*
 * Verify that the tape drive can be accessed and
 * that it actually is a dump tape.
 */
void
setup(void)
{
	int i, j, *ip;
	struct stat stbuf;

	vprintf(stdout, "Verify tape and initialize maps\n");
	if (pipecmdin) {
		if (setenv("RESTORE_VOLUME", "1", 1) == -1) {
			fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
			    strerror(errno));
			done(1);
		}
		popenfp = popen(magtape, "r");
		mt = popenfp ? fileno(popenfp) : -1;
	} else
#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
	if (pipein)
		mt = 0;
	else
		mt = open(magtape, O_RDONLY, 0);
	if (mt < 0) {
		fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
		done(1);
	}
	volno = 1;
	setdumpnum();
	FLUSHTAPEBUF();
	if (!pipein && !pipecmdin && !bflag)
		findtapeblksize();
	if (gethead(&spcl) == FAIL) {
		fprintf(stderr, "Tape is not a dump tape\n");
		done(1);
	}
	if (pipein) {
		endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC;
		endoftapemark.s_spcl.c_type = TS_END;
		ip = (int *)&endoftapemark;
		j = sizeof(union u_spcl) / sizeof(int);
		i = 0;
		do
			i += *ip++;
		while (--j);
		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
	}
	if (vflag || command == 't')
		printdumpinfo();
	dumptime = _time64_to_time(spcl.c_ddate);
	dumpdate = _time64_to_time(spcl.c_date);
	if (stat(".", &stbuf) < 0) {
		fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
		done(1);
	}
	if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
		fssize = TP_BSIZE;
	if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE)
		fssize = stbuf.st_blksize;
	if (((TP_BSIZE - 1) & stbuf.st_blksize) != 0) {
		fprintf(stderr, "Warning: filesystem with non-multiple-of-%d "
		    "blocksize (%d);\n", TP_BSIZE, stbuf.st_blksize);
		fssize = roundup(fssize, TP_BSIZE);
		fprintf(stderr, "\twriting using blocksize %ld\n", fssize);
	}
	if (spcl.c_volume != 1) {
		fprintf(stderr, "Tape is not volume 1 of the dump\n");
		done(1);
	}
	if (gethead(&spcl) == FAIL) {
		dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		panic("no header after volume mark!\n");
	}
	findinode(&spcl);
	if (spcl.c_type != TS_CLRI) {
		fprintf(stderr, "Cannot find file removal list\n");
		done(1);
	}
	maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
	dprintf(stdout, "maxino = %ju\n", (uintmax_t)maxino);
	map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
	if (map == NULL)
		panic("no memory for active inode map\n");
	usedinomap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip, xtrmapskip);
	if (spcl.c_type != TS_BITS) {
		fprintf(stderr, "Cannot find file dump list\n");
		done(1);
	}
	map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
	if (map == (char *)NULL)
		panic("no memory for file dump list\n");
	dumpmap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip, xtrmapskip);
	/*
	 * If there may be whiteout entries on the tape, pretend that the
	 * whiteout inode exists, so that the whiteout entries can be
	 * extracted.
	 */
	SETINO(WINO, dumpmap);
	/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
	if (command == 'r')
		tapesread = 1;
}
Beispiel #5
0
/*
 * Prompt user to load a new dump volume.
 * "Nextvol" is the next suggested volume to use.
 * This suggested volume is enforced when doing full
 * or incremental restores, but can be overrridden by
 * the user when only extracting a subset of the files.
 */
void
getvol(long nextvol)
{
	long newvol = 0, savecnt = 0, wantnext = 0, i;
	union u_spcl tmpspcl;
#	define tmpbuf tmpspcl.s_spcl
	char buf[TP_BSIZE];
	const char *errstr;

	if (nextvol == 1) {
		tapesread = 0;
		gettingfile = 0;
	}
	if (pipein) {
		if (nextvol != 1)
			panic("Changing volumes on pipe input?\n");
		if (volno == 1)
			return;
		goto gethdr;
	}
	savecnt = blksread;
again:
	if (pipein)
		exit(1); /* pipes do not get a second chance */
	if (command == 'R' || command == 'r' || curfile.action != SKIP) {
		newvol = nextvol;
		wantnext = 1;
	} else {
		newvol = 0;
		wantnext = 0;
	}
	while (newvol <= 0) {
		if (tapesread == 0) {
			fprintf(stderr, "%s%s%s%s%s",
			    "You have not read any tapes yet.\n",
			    "Unless you know which volume your",
			    " file(s) are on you should start\n",
			    "with the last volume and work",
			    " towards the first.\n");
		} else {
			fprintf(stderr, "You have read volumes");
			strlcpy(buf, ": ", sizeof buf);
			for (i = 1; i < 32; i++)
				if (tapesread & (1 << i)) {
					fprintf(stderr, "%s%ld", buf, i);
					strlcpy(buf, ", ", sizeof buf);
				}
			fprintf(stderr, "\n");
		}
		do	{
			fprintf(stderr, "Specify next volume #: ");
			(void)fflush(stderr);
			if (fgets(buf, sizeof buf, terminal) == NULL)
				exit(1);
			buf[strcspn(buf, "\n")] = '\0';

			newvol = strtonum(buf, 1, INT_MAX, &errstr);
			if (errstr)
				fprintf(stderr, "Volume number %s: %s\n", errstr, buf);
		} while (errstr);
	}
	if (newvol == volno) {
		tapesread |= 1 << volno;
		return;
	}
	closemt();
	fprintf(stderr, "Mount tape volume %ld\n", newvol);
	fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
	fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
	(void)fflush(stderr);
	if (fgets(buf, sizeof buf, terminal) == NULL || feof(terminal))
		exit(1);
	buf[strcspn(buf, "\n")] = '\0';
	if (strcmp(buf, "none") == 0) {
		terminateinput();
		return;
	}
	if (buf[0] != '\0')
		(void)strlcpy(magtape, buf, sizeof magtape);

#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
		mt = open(magtape, O_RDONLY);

	if (mt == -1) {
		fprintf(stderr, "Cannot open %s\n", magtape);
		volno = -1;
		goto again;
	}
gethdr:
	volno = newvol;
	setdumpnum();
	FLUSHTAPEBUF();
	if (gethead(&tmpbuf) == FAIL) {
		Dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		fprintf(stderr, "tape is not dump tape\n");
		volno = 0;
		goto again;
	}
	if (tmpbuf.c_volume != volno) {
		fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
		volno = 0;
		goto again;
	}
	if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
		time_t t = (time_t)tmpbuf.c_date;
		fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t));
		fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
		volno = 0;
		goto again;
	}
	tapesread |= 1 << volno;
	blksread = savecnt;
 	/*
 	 * If continuing from the previous volume, skip over any
 	 * blocks read already at the end of the previous volume.
 	 *
 	 * If coming to this volume at random, skip to the beginning
 	 * of the next record.
 	 */
	Dprintf(stdout, "read %ld recs, tape starts with %lld\n",
		tpblksread, tmpbuf.c_firstrec);
 	if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
 		if (!wantnext) {
 			tpblksread = tmpbuf.c_firstrec;
 			for (i = tmpbuf.c_count; i > 0; i--)
 				readtape(buf);
 		} else if (tmpbuf.c_firstrec > 0 &&
			   tmpbuf.c_firstrec < tpblksread - 1) {
			/*
			 * -1 since we've read the volume header
			 */
 			i = tpblksread - tmpbuf.c_firstrec - 1;
			Dprintf(stderr, "Skipping %ld duplicate record%s.\n",
				i, (i == 1) ? "" : "s");
 			while (--i >= 0)
 				readtape(buf);
 		}
 	}
	if (curfile.action == USING) {
		if (volno == 1)
			panic("active file into volume 1\n");
		return;
	}
	/*
	 * Skip up to the beginning of the next record
	 */
	if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER))
		for (i = tmpbuf.c_count; i > 0; i--)
			readtape(buf);
	(void)gethead(&spcl);
	findinode(&spcl);
	if (gettingfile) {
		gettingfile = 0;
		longjmp(restart, 1);
	}
}
Beispiel #6
0
/*
 * Verify that the tape drive can be accessed and
 * that it actually is a dump tape.
 */
void
setup(void)
{
	int i, j, *ip;
	struct stat stbuf;

	Vprintf(stdout, "Verify tape and initialize maps\n");
#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
	if (pipein)
		mt = 0;
	else
		mt = open(magtape, O_RDONLY);
	if (mt < 0)
		err(1, "%s", magtape);
	volno = 1;
	setdumpnum();
	FLUSHTAPEBUF();
	if (!pipein && !bflag)
		findtapeblksize();
	if (gethead(&spcl) == FAIL) {
		blkcnt--; /* push back this block */
		blksread--;
		tpblksread--;
		cvtflag++;
		if (gethead(&spcl) == FAIL)
			errx(1, "Tape is not a dump tape");
		(void)fputs("Converting to new file system format.\n", stderr);
	}
	if (pipein) {
		endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC :
		    FS_UFS2_MAGIC;
		endoftapemark.s_spcl.c_type = TS_END;
		ip = (int *)&endoftapemark;
		j = sizeof(union u_spcl) / sizeof(int);
		i = 0;
		do
			i += *ip++;
		while (--j);
		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
	}
	if (vflag || command == 't')
		printdumpinfo();
	dumptime = (time_t)spcl.c_ddate;
	dumpdate = (time_t)spcl.c_date;
	if (stat(".", &stbuf) < 0)
		err(1, "cannot stat .");
	if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
		fssize = TP_BSIZE;
	if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE)
		fssize = stbuf.st_blksize;
	if (((fssize - 1) & fssize) != 0)
		errx(1, "bad block size %ld", fssize);
	if (spcl.c_volume != 1)
		errx(1, "Tape is not volume 1 of the dump");
	if (gethead(&spcl) == FAIL) {
		Dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		panic("no header after volume mark!\n");
	}
	findinode(&spcl);
	if (spcl.c_type != TS_CLRI)
		errx(1, "Cannot find file removal list");
	maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
	Dprintf(stdout, "maxino = %d\n", maxino);
	map = calloc(1, howmany(maxino, NBBY));
	if (map == NULL)
		panic("no memory for active inode map\n");
	usedinomap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip);
	if (spcl.c_type != TS_BITS)
		errx(1, "Cannot find file dump list");
	map = calloc(1, howmany(maxino, NBBY));
	if (map == NULL)
		panic("no memory for file dump list\n");
	dumpmap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip);
}
Beispiel #7
0
int
ar_open(const char *name)
{
#ifdef HAVE_SYS_MTIO_H
	struct mtget mb;
#endif

	if (arfd != -1)
		(void)close(arfd);
	arfd = -1;
	can_unlnk = did_io = io_ok = invld_rec = 0;
	artyp = ISREG;
	flcnt = 0;

#ifdef SUPPORT_RMT
	if (name && strchr(name, ':') != NULL && !forcelocal) {
		artyp = ISRMT;
		if ((arfd = rmtopen(name, O_RDWR, DMOD)) == -1) {
			syswarn(0, errno, "Failed open on %s", name);
			return -1;
		}
		if (!isrmt(arfd)) {
			rmtclose(arfd);
			tty_warn(0, "Not a remote file: %s", name);
			return -1;
		}
		blksz = rdblksz = 8192;
		lstrval = 1;
		return 0;
	}
#endif /* SUPPORT_RMT */

	/*
	 * open based on overall operation mode
	 */
	switch (act) {
	case LIST:
	case EXTRACT:
		if (name == NULL) {
			arfd = STDIN_FILENO;
			arcname = STDN;
		} else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
			syswarn(0, errno, "Failed open to read on %s", name);
		if (arfd != -1 && gzip_program != NULL)
			ar_start_gzip(arfd, gzip_program, 0);
		break;
	case ARCHIVE:
		if (name == NULL) {
			arfd = STDOUT_FILENO;
			arcname = STDO;
		} else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
			syswarn(0, errno, "Failed open to write on %s", name);
		else
			can_unlnk = 1;
		if (arfd != -1 && gzip_program != NULL)
			ar_start_gzip(arfd, gzip_program, 1);
		break;
	case APPND:
		if (name == NULL) {
			arfd = STDOUT_FILENO;
			arcname = STDO;
		} else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
			syswarn(0, errno, "Failed open to read/write on %s",
				name);
		break;
	case COPY:
		/*
		 * arfd not used in COPY mode
		 */
		arcname = NONE;
		lstrval = 1;
		return 0;
	}
	if (arfd < 0)
		return -1;

	if (chdname != NULL)
		if (dochdir(chdname) == -1)
			return -1;
	/*
	 * set up is based on device type
	 */
	if (fstat(arfd, &arsb) < 0) {
		syswarn(0, errno, "Failed stat on %s", arcname);
		(void)close(arfd);
		arfd = -1;
		can_unlnk = 0;
		return -1;
	}
	if (S_ISDIR(arsb.st_mode)) {
		tty_warn(0, "Cannot write an archive on top of a directory %s",
		    arcname);
		(void)close(arfd);
		arfd = -1;
		can_unlnk = 0;
		return -1;
	}

	if (S_ISCHR(arsb.st_mode)) {
#ifdef HAVE_SYS_MTIO_H
		artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;
#else
		tty_warn(1, "System does not have tape support");
		artyp = ISREG;
#endif
	} else if (S_ISBLK(arsb.st_mode))
		artyp = ISBLK;
	else if ((lseek(arfd, (off_t)0L, SEEK_CUR) == -1) && (errno == ESPIPE))
		artyp = ISPIPE;
	else
		artyp = ISREG;

	/*
	 * Special handling for empty files.
	 */
	if (artyp == ISREG && arsb.st_size == 0) {
		switch (act) {
		case LIST:
		case EXTRACT:
			return -1;
		case APPND:
			act = -ARCHIVE;
			return -1;
		case ARCHIVE:
			break;
		}
	}

	/*
	 * make sure we beyond any doubt that we only can unlink regular files
	 * we created
	 */
	if (artyp != ISREG)
		can_unlnk = 0;

	/*
	 * if we are writing, we are done
	 */
	if (act == ARCHIVE) {
		blksz = rdblksz = wrblksz;
		lstrval = 1;
		return 0;
	}

	/*
	 * set default blksz on read. APPNDs writes rdblksz on the last volume
	 * On all new archive volumes, we shift to wrblksz (if the user
	 * specified one, otherwize we will continue to use rdblksz). We
	 * must set blocksize based on what kind of device the archive is
	 * stored.
	 */
	switch(artyp) {
	case ISTAPE:
		/*
		 * Tape drives come in at least two flavors. Those that support
		 * variable sized records and those that have fixed sized
		 * records. They must be treated differently. For tape drives
		 * that support variable sized records, we must make large
		 * reads to make sure we get the entire record, otherwise we
		 * will just get the first part of the record (up to size we
		 * asked). Tapes with fixed sized records may or may not return
		 * multiple records in a single read. We really do not care
		 * what the physical record size is UNLESS we are going to
		 * append. (We will need the physical block size to rewrite
		 * the trailer). Only when we are appending do we go to the
		 * effort to figure out the true PHYSICAL record size.
		 */
		blksz = rdblksz = MAXBLK;
		break;
	case ISPIPE:
	case ISBLK:
	case ISCHR:
		/*
		 * Blocksize is not a major issue with these devices (but must
		 * be kept a multiple of 512). If the user specified a write
		 * block size, we use that to read. Under append, we must
		 * always keep blksz == rdblksz. Otherwise we go ahead and use
		 * the device optimal blocksize as (and if) returned by stat
		 * and if it is within pax specs.
		 */
		if ((act == APPND) && wrblksz) {
			blksz = rdblksz = wrblksz;
			break;
		}

		if ((arsb.st_blksize > 0) && (arsb.st_blksize < MAXBLK) &&
		    ((arsb.st_blksize % BLKMULT) == 0))
			rdblksz = arsb.st_blksize;
		else
			rdblksz = DEVBLK;
		/*
		 * For performance go for large reads when we can without harm
		 */
		if ((act == APPND) || (artyp == ISCHR))
			blksz = rdblksz;
		else
			blksz = MAXBLK;
		break;
	case ISREG:
		/*
		 * if the user specified wrblksz works, use it. Under appends
		 * we must always keep blksz == rdblksz
		 */
		if ((act == APPND) && wrblksz && ((arsb.st_size%wrblksz)==0)){
			blksz = rdblksz = wrblksz;
			break;
		}
		/*
		 * See if we can find the blocking factor from the file size
		 */
		for (rdblksz = MAXBLK; rdblksz > 0; rdblksz -= BLKMULT)
			if ((arsb.st_size % rdblksz) == 0)
				break;
		/*
		 * When we cannot find a match, we may have a flawed archive.
		 */
		if (rdblksz <= 0)
			rdblksz = FILEBLK;
		/*
		 * for performance go for large reads when we can
		 */
		if (act == APPND)
			blksz = rdblksz;
		else
			blksz = MAXBLK;
		break;
	default:
		/*
		 * should never happen, worst case, slow...
		 */
		blksz = rdblksz = BLKMULT;
		break;
	}
	lstrval = 1;
	return 0;
}
Beispiel #8
0
/* Set ARCHIVE for uncompressing, then reading an archive.  */
pid_t
sys_child_open_for_uncompress (void)
{
  int parent_pipe[2];
  int child_pipe[2];
  pid_t grandchild_pid;
  pid_t child_pid;

  xpipe (parent_pipe);
  child_pid = xfork ();

  if (child_pid > 0)
    {
      /* The parent tar is still here!  Just clean up.  */

      archive = parent_pipe[PREAD];
      xclose (parent_pipe[PWRITE]);
      return child_pid;
    }

  /* The newborn child tar is here!  */

  set_program_name (_("tar (child)"));
  signal (SIGPIPE, SIG_DFL);
  
  xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
  xclose (parent_pipe[PREAD]);

  /* Check if we need a grandchild tar.  This happens only if either:
     a) we're reading stdin: to force unblocking;
     b) the file is to be accessed by rmt: compressor doesn't know how;
     c) the file is not a plain file.  */

  if (strcmp (archive_name_array[0], "-") != 0
      && !_remdev (archive_name_array[0])
      && is_regular_file (archive_name_array[0]))
    {
      /* We don't need a grandchild tar.  Open the archive and lauch the
	 uncompressor.  */

      archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);
      if (archive < 0)
	open_fatal (archive_name_array[0]);
      xdup2 (archive, STDIN_FILENO);
      execlp (use_compress_program_option, use_compress_program_option,
	      "-d", (char *) 0);
      exec_fatal (use_compress_program_option);
    }

  /* We do need a grandchild tar.  */

  xpipe (child_pipe);
  grandchild_pid = xfork ();

  if (grandchild_pid == 0)
    {
      /* The newborn grandchild tar is here!  Launch the uncompressor.  */

      set_program_name (_("tar (grandchild)"));

      xdup2 (child_pipe[PREAD], STDIN_FILENO);
      xclose (child_pipe[PWRITE]);
      execlp (use_compress_program_option, use_compress_program_option,
	      "-d", (char *) 0);
      exec_fatal (use_compress_program_option);
    }

  /* The child tar is still here!  */

  /* Prepare for unblocking the data from the archive into the
     uncompressor.  */

  xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
  xclose (child_pipe[PREAD]);

  if (strcmp (archive_name_array[0], "-") == 0)
    archive = STDIN_FILENO;
  else
    archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
		       MODE_RW, rsh_command_option);
  if (archive < 0)
    open_fatal (archive_name_array[0]);

  /* Let's read the archive and pipe it into stdout.  */

  while (1)
    {
      char *cursor;
      size_t maximum;
      size_t count;
      size_t status;

      clear_read_error_count ();

    error_loop:
      status = rmtread (archive, record_start->buffer, record_size);
      if (status == SAFE_READ_ERROR)
	{
	  archive_read_error ();
	  goto error_loop;
	}
      if (status == 0)
	break;
      cursor = record_start->buffer;
      maximum = status;
      while (maximum)
	{
	  count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
	  if (full_write (STDOUT_FILENO, cursor, count) != count)
	    write_error (use_compress_program_option);
	  cursor += count;
	  maximum -= count;
	}
    }

  xclose (STDOUT_FILENO);

  wait_for_grandchild (grandchild_pid);
}
Beispiel #9
0
/*
 * Verify that the tape drive can be accessed and
 * that it actually is a dump tape.
 */
void
setup(void)
{
	int i, j, *ip;
	struct stat stbuf;

	vprintf(stdout, "Verify tape and initialize maps\n");
#ifdef RRESTORE
	if (host)
		mt = rmtopen(magtape, 0);
	else
#endif
	if (pipein)
		mt = 0;
	else
		mt = open(magtape, O_RDONLY, 0);
	if (mt < 0) {
		fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
		done(1);
	}
	volno = 1;
	setdumpnum();
	FLUSHTAPEBUF();
	if (!pipein && !bflag)
		findtapeblksize();
	if (gethead(&spcl) == FAIL) {
		blkcnt--; /* push back this block */
		blksread--;
		cvtflag++;
		if (gethead(&spcl) == FAIL) {
			fprintf(stderr, "Tape is not a dump tape\n");
			done(1);
		}
		fprintf(stderr, "Converting to new file system format.\n");
	}
	if (pipein) {
		endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
		endoftapemark.s_spcl.c_type = TS_END;
		ip = (int *)&endoftapemark;
		j = sizeof(union u_spcl) / sizeof(int);
		i = 0;
		do
			i += *ip++;
		while (--j);
		endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
	}
	if (vflag || command == 't')
		printdumpinfo();
	dumptime = spcl.c_ddate;
	dumpdate = spcl.c_date;
	if (stat(".", &stbuf) < 0) {
		fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
		done(1);
	}
	if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
		fssize = TP_BSIZE;
	if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE)
		fssize = stbuf.st_blksize;
	if (((fssize - 1) & fssize) != 0) {
		fprintf(stderr, "bad block size %ld\n", fssize);
		done(1);
	}
	if (spcl.c_volume != 1) {
		fprintf(stderr, "Tape is not volume 1 of the dump\n");
		done(1);
	}
	if (gethead(&spcl) == FAIL) {
		dprintf(stdout, "header read failed at %ld blocks\n", blksread);
		panic("no header after volume mark!\n");
	}
	findinode(&spcl);
	if (spcl.c_type != TS_CLRI) {
		fprintf(stderr, "Cannot find file removal list\n");
		done(1);
	}
	maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
	dprintf(stdout, "maxino = %d\n", maxino);
	map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
	if (map == NULL)
		panic("no memory for active inode map\n");
	usedinomap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip);
	if (spcl.c_type != TS_BITS) {
		fprintf(stderr, "Cannot find file dump list\n");
		done(1);
	}
	map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
	if (map == NULL)
		panic("no memory for file dump list\n");
	dumpmap = map;
	curfile.action = USING;
	getfile(xtrmap, xtrmapskip);
	/*
	 * If there may be whiteout entries on the tape, pretend that the
	 * whiteout inode exists, so that the whiteout entries can be
	 * extracted.
	 */
	if (oldinofmt == 0)
		SETINO(WINO, dumpmap);
	/* 'r' restores don't call getvol() for tape 1, so mark it as read. */
	if (command == 'r')
		tapesread = 1;
}