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

📄 ar_io.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * deal with the end of file (it will go to next volume by		 * itself)	 	 */		if ((mpos = cpos + sksz) > arsb.st_size) {			*skipped = arsb.st_size - cpos;			mpos = arsb.st_size;		} else			*skipped = sksz;		if (lseek(arfd, mpos, SEEK_SET) >= 0)			return(0);	}	syswarn(1, errno, "Foward positioning operation on archive failed");	lstrval = -1;	return(-1);}/* * ar_rev() *	move the i/o position within the archive backwards the specified byte *	count as supported by the device. With tapes drives we RESET rdblksz to *	the PHYSICAL blocksize. *	NOTE: We should only be called to move backwards so we can rewrite the *	last records (the trailer) of an archive (APPEND). * Return: *	0 if moved the requested distance, -1 on complete failure */#if __STDC__intar_rev(off_t sksz)#elseintar_rev(sksz)	off_t sksz;#endif{	off_t cpos;        struct mtop mb;	register int phyblk; 	/*	 * make sure we do not have try to reverse on a flawed archive	 */	if (lstrval < 0)		return(lstrval);	switch(artyp) {	case ISPIPE:		if (sksz <= 0) 			break;		/*		 * cannot go backwards on these critters		 */		warn(1, "Reverse positioning on pipes is not supported.");		lstrval = -1;		return(-1);	case ISREG:	case ISBLK:	case ISCHR:	default:		if (sksz <= 0)			break;		/*		 * For things other than files, backwards movement has a very		 * high probability of failure as we really do not know the		 * true attributes of the device we are talking to (the device		 * may not even have the ability to lseek() in any direction).		 * First we figure out where we are in the archive.		 */		if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0) {			syswarn(1, errno,			   "Unable to obtain current archive byte offset");			lstrval = -1;			return(-1);		}		/*		 * we may try to go backwards past the start when the archive		 * is only a single record. If this hapens and we are on a		 * multi volume archive, we need to go to the end of the		 * previous volume and continue our movement backwards from		 * there.		 */		if ((cpos -= sksz) < (off_t)0L) {			if (arvol > 1) {				/*				 * this should never happen				 */				warn(1,"Reverse position on previous volume.");				lstrval = -1;				return(-1);			}			cpos = (off_t)0L;		}		if (lseek(arfd, cpos, SEEK_SET) < 0) {			syswarn(1, errno, "Unable to seek archive backwards");			lstrval = -1;			return(-1);		}		break;	case ISTAPE:		/*	 	 * Calculate and move the proper number of PHYSICAL tape		 * blocks. If the sksz is not an even multiple of the physical		 * tape size, we cannot do the move (this should never happen).		 * (We also cannot handler trailers spread over two vols).		 * get_phys() also makes sure we are in front of the filemark.	 	 */		if ((phyblk = get_phys()) <= 0) {			lstrval = -1;			return(-1);		}		/*		 * make sure future tape reads only go by physical tape block		 * size (set rdblksz to the real size).		 */		rdblksz = phyblk;		/*		 * if no movement is required, just return (we must be after		 * get_phys() so the physical blocksize is properly set)		 */		if (sksz <= 0)			break;		/*		 * ok we have to move. Make sure the tape drive can do it.		 */		if (sksz % phyblk) {			warn(1,			    "Tape drive unable to backspace requested amount");			lstrval = -1;			return(-1);		}		/*		 * move backwards the requested number of bytes		 */		mb.mt_op = MTBSR;		mb.mt_count = sksz/phyblk;		if (ioctl(arfd, MTIOCTOP, &mb) < 0) {			syswarn(1,errno, "Unable to backspace tape %d blocks.",			    mb.mt_count);			lstrval = -1;			return(-1);		}		break;	}	lstrval = 1;	return(0);}/* * get_phys() *	Determine the physical block size on a tape drive. We need the physical *	block size so we know how many bytes we skip over when we move with  *	mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when *	return. *	This is one really SLOW routine... * Return: *	physical block size if ok (ok > 0), -1 otherwise */#if __STDC__static intget_phys(void)#elsestatic intget_phys()#endif{	register int padsz = 0;	register int res;	register int phyblk;	struct mtop mb;	char scbuf[MAXBLK];	/*	 * move to the file mark, and then back up one record and read it.	 * this should tell us the physical record size the tape is using.	 */	if (lstrval == 1) {		/*		 * we know we are at file mark when we get back a 0 from		 * read()		 */		while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)			padsz += res;		if (res < 0) {			syswarn(1, errno, "Unable to locate tape filemark.");			return(-1);		}	}	/*	 * move backwards over the file mark so we are at the end of the	 * last record.	 */	mb.mt_op = MTBSF;	mb.mt_count = 1;	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {		syswarn(1, errno, "Unable to backspace over tape filemark.");		return(-1);	}	/*	 * move backwards so we are in front of the last record and read it to	 * get physical tape blocksize.	 */	mb.mt_op = MTBSR;	mb.mt_count = 1;	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {		syswarn(1, errno, "Unable to backspace over last tape block.");		return(-1);	}	if ((phyblk = read(arfd, scbuf, sizeof(scbuf))) <= 0) {		syswarn(1, errno, "Cannot determine archive tape blocksize.");		return(-1);	}	/*	 * read foward to the file mark, then back up in front of the filemark	 * (this is a bit paranoid, but should be safe to do).	 */	while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)		;	if (res < 0) {		syswarn(1, errno, "Unable to locate tape filemark.");		return(-1);	}	mb.mt_op = MTBSF;	mb.mt_count = 1;	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {		syswarn(1, errno, "Unable to backspace over tape filemark.");		return(-1);	}	/*	 * set lstrval so we know that the filemark has not been seen	 */	lstrval = 1;	/*	 * return if there was no padding	 */	if (padsz == 0)		return(phyblk);	/*	 * make sure we can move backwards over the padding. (this should	 * never fail).	 */	if (padsz % phyblk) {		warn(1, "Tape drive unable to backspace requested amount");		return(-1);	}	/*	 * move backwards over the padding so the head is where it was when	 * we were first called (if required).	 */	mb.mt_op = MTBSR;	mb.mt_count = padsz/phyblk;	if (ioctl(arfd, MTIOCTOP, &mb) < 0) {		syswarn(1,errno,"Unable to backspace tape over %d pad blocks",		    mb.mt_count);		return(-1);	}	return(phyblk);}/* * ar_next() *	prompts the user for the next volume in this archive. For some devices *	we may allow the media to be changed. Otherwise a new archive is *	prompted for. By pax spec, if there is no controlling tty or an eof is *	read on tty input, we must quit pax. * Return: *	0 when ready to continue, -1 when all done */#if __STDC__intar_next(void)#elseintar_next()#endif{	char buf[PAXPATHLEN+2];	static int freeit = 0;	sigset_t o_mask;	/*	 * WE MUST CLOSE THE DEVICE. A lot of devices must see last close, (so	 * things like writing EOF etc will be done) (Watch out ar_close() can	 * also be called via a signal handler, so we must prevent a race.	 */	if (sigprocmask(SIG_BLOCK, &s_mask, &o_mask) < 0)		syswarn(0, errno, "Unable to set signal mask");	ar_close();	if (sigprocmask(SIG_SETMASK, &o_mask, (sigset_t *)NULL) < 0)		syswarn(0, errno, "Unable to restore signal mask");	if (done || !wr_trail)		return(-1);	tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);	/*	 * if i/o is on stdin or stdout, we cannot reopen it (we do not know	 * the name), the user will be forced to type it in.	 */	if (strcmp(arcname, STDO) && strcmp(arcname, STDN) && (artyp != ISREG)	    && (artyp != ISPIPE)) {		if (artyp == ISTAPE) {			tty_prnt("%s ready for archive tape volume: %d\n",				arcname, arvol);			tty_prnt("Load the NEXT TAPE on the tape drive");		} else {			tty_prnt("%s ready for archive volume: %d\n",				arcname, arvol);			tty_prnt("Load the NEXT STORAGE MEDIA (if required)");		}		if ((act == ARCHIVE) || (act == APPND))			tty_prnt(" and make sure it is WRITE ENABLED.\n");		else			tty_prnt("\n");		for(;;) {			tty_prnt("Type \"y\" to continue, \".\" to quit %s,",				argv0);			tty_prnt(" or \"s\" to switch to new device.\nIf you");			tty_prnt(" cannot change storage media, type \"s\"\n");			tty_prnt("Is the device ready and online? > ");			if ((tty_read(buf,sizeof(buf))<0) || !strcmp(buf,".")){				done = 1;				lstrval = -1;				tty_prnt("Quitting %s!\n", argv0);				vfpart = 0;				return(-1);			}			if ((buf[0] == '\0') || (buf[1] != '\0')) {				tty_prnt("%s unknown command, try again\n",buf);				continue;			}			switch (buf[0]) {			case 'y':			case 'Y':				/*				 * we are to continue with the same device				 */				if (ar_open(arcname) >= 0) 					return(0);				tty_prnt("Cannot re-open %s, try again\n",					arcname);				continue;			case 's':			case 'S':				/*				 * user wants to open a different device				 */				tty_prnt("Switching to a different archive\n");				break;			default:				tty_prnt("%s unknown command, try again\n",buf);				continue;			}			break;		}	} else		tty_prnt("Ready for archive volume: %d\n", arvol);	/*	 * have to go to a different archive	 */	for (;;) {		tty_prnt("Input archive name or \".\" to quit %s.\n", argv0);		tty_prnt("Archive name > ");		if ((tty_read(buf, sizeof(buf)) < 0) || !strcmp(buf, ".")) {			done = 1;			lstrval = -1;			tty_prnt("Quitting %s!\n", argv0);			vfpart = 0;			return(-1);		}		if (buf[0] == '\0') {			tty_prnt("Empty file name, try again\n");			continue;		}                if (!strcmp(buf, "..")) {                        tty_prnt("Illegal file name: .. try again\n");                        continue;                }		if (strlen(buf) > PAXPATHLEN) {			tty_prnt("File name too long, try again\n");			continue;		}		/*		 * try to open new archive		 */		if (ar_open(buf) >= 0) {			if (freeit) {				(void)free(arcname);				freeit = 0;			}			if ((arcname = strdup(buf)) == NULL) {				done = 1;				lstrval = -1;				warn(0, "Cannot save archive name.");				return(-1);			}			freeit = 1;			break;		}		tty_prnt("Cannot open %s, try again\n", buf);		continue;	}	return(0);}

⌨️ 快捷键说明

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