⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar_io.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * Copyright (c) 1992 Keith Muller. * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Keith Muller of the University of California, San Diego. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)ar_io.c	8.2 (Berkeley) 4/18/94";#endif /* not lint */#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/mtio.h>#include <sys/param.h>#include <signal.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <ctype.h>#include <errno.h>#include <stdlib.h>#include "pax.h"#include "extern.h"/* * Routines which deal directly with the archive I/O device/file. */#define DMOD		0666		/* default mode of created archives */#define EXT_MODE	O_RDONLY	/* open mode for list/extract */#define AR_MODE		(O_WRONLY | O_CREAT | O_TRUNC)	/* mode for archive */#define APP_MODE	O_RDWR		/* mode for append */#define STDO		"<STDOUT>"	/* psuedo name for stdout */#define STDN		"<STDIN>"	/* psuedo name for stdin */static int arfd = -1;			/* archive file descriptor */static int artyp = ISREG;		/* archive type: file/FIFO/tape */static int arvol = 1;			/* archive volume number */static int lstrval = -1;		/* return value from last i/o */static int io_ok;			/* i/o worked on volume after resync */static int did_io;			/* did i/o ever occur on volume? */static int done;			/* set via tty termination */static struct stat arsb;		/* stat of archive device at open */static int invld_rec;			/* tape has out of spec record size */static int wr_trail = 1;		/* trailer was rewritten in append */static int can_unlnk = 0;		/* do we unlink null archives?  */char *arcname;                  	/* printable name of archive */static int get_phys __P((void));extern sigset_t s_mask;/* * ar_open() *	Opens the next archive volume. Determines the type of the device and *	sets up block sizes as required by the archive device and the format. *	Note: we may be called with name == NULL on the first open only. * Return: *	-1 on failure, 0 otherwise */#if __STDC__intar_open(char *name)#elseintar_open(name)	char *name;#endif{        struct mtget mb;	if (arfd != -1)		(void)close(arfd);	arfd = -1;	can_unlnk = did_io = io_ok = invld_rec = 0;	artyp = ISREG;	flcnt = 0;	/*	 * 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);		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;		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);	/*	 * 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)) {		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))		artyp = ioctl(arfd, MTIOCGET, &mb) ? ISCHR : ISTAPE;	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;	/*	 * 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 to 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 cannont 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, worse case, slow... 		 */		blksz = rdblksz = BLKMULT;		break;	}	lstrval = 1;	return(0);}/* * ar_close() *	closes archive device, increments volume number, and prints i/o summary */#if __STDC__voidar_close(void)#elsevoidar_close()#endif{	FILE *outf;	if (arfd < 0) {		did_io = io_ok = flcnt = 0;		return;	}	if (act == LIST)		outf = stdout;	else		outf = stderr;	/*	 * Close archive file. This may take a LONG while on tapes (we may be	 * forced to wait for the rewind to complete) so tell the user what is	 * going on (this avoids the user hitting control-c thinking pax is	 * broken).	 */	if (vflag && (artyp == ISTAPE)) {		if (vfpart)			(void)putc('\n', outf);		(void)fprintf(outf,			"%s: Waiting for tape drive close to complete...",			argv0);		(void)fflush(outf);	}	/*	 * if nothing was written to the archive (and we created it), we remove	 * it	 */	if (can_unlnk && (fstat(arfd, &arsb) == 0) && (S_ISREG(arsb.st_mode)) &&	    (arsb.st_size == 0)) {		(void)unlink(arcname);		can_unlnk = 0;	}	(void)close(arfd);	if (vflag && (artyp == ISTAPE)) {		(void)fputs("done.\n", outf);		vfpart = 0;		(void)fflush(outf);	}	arfd = -1;	if (!io_ok && !did_io) {		flcnt = 0;		return;	}	did_io = io_ok = 0;	/*	 * The volume number is only increased when the last device has data	 * and we have already determined the archive format.	 */	if (frmt != NULL)		++arvol;	if (!vflag) {		flcnt = 0;		return;	}	/*	 * Print out a summary of I/O for this archive volume.	 */	if (vfpart) {		(void)putc('\n', outf);		vfpart = 0;	}	/*	 * If we have not determined the format yet, we just say how many bytes	 * we have skipped over looking for a header to id. there is no way we	 * could have written anything yet.	 */	if (frmt == NULL) {#	ifdef NET2_STAT		(void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n",#	else		(void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n",#	endif		    argv0, rdcnt);		(void)fflush(outf);		flcnt = 0;		return;	}	(void)fprintf(outf,#	ifdef NET2_STAT	    "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",#	else	    "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",#	endif	    argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);	(void)fflush(outf);	flcnt = 0;}/* * ar_drain() *	drain any archive format independent padding from an archive read *	from a socket or a pipe. This is to prevent the process on the *	other side of the pipe from getting a SIGPIPE (pax will stop *	reading an archive once a format dependent trailer is detected). */#if __STDC__voidar_drain(void)#elsevoidar_drain()#endif{	register int res;	char drbuf[MAXBLK];	/*	 * we only drain from a pipe/socket. Other devices can be closed	 * without reading up to end of file. We sure hope that pipe is closed	 * on the other side so we will get an EOF.	 */	if ((artyp != ISPIPE) || (lstrval <= 0))		return;	/*	 * keep reading until pipe is drained	 */	while ((res = read(arfd, drbuf, sizeof(drbuf))) > 0)		;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -