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

📄 tape.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Write out the next block of a file. */static voidxtrfile(buf, size)	char	*buf;	long	size;{	if (Nflag)		return;	if (write(ofile, buf, (int) size) == -1) {		fprintf(stderr,		    "write error extracting inode %d, name %s\nwrite: %s\n",			curfile.ino, curfile.name, strerror(errno));		done(1);	}}/* * Skip over a hole in a file. *//* ARGSUSED */static voidxtrskip(buf, size)	char *buf;	long size;{	if (lseek(ofile, size, SEEK_CUR) == -1) {		fprintf(stderr,		    "seek error extracting inode %d, name %s\nlseek: %s\n",			curfile.ino, curfile.name, strerror(errno));		done(1);	}}/* * Collect the next block of a symbolic link. */static voidxtrlnkfile(buf, size)	char	*buf;	long	size;{	pathlen += size;	if (pathlen > MAXPATHLEN) {		fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n",		    curfile.name, lnkbuf, buf, pathlen);		done(1);	}	(void) strcat(lnkbuf, buf);}/* * Skip over a hole in a symbolic link (should never happen). *//* ARGSUSED */static voidxtrlnkskip(buf, size)	char *buf;	long size;{	fprintf(stderr, "unallocated block in symbolic link %s\n",		curfile.name);	done(1);}/* * Collect the next block of a bit map. */static voidxtrmap(buf, size)	char	*buf;	long	size;{	bcopy(buf, map, size);	map += size;}/* * Skip over a hole in a bit map (should never happen). *//* ARGSUSED */static voidxtrmapskip(buf, size)	char *buf;	long size;{	panic("hole in map\n");	map += size;}/* * Noop, when an extraction function is not needed. *//* ARGSUSED */voidxtrnull(buf, size)	char *buf;	long size;{	return;}/* * Read TP_BSIZE blocks from the input. * Handle read errors, and end of media. */static voidreadtape(buf)	char *buf;{	long rd, newvol, i;	int cnt, seek_failed;	if (blkcnt < numtrec) {		bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);		blksread++;		tpblksread++;		return;	}	for (i = 0; i < ntrec; i++)		((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;	if (numtrec == 0)		numtrec = ntrec;	cnt = ntrec * TP_BSIZE;	rd = 0;getmore:#ifdef RRESTORE	if (host)		i = rmtread(&tapebuf[rd], cnt);	else#endif		i = read(mt, &tapebuf[rd], cnt);	/*	 * Check for mid-tape short read error.	 * If found, skip rest of buffer and start with the next.	 */	if (!pipein && numtrec < ntrec && i > 0) {		dprintf(stdout, "mid-media short read error.\n");		numtrec = ntrec;	}	/*	 * Handle partial block read.	 */	if (pipein && i == 0 && rd > 0)		i = rd;	else if (i > 0 && i != ntrec * TP_BSIZE) {		if (pipein) {			rd += i;			cnt -= i;			if (cnt > 0)				goto getmore;			i = rd;		} else {			/*			 * Short read. Process the blocks read.			 */			if (i % TP_BSIZE != 0)				vprintf(stdout,				    "partial block read: %d should be %d\n",				    i, ntrec * TP_BSIZE);			numtrec = i / TP_BSIZE;		}	}	/*	 * Handle read error.	 */	if (i < 0) {		fprintf(stderr, "Tape read error while ");		switch (curfile.action) {		default:			fprintf(stderr, "trying to set up tape\n");			break;		case UNKNOWN:			fprintf(stderr, "trying to resynchronize\n");			break;		case USING:			fprintf(stderr, "restoring %s\n", curfile.name);			break;		case SKIP:			fprintf(stderr, "skipping over inode %d\n",				curfile.ino);			break;		}		if (!yflag && !reply("continue"))			done(1);		i = ntrec * TP_BSIZE;		bzero(tapebuf, i);#ifdef RRESTORE		if (host)			seek_failed = (rmtseek(i, 1) < 0);		else#endif			seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1);		if (seek_failed) {			fprintf(stderr,			    "continuation failed: %s\n", strerror(errno));			done(1);		}	}	/*	 * Handle end of tape.	 */	if (i == 0) {		vprintf(stdout, "End-of-tape encountered\n");		if (!pipein) {			newvol = volno + 1;			volno = 0;			numtrec = 0;			getvol(newvol);			readtape(buf);			return;		}		if (rd % TP_BSIZE != 0)			panic("partial block read: %d should be %d\n",				rd, ntrec * TP_BSIZE);		terminateinput();		bcopy((char *)&endoftapemark, &tapebuf[rd], (long)TP_BSIZE);	}	blkcnt = 0;	bcopy(&tapebuf[(blkcnt++ * TP_BSIZE)], buf, (long)TP_BSIZE);	blksread++;	tpblksread++;}static voidfindtapeblksize(){	register long i;	for (i = 0; i < ntrec; i++)		((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;	blkcnt = 0;#ifdef RRESTORE	if (host)		i = rmtread(tapebuf, ntrec * TP_BSIZE);	else#endif		i = read(mt, tapebuf, ntrec * TP_BSIZE);	if (i <= 0) {		fprintf(stderr, "tape read error: %s\n", strerror(errno));		done(1);	}	if (i % TP_BSIZE != 0) {		fprintf(stderr, "Tape block size (%d) %s (%d)\n",			i, "is not a multiple of dump block size", TP_BSIZE);		done(1);	}	ntrec = i / TP_BSIZE;	numtrec = ntrec;	vprintf(stdout, "Tape block size is %d\n", ntrec);}voidclosemt(){	if (mt < 0)		return;#ifdef RRESTORE	if (host)		rmtclose();	else#endif		(void) close(mt);}/* * Read the next block from the tape. * Check to see if it is one of several vintage headers. * If it is an old style header, convert it to a new style header. * If it is not any valid header, return an error. */static intgethead(buf)	struct s_spcl *buf;{	long i;	union {		quad_t	qval;		long	val[2];	} qcvt;	union u_ospcl {		char dummy[TP_BSIZE];		struct	s_ospcl {			long	c_type;			long	c_date;			long	c_ddate;			long	c_volume;			long	c_tapea;			u_short	c_inumber;			long	c_magic;			long	c_checksum;			struct odinode {				unsigned short odi_mode;				u_short	odi_nlink;				u_short	odi_uid;				u_short	odi_gid;				long	odi_size;				long	odi_rdev;				char	odi_addr[36];				long	odi_atime;				long	odi_mtime;				long	odi_ctime;			} c_dinode;			long	c_count;			char	c_addr[256];		} s_ospcl;	} u_ospcl;	if (!cvtflag) {		readtape((char *)buf);		if (buf->c_magic != NFS_MAGIC) {			if (swabl(buf->c_magic) != NFS_MAGIC)				return (FAIL);			if (!Bcvt) {				vprintf(stdout, "Note: Doing Byte swapping\n");				Bcvt = 1;			}		}		if (checksum((int *)buf) == FAIL)			return (FAIL);		if (Bcvt)			swabst((u_char *)"8l4s31l", (u_char *)buf);		goto good;	}	readtape((char *)(&u_ospcl.s_ospcl));	bzero((char *)buf, (long)TP_BSIZE);	buf->c_type = u_ospcl.s_ospcl.c_type;	buf->c_date = u_ospcl.s_ospcl.c_date;	buf->c_ddate = u_ospcl.s_ospcl.c_ddate;	buf->c_volume = u_ospcl.s_ospcl.c_volume;	buf->c_tapea = u_ospcl.s_ospcl.c_tapea;	buf->c_inumber = u_ospcl.s_ospcl.c_inumber;	buf->c_checksum = u_ospcl.s_ospcl.c_checksum;	buf->c_magic = u_ospcl.s_ospcl.c_magic;	buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;	buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;	buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;	buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;	buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;	buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;	buf->c_dinode.di_atime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_atime;	buf->c_dinode.di_mtime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_mtime;	buf->c_dinode.di_ctime.ts_sec = u_ospcl.s_ospcl.c_dinode.odi_ctime;	buf->c_count = u_ospcl.s_ospcl.c_count;	bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256);	if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||	    checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)		return(FAIL);	buf->c_magic = NFS_MAGIC;good:	if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) &&	    (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) {		qcvt.qval = buf->c_dinode.di_size;		if (qcvt.val[0] || qcvt.val[1]) {			printf("Note: Doing Quad swapping\n");			Qcvt = 1;		}	}	if (Qcvt) {		qcvt.qval = buf->c_dinode.di_size;		i = qcvt.val[1];		qcvt.val[1] = qcvt.val[0];		qcvt.val[0] = i;		buf->c_dinode.di_size = qcvt.qval;	}	switch (buf->c_type) {	case TS_CLRI:	case TS_BITS:		/*		 * Have to patch up missing information in bit map headers		 */		buf->c_inumber = 0;		buf->c_dinode.di_size = buf->c_count * TP_BSIZE;		for (i = 0; i < buf->c_count; i++)			buf->c_addr[i]++;		break;	case TS_TAPE:		if ((buf->c_flags & DR_NEWINODEFMT) == 0)			oldinofmt = 1;		/* fall through */	case TS_END:		buf->c_inumber = 0;		break;	case TS_INODE:	case TS_ADDR:		break;	default:		panic("gethead: unknown inode type %d\n", buf->c_type);		break;	}	/*	 * If we are restoring a filesystem with old format inodes, 	 * copy the uid/gid to the new location.	 */	if (oldinofmt) {		buf->c_dinode.di_uid = buf->c_dinode.di_ouid;		buf->c_dinode.di_gid = buf->c_dinode.di_ogid;	}	if (dflag)		accthdr(buf);	return(GOOD);}/* * Check that a header is where it belongs and predict the next header */static voidaccthdr(header)	struct s_spcl *header;{	static ino_t previno = 0x7fffffff;	static int prevtype;	static long predict;	long blks, i;	if (header->c_type == TS_TAPE) {		fprintf(stderr, "Volume header (%s inode format) ",		    oldinofmt ? "old" : "new"); 		if (header->c_firstrec) 			fprintf(stderr, "begins with record %d", 				header->c_firstrec); 		fprintf(stderr, "\n");		previno = 0x7fffffff;		return;	}	if (previno == 0x7fffffff)		goto newcalc;	switch (prevtype) {	case TS_BITS:		fprintf(stderr, "Dump mask header");		break;	case TS_CLRI:		fprintf(stderr, "Remove mask header");		break;	case TS_INODE:		fprintf(stderr, "File header, ino %d", previno);		break;	case TS_ADDR:		fprintf(stderr, "File continuation header, ino %d", previno);		break;	case TS_END:		fprintf(stderr, "End of tape header");		break;	}	if (predict != blksread - 1)		fprintf(stderr, "; predicted %d blocks, got %d blocks",			predict, blksread - 1);	fprintf(stderr, "\n");newcalc:	blks = 0;	if (header->c_type != TS_END)		for (i = 0; i < header->c_count; i++)			if (header->c_addr[i] != 0)				blks++;	predict = blks;	blksread = 0;	prevtype = header->c_type;	previno = header->c_inumber;}/* * Find an inode header. * Complain if had to skip, and complain is set. */static voidfindinode(header)	struct s_spcl *header;{	static long skipcnt = 0;	long i;	char buf[TP_BSIZE];	curfile.name = "<name unknown>";	curfile.action = UNKNOWN;	curfile.dip = NULL;	curfile.ino = 0;	do {		if (header->c_magic != NFS_MAGIC) {			skipcnt++;			while (gethead(header) == FAIL ||			    header->c_date != dumpdate)				skipcnt++;		}		switch (header->c_type) {		case TS_ADDR:			/*			 * Skip up to the beginning of the next record			 */			for (i = 0; i < header->c_count; i++)				if (header->c_addr[i])					readtape(buf);			while (gethead(header) == FAIL ||			    header->c_date != dumpdate)				skipcnt++;			break;		case TS_INODE:			curfile.dip = &header->c_dinode;			curfile.ino = header->c_inumber;			break;		case TS_END:			curfile.ino = maxino;			break;		case TS_CLRI:			curfile.name = "<file removal list>";			break;		case TS_BITS:			curfile.name = "<file dump list>";			break;		case TS_TAPE:			panic("unexpected tape header\n");			/* NOTREACHED */		default:			panic("unknown tape header type %d\n", spcl.c_type);			/* NOTREACHED */		}	} while (header->c_type == TS_ADDR);	if (skipcnt > 0)		fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);	skipcnt = 0;}static intchecksum(buf)	register int *buf;{	register int i, j;	j = sizeof(union u_spcl) / sizeof(int);	i = 0;	if(!Bcvt) {		do			i += *buf++;		while (--j);	} else {		/* What happens if we want to read restore tapes			for a 16bit int machine??? */		do 			i += swabl(*buf++);		while (--j);	}				if (i != CHECKSUM) {		fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,			curfile.ino, curfile.name);		return(FAIL);	}	return(GOOD);}#ifdef RRESTORE#if __STDC__#include <stdarg.h>#else#include <varargs.h>#endifvoid#if __STDC__msg(const char *fmt, ...)#elsemsg(fmt, va_alist)	char *fmt;	va_dcl#endif{	va_list ap;#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	(void)vfprintf(stderr, fmt, ap);	va_end(ap);}#endif /* RRESTORE */static u_char *swabshort(sp, n)	register u_char *sp;	register int n;{	char c;	while (--n >= 0) {		c = sp[0]; sp[0] = sp[1]; sp[1] = c;		sp += 2;	}	return (sp);}static u_char *swablong(sp, n)	register u_char *sp;	register int n;{	char c;	while (--n >= 0) {		c = sp[0]; sp[0] = sp[3]; sp[3] = c;		c = sp[2]; sp[2] = sp[1]; sp[1] = c;		sp += 4;	}	return (sp);}voidswabst(cp, sp)	register u_char *cp, *sp;{	int n = 0;	while (*cp) {		switch (*cp) {		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':			n = (n * 10) + (*cp++ - '0');			continue;				case 's': case 'w': case 'h':			if (n == 0)				n = 1;			sp = swabshort(sp, n);			break;		case 'l':			if (n == 0)				n = 1;			sp = swablong(sp, n);			break;		default: /* Any other character, like 'b' counts as byte. */			if (n == 0)				n = 1;			sp += n;			break;		}		cp++;		n = 0;	}}static u_longswabl(x)	u_long x;{	swabst((u_char *)"l", (u_char *)&x);	return (x);}

⌨️ 快捷键说明

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