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

📄 ar.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(strcmp(p->name, name) == 0)			return 1;	p = (Hashchain*) armalloc(sizeof(Hashchain));	p->next = hash[h];	p->name = name;	hash[h] = p;	return 0;}/* *	open an archive and validate its header */intopenar(char *arname, int mode, int errok){	int fd;	char mbuf[SARMAG];	fd = open(arname, mode);	if(fd >= 0){		if(read(fd, mbuf, SARMAG) != SARMAG || strncmp(mbuf, ARMAG, SARMAG)) {			fprint(2, "ar: %s not in archive format\n", arname);			exits("error");		}	}else if(!errok){		fprint(2, "ar: cannot open %s: %r\n", arname);		exits("error");	}	return fd;}/* *	create an archive and set its header */intarcreate(char *arname){	int fd;	fd = create(arname, OWRITE, 0664);	if(fd < 0){		fprint(2, "ar: cannot create %s: %r\n", arname);		exits("error");	}	if(write(fd, ARMAG, SARMAG) != SARMAG)		wrerr();	return fd;}/* *		error handling */voidwrerr(void){	perror("ar: write error");	exits("error");}voidrderr(void){	perror("ar: read error");	exits("error");}voidphaseerr(int offset){	fprint(2, "ar: phase error at offset %d\n", offset);	exits("error");}voidusage(void){	fprint(2, "usage: ar [%s][%s] archive files ...\n", opt, man);	exits("error");}/* *	read the header for the next archive member */Armember *getdir(Biobuf *b){	Armember *bp;	char *cp;	static char name[ARNAMESIZE+1];	bp = newmember();	if(HEADER_IO(Bread, b, bp->hdr)) {		free(bp);		return 0;	}	if(strncmp(bp->hdr.fmag, ARFMAG, sizeof(bp->hdr.fmag)))		phaseerr(Boffset(b));	strncpy(name, bp->hdr.name, sizeof(bp->hdr.name));	cp = name+sizeof(name)-1;	while(*--cp==' ')		;	cp[1] = '\0';	file = name;	bp->date = strtol(bp->hdr.date, 0, 0);	bp->size = strtol(bp->hdr.size, 0, 0);	return bp;}/* *	Copy the file referenced by fd to the temp file */voidarmove(Biobuf *b, Arfile *ap, Armember *bp){	char *cp;	Dir *d;	d = dirfstat(Bfildes(b));	if (d == nil) {		fprint(2, "ar: cannot stat %s\n", file);		return;	}	trim(file, bp->hdr.name, sizeof(bp->hdr.name));	for (cp = strchr(bp->hdr.name, 0);		/* blank pad on right */		cp < bp->hdr.name+sizeof(bp->hdr.name); cp++)			*cp = ' ';	sprint(bp->hdr.date, "%-12ld", d->mtime);	sprint(bp->hdr.uid, "%-6d", 0);	sprint(bp->hdr.gid, "%-6d", 0);	sprint(bp->hdr.mode, "%-8lo", d->mode);	sprint(bp->hdr.size, "%-10lld", d->length);	strncpy(bp->hdr.fmag, ARFMAG, 2);	bp->size = d->length;	arread(b, bp, bp->size);	if (d->length&0x01)		d->length++;	if (ap) {		arinsert(ap, bp);		ap->size += d->length+SAR_HDR;	}	free(d);}/* *	Copy the archive member at the current offset into the temp file. */voidarcopy(Biobuf *b, Arfile *ap, Armember *bp){	long n;	n = bp->size;	if (n & 01)		n++;	arread(b, bp, n);	if (ap) {		arinsert(ap, bp);		ap->size += n+SAR_HDR;	}}/* *	Skip an archive member */voidskip(Biobuf *bp, vlong len){	if (len & 01)		len++;	Bseek(bp, len, 1);}/* *	Stream the three temp files to an archive */voidinstall(char *arname, Arfile *astart, Arfile *amiddle, Arfile *aend, int createflag){	int fd;	if(allobj && dupfound) {		fprint(2, "%s not changed\n", arname);		return;	}	/* leave note group behind when copying back; i.e. sidestep interrupts */	rfork(RFNOTEG);	if(createflag)		fprint(2, "ar: creating %s\n", arname);	fd = arcreate(arname);	if(allobj)		rl(fd);	if (astart) {		arstream(fd, astart);		arfree(astart);	}	if (amiddle) {		arstream(fd, amiddle);		arfree(amiddle);	}	if (aend) {		arstream(fd, aend);		arfree(aend);	}	close(fd);}voidrl(int fd){	Biobuf b;	char *cp;	struct ar_hdr a;	long len;	Binit(&b, fd, OWRITE);	Bseek(&b,seek(fd,0,1), 0);	len = symdefsize;	if(len&01)		len++;	sprint(a.date, "%-12ld", time(0));	sprint(a.uid, "%-6d", 0);	sprint(a.gid, "%-6d", 0);	sprint(a.mode, "%-8lo", 0644L);	sprint(a.size, "%-10ld", len);	strncpy(a.fmag, ARFMAG, 2);	strcpy(a.name, symdef);	for (cp = strchr(a.name, 0);		/* blank pad on right */		cp < a.name+sizeof(a.name); cp++)			*cp = ' ';	if(HEADER_IO(Bwrite, &b, a))			wrerr();	len += Boffset(&b);	if (astart) {		wrsym(&b, len, astart->sym);		len += astart->size;	}	if(amiddle) {		wrsym(&b, len, amiddle->sym);		len += amiddle->size;	}	if(aend)		wrsym(&b, len, aend->sym);	if(symdefsize&0x01)		Bputc(&b, 0);	Bterm(&b);}/* *	Write the defined symbols to the symdef file */voidwrsym(Biobuf *bp, long offset, Arsymref *as){	int off;	while(as) {		Bputc(bp, as->type);		off = as->offset+offset;		Bputc(bp, off);		Bputc(bp, off>>8);		Bputc(bp, off>>16);		Bputc(bp, off>>24);		if (Bwrite(bp, as->name, as->len+1) != as->len+1)			wrerr();		as = as->next;	}}/* *	Check if the archive member matches an entry on the command line. */intmatch(int count, char **files){	int i;	char name[ARNAMESIZE+1];	for(i=0; i<count; i++) {		if(files[i] == 0)			continue;		trim(files[i], name, ARNAMESIZE);		if(strncmp(name, file, ARNAMESIZE) == 0) {			file = files[i];			files[i] = 0;			return 1;		}	}	return 0;}/* *	compare the current member to the name of the pivot member */intbamatch(char *file, char *pivot){	static int state = 0;	switch(state)	{	case 0:			/* looking for position file */		if (aflag) {			if (strncmp(file, pivot, ARNAMESIZE) == 0)				state = 1;		} else if (bflag) {			if (strncmp(file, pivot, ARNAMESIZE) == 0) {				state = 2;	/* found */				return 1;			}		}		break;	case 1:			/* found - after previous file */		state = 2;		return 1;	case 2:			/* already found position file */		break;	}	return 0;}/* *	output a message, if 'v' option was specified */voidmesg(int c, char *file){	if(vflag)		Bprint(&bout, "%c - %s\n", c, file);}/* *	isolate file name by stripping leading directories and trailing slashes */voidtrim(char *s, char *buf, int n){	char *p;	for(;;) {		p = strrchr(s, '/');		if (!p) {		/* no slash in name */			strncpy(buf, s, n);			return;		}		if (p[1] != 0) {	/* p+1 is first char of file name */			strncpy(buf, p+1, n);			return;		}		*p = 0;			/* strip trailing slash */	}}/* *	utilities for printing long form of 't' command */#define	SUID	04000#define	SGID	02000#define	ROWN	0400#define	WOWN	0200#define	XOWN	0100#define	RGRP	040#define	WGRP	020#define	XGRP	010#define	ROTH	04#define	WOTH	02#define	XOTH	01#define	STXT	01000voidlongt(Armember *bp){	char *cp;	pmode(strtoul(bp->hdr.mode, 0, 8));	Bprint(&bout, "%3ld/%1ld", strtol(bp->hdr.uid, 0, 0), strtol(bp->hdr.gid, 0, 0));	Bprint(&bout, "%7ld", bp->size);	cp = ctime(bp->date);	Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);}int	m1[] = { 1, ROWN, 'r', '-' };int	m2[] = { 1, WOWN, 'w', '-' };int	m3[] = { 2, SUID, 's', XOWN, 'x', '-' };int	m4[] = { 1, RGRP, 'r', '-' };int	m5[] = { 1, WGRP, 'w', '-' };int	m6[] = { 2, SGID, 's', XGRP, 'x', '-' };int	m7[] = { 1, ROTH, 'r', '-' };int	m8[] = { 1, WOTH, 'w', '-' };int	m9[] = { 2, STXT, 't', XOTH, 'x', '-' };int	*m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9};voidpmode(long mode){	int **mp;	for(mp = &m[0]; mp < &m[9];)		select(*mp++, mode);}voidselect(int *ap, long mode){	int n;	n = *ap++;	while(--n>=0 && (mode&*ap++)==0)		ap++;	Bputc(&bout, *ap);}/* *	Temp file I/O subsystem.  We attempt to cache all three temp files in *	core.  When we run out of memory we spill to disk. *	The I/O model assumes that temp files: *		1) are only written on the end *		2) are only read from the beginning *		3) are only read after all writing is complete. *	The architecture uses one control block per temp file.  Each control *	block anchors a chain of buffers, each containing an archive member. */Arfile *newtempfile(char *name)		/* allocate a file control block */{	Arfile *ap;	ap = (Arfile *) armalloc(sizeof(Arfile));	ap->fname = name;	return ap;}Armember *newmember(void)			/* allocate a member buffer */{	return (Armember *)armalloc(sizeof(Armember));}voidarread(Biobuf *b, Armember *bp, int n)	/* read an image into a member buffer */{	int i;	bp->member = armalloc(n);	i = Bread(b, bp->member, n);	if (i < 0) {		free(bp->member);		bp->member = 0;		rderr();	}}/* * insert a member buffer into the member chain */voidarinsert(Arfile *ap, Armember *bp){	bp->next = 0;	if (!ap->tail)		ap->head = bp;	else		ap->tail->next = bp;	ap->tail = bp;}/* *	stream the members in a temp file to the file referenced by 'fd'. */voidarstream(int fd, Arfile *ap){	Armember *bp;	int i;	char buf[8192];	if (ap->paged) {		/* copy from disk */		seek(ap->fd, 0, 0);		for (;;) {			i = read(ap->fd, buf, sizeof(buf));			if (i < 0)				rderr();			if (i == 0)				break;			if (write(fd, buf, i) != i)				wrerr();		}		close(ap->fd);		ap->paged = 0;	}		/* dump the in-core buffers */	for (bp = ap->head; bp; bp = bp->next) {		if (!arwrite(fd, bp))			wrerr();	}}/* *	write a member to 'fd'. */intarwrite(int fd, Armember *bp){	int len;	if(HEADER_IO(write, fd, bp->hdr))		return 0;	len = bp->size;	if (len & 01)		len++;	if (write(fd, bp->member, len) != len)		return 0;	return 1;}/* *	Spill a member to a disk copy of a temp file */intpage(Arfile *ap){	Armember *bp;	bp = ap->head;	if (!ap->paged) {		/* not yet paged - create file */		ap->fname = mktemp(ap->fname);		ap->fd = create(ap->fname, ORDWR|ORCLOSE, 0600);		if (ap->fd < 0) {			fprint(2,"ar: can't create temp file\n");			return 0;		}		ap->paged = 1;	}	if (!arwrite(ap->fd, bp))	/* write member and free buffer block */		return 0;	ap->head = bp->next;	if (ap->tail == bp)		ap->tail = bp->next;	free(bp->member);	free(bp);	return 1;}/* *	try to reclaim space by paging.  we try to spill the start, middle, *	and end files, in that order.  there is no particular reason for the *	ordering. */intgetspace(void){	if (astart && astart->head && page(astart))			return 1;	if (amiddle && amiddle->head && page(amiddle))			return 1;	if (aend && aend->head && page(aend))			return 1;	return 0;}voidarfree(Arfile *ap)		/* free a member buffer */{	Armember *bp, *next;	for (bp = ap->head; bp; bp = next) {		next = bp->next;		if (bp->member)			free(bp->member);		free(bp);	}	free(ap);}/* *	allocate space for a control block or member buffer.  if the malloc *	fails we try to reclaim space by spilling previously allocated *	member buffers. */char *armalloc(int n){	char *cp;	do {		cp = malloc(n);		if (cp) {			memset(cp, 0, n);			return cp;		}	} while (getspace());	fprint(2, "ar: out of memory\n");	exits("malloc");	return 0;}

⌨️ 快捷键说明

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