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

📄 ar.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ar - portable (ascii) format version */#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#include <ar.h>/* *	The algorithm uses up to 3 temp files.  The "pivot member" is the *	archive member specified by and a, b, or i option.  The temp files are *	astart - contains existing members up to and including the pivot member. *	amiddle - contains new files moved or inserted behind the pivot. *	aend - contains the existing members that follow the pivot member. *	When all members have been processed, function 'install' streams the * 	temp files, in order, back into the archive. */typedef struct	Arsymref{	char	*name;	int	type;	int	len;	vlong	offset;	struct	Arsymref *next;} Arsymref;typedef struct	Armember	/* Temp file entry - one per archive member */{	struct Armember	*next;	struct ar_hdr	hdr;	long		size;	long		date;	void		*member;} Armember;typedef	struct Arfile		/* Temp file control block - one per tempfile */{	int	paged;		/* set when some data paged to disk */	char	*fname;		/* paging file name */	int	fd;		/* paging file descriptor */	vlong	size;	Armember *head;		/* head of member chain */	Armember *tail;		/* tail of member chain */	Arsymref *sym;		/* head of defined symbol chain */} Arfile;typedef struct Hashchain{	char	*name;	struct Hashchain *next;} Hashchain;#define	NHASH	1024/* *	macro to portably read/write archive header. *	'cmd' is read/write/Bread/Bwrite, etc. */#define	HEADER_IO(cmd, f, h)	cmd(f, h.name, sizeof(h.name)) != sizeof(h.name)\				|| cmd(f, h.date, sizeof(h.date)) != sizeof(h.date)\				|| cmd(f, h.uid, sizeof(h.uid)) != sizeof(h.uid)\				|| cmd(f, h.gid, sizeof(h.gid)) != sizeof(h.gid)\				|| cmd(f, h.mode, sizeof(h.mode)) != sizeof(h.mode)\				|| cmd(f, h.size, sizeof(h.size)) != sizeof(h.size)\				|| cmd(f, h.fmag, sizeof(h.fmag)) != sizeof(h.fmag)		/* constants and flags */char	*man =		"mrxtdpq";char	*opt =		"uvnbailo";char	artemp[] =	"/tmp/vXXXXX";char	movtemp[] =	"/tmp/v1XXXXX";char	tailtemp[] =	"/tmp/v2XXXXX";char	symdef[] =	"__.SYMDEF";int	aflag;				/* command line flags */int	bflag;int	cflag;int	oflag;int	uflag;int	vflag;Arfile *astart, *amiddle, *aend;	/* Temp file control block pointers */int	allobj = 1;			/* set when all members are object files of the same type */int	symdefsize;			/* size of symdef file */int	dupfound;			/* flag for duplicate symbol */Hashchain	*hash[NHASH];		/* hash table of text symbols */	#define	ARNAMESIZE	sizeof(astart->tail->hdr.name)char	poname[ARNAMESIZE+1];		/* name of pivot member */char	*file;				/* current file or member being worked on */Biobuf	bout;Biobuf bar;void	arcopy(Biobuf*, Arfile*, Armember*);int	arcreate(char*);void	arfree(Arfile*);void	arinsert(Arfile*, Armember*);char	*armalloc(int);void	armove(Biobuf*, Arfile*, Armember*);void	arread(Biobuf*, Armember*, int);void	arstream(int, Arfile*);int	arwrite(int, Armember*);int	bamatch(char*, char*);int	duplicate(char*);Armember *getdir(Biobuf*);int	getspace(void);void	install(char*, Arfile*, Arfile*, Arfile*, int);void	longt(Armember*);int	match(int, char**);void	mesg(int, char*);Arfile	*newtempfile(char*);Armember *newmember(void);void	objsym(Sym*, void*);int	openar(char*, int, int);int	page(Arfile*);void	pmode(long);void	rl(int);void	scanobj(Biobuf*, Arfile*, long);void	select(int*, long);void	setcom(void(*)(char*, int, char**));void	skip(Biobuf*, vlong);int	symcomp(void*, void*);void	trim(char*, char*, int);void	usage(void);void	wrerr(void);void	wrsym(Biobuf*, long, Arsymref*);void	rcmd(char*, int, char**);		/* command processing */void	dcmd(char*, int, char**);void	xcmd(char*, int, char**);void	tcmd(char*, int, char**);void	pcmd(char*, int, char**);void	mcmd(char*, int, char**);void	qcmd(char*, int, char**);void	(*comfun)(char*, int, char**);voidmain(int argc, char *argv[]){	char *cp;	Binit(&bout, 1, OWRITE);	if(argc < 3)		usage();	for (cp = argv[1]; *cp; cp++) {		switch(*cp) {		case 'a':	aflag = 1;	break;		case 'b':	bflag = 1;	break;		case 'c':	cflag = 1;	break;		case 'd':	setcom(dcmd);	break;		case 'i':	bflag = 1;	break;		case 'l':				strcpy(artemp, "vXXXXX");				strcpy(movtemp, "v1XXXXX");				strcpy(tailtemp, "v2XXXXX");				break;		case 'm':	setcom(mcmd);	break;		case 'o':	oflag = 1;	break;		case 'p':	setcom(pcmd);	break;		case 'q':	setcom(qcmd);	break;		case 'r':	setcom(rcmd);	break;		case 't':	setcom(tcmd);	break;		case 'u':	uflag = 1;	break;		case 'v':	vflag = 1;	break;		case 'x':	setcom(xcmd);	break;		default:			fprint(2, "ar: bad option `%c'\n", *cp);			exits("error");		}	}	if (aflag && bflag) {		fprint(2, "ar: only one of 'a' and 'b' can be specified\n");		usage();	}	if(aflag || bflag) {		trim(argv[2], poname, sizeof(poname));		argv++;		argc--;		if(argc < 3)			usage();	}	if(comfun == 0) {		if(uflag == 0) {			fprint(2, "ar: one of [%s] must be specified\n", man);			usage();		}		setcom(rcmd);	}	cp = argv[2];	argc -= 3;	argv += 3;	(*comfun)(cp, argc, argv);	/* do the command */	cp = 0;	while (argc--) {		if (*argv) {			fprint(2, "ar: %s not found\n", *argv);			cp = "error";		}		argv++;	}	exits(cp);}/* *	select a command */voidsetcom(void (*fun)(char *, int, char**)){	if(comfun != 0) {		fprint(2, "ar: only one of [%s] allowed\n", man);		usage();	}	comfun = fun;}/* *	perform the 'r' and 'u' commands */voidrcmd(char *arname, int count, char **files){	int fd;	int i;	Arfile *ap;	Armember *bp;	Dir *d;	Biobuf *bfile;	fd = openar(arname, ORDWR, 1);	if (fd >= 0) {		Binit(&bar, fd, OREAD);		Bseek(&bar,seek(fd,0,1), 1);	}	astart = newtempfile(artemp);	ap = astart;	aend = 0;	for(i = 0; fd >= 0; i++) {		bp = getdir(&bar);		if (!bp)			break;		if (bamatch(file, poname)) {		/* check for pivot */			aend = newtempfile(tailtemp);			ap = aend;		}			/* pitch symdef file */		if (i == 0 && strcmp(file, symdef) == 0) {			skip(&bar, bp->size);			continue;		}		if (count && !match(count, files)) {			scanobj(&bar, ap, bp->size);			arcopy(&bar, ap, bp);			continue;		}		bfile = Bopen(file, OREAD);		if (!bfile) {			if (count != 0)				fprint(2, "ar: cannot open %s\n", file);			scanobj(&bar, ap, bp->size);			arcopy(&bar, ap, bp);			continue;		}		d = dirfstat(Bfildes(bfile));		if(d == nil)			fprint(2, "ar: cannot stat %s: %r\n", file);		if (uflag && (d==nil || d->mtime <= bp->date)) {			scanobj(&bar, ap, bp->size);			arcopy(&bar, ap, bp);			Bterm(bfile);			free(d);			continue;		}		mesg('r', file);		skip(&bar, bp->size);		scanobj(bfile, ap, d->length);		free(d);		armove(bfile, ap, bp);		Bterm(bfile);	}	if(fd >= 0)		close(fd);		/* copy in remaining files named on command line */	for (i = 0; i < count; i++) {		file = files[i];		if(file == 0)			continue;		files[i] = 0;		bfile = Bopen(file, OREAD);		if (!bfile)			fprint(2, "ar: %s cannot open\n", file);		else {			mesg('a', file);			d = dirfstat(Bfildes(bfile));			if (d == nil)				fprint(2, "can't stat %s\n", file);			else {				scanobj(bfile, astart, d->length);				armove(bfile, astart, newmember());				free(d);			}			Bterm(bfile);		}	}	if(fd < 0 && !cflag)		install(arname, astart, 0, aend, 1);	/* issue 'creating' msg */	else		install(arname, astart, 0, aend, 0);}voiddcmd(char *arname, int count, char **files){	Armember *bp;	int fd, i;	if (!count)		return;	fd = openar(arname, ORDWR, 0);	Binit(&bar, fd, OREAD);	Bseek(&bar,seek(fd,0,1), 1);	astart = newtempfile(artemp);	for (i = 0; bp = getdir(&bar); i++) {		if(match(count, files)) {			mesg('d', file);			skip(&bar, bp->size);			if (strcmp(file, symdef) == 0)				allobj = 0;		} else if (i == 0 && strcmp(file, symdef) == 0)				skip(&bar, bp->size);		else {			scanobj(&bar, astart, bp->size);			arcopy(&bar, astart, bp);		}	}	close(fd);	install(arname, astart, 0, 0, 0);}voidxcmd(char *arname, int count, char **files){	int fd, f, mode, i;	Armember *bp;	Dir dx;	fd = openar(arname, OREAD, 0);	Binit(&bar, fd, OREAD);	Bseek(&bar,seek(fd,0,1), 1);	i = 0;	while (bp = getdir(&bar)) {		if(count == 0 || match(count, files)) {			mode = strtoul(bp->hdr.mode, 0, 8) & 0777;			f = create(file, OWRITE, mode);			if(f < 0) {				fprint(2, "ar: %s cannot create\n", file);				skip(&bar, bp->size);			} else {				mesg('x', file);				arcopy(&bar, 0, bp);				if (write(f, bp->member, bp->size) < 0)					wrerr();				if(oflag) {					nulldir(&dx);					dx.atime = bp->date;					dx.mtime = bp->date;					if(dirwstat(file, &dx) < 0)						perror(file);				}				free(bp->member);				close(f);			}			free(bp);			if (count && ++i >= count)				break;		} else {			skip(&bar, bp->size);			free(bp);		}	}	close(fd);}voidpcmd(char *arname, int count, char **files){	int fd;	Armember *bp;	fd = openar(arname, OREAD, 0);	Binit(&bar, fd, OREAD);	Bseek(&bar,seek(fd,0,1), 1);	while(bp = getdir(&bar)) {		if(count == 0 || match(count, files)) {			if(vflag)				print("\n<%s>\n\n", file);			arcopy(&bar, 0, bp);			if (write(1, bp->member, bp->size) < 0)				wrerr();		} else			skip(&bar, bp->size);		free(bp);	}	close(fd);}voidmcmd(char *arname, int count, char **files){	int fd, i;	Arfile *ap;	Armember *bp;	if (count == 0)		return;	fd = openar(arname, ORDWR, 0);	Binit(&bar, fd, OREAD);	Bseek(&bar,seek(fd,0,1), 1);	astart = newtempfile(artemp);	amiddle = newtempfile(movtemp);	aend = 0;	ap = astart;	for (i = 0; bp = getdir(&bar); i++) {		if (bamatch(file, poname)) {			aend = newtempfile(tailtemp);			ap = aend;		}		if(match(count, files)) {			mesg('m', file);			scanobj(&bar, amiddle, bp->size);			arcopy(&bar, amiddle, bp);		} else			/*			 * pitch the symdef file if it is at the beginning			 * of the archive and we aren't inserting in front			 * of it (ap == astart).			 */		if (ap == astart && i == 0 && strcmp(file, symdef) == 0)			skip(&bar, bp->size);		else {			scanobj(&bar, ap, bp->size);			arcopy(&bar, ap, bp);		}	}	close(fd);	if (poname[0] && aend == 0)		fprint(2, "ar: %s not found - files moved to end.\n", poname);	install(arname, astart, amiddle, aend, 0);}voidtcmd(char *arname, int count, char **files){	int fd;	Armember *bp;	char name[ARNAMESIZE+1];	fd = openar(arname, OREAD, 0);	Binit(&bar, fd, OREAD);	Bseek(&bar,seek(fd,0,1), 1);	while(bp = getdir(&bar)) {		if(count == 0 || match(count, files)) {			if(vflag)				longt(bp);			trim(file, name, ARNAMESIZE);			Bprint(&bout, "%s\n", name);		}		skip(&bar, bp->size);		free(bp);	}	close(fd);}voidqcmd(char *arname, int count, char **files){	int fd, i;	Armember *bp;	Biobuf *bfile;	if(aflag || bflag) {		fprint(2, "ar: abi not allowed with q\n");		exits("error");	}	fd = openar(arname, ORDWR, 1);	if (fd < 0) {		if(!cflag)			fprint(2, "ar: creating %s\n", arname);		fd = arcreate(arname);	}	Binit(&bar, fd, OREAD);	Bseek(&bar,seek(fd,0,1), 1);	/* leave note group behind when writing archive; i.e. sidestep interrupts */	rfork(RFNOTEG);	Bseek(&bar, 0, 2);	bp = newmember();	for(i=0; i<count && files[i]; i++) {		file = files[i];		files[i] = 0;		bfile = Bopen(file, OREAD);		if(!bfile)			fprint(2, "ar: %s cannot open\n", file);		else {			mesg('q', file);			armove(bfile, 0, bp);			if (!arwrite(fd, bp))				wrerr();			free(bp->member);			bp->member = 0;			Bterm(bfile);		}	}	free(bp);	close(fd);}/* *	extract the symbol references from an object file */voidscanobj(Biobuf *b, Arfile *ap, long size){	int obj;	vlong offset;	Dir *d;	static int lastobj = -1;	if (!allobj)			/* non-object file encountered */		return;	offset = Boffset(b);	obj = objtype(b, 0);	if (obj < 0) {			/* not an object file */		allobj = 0;		d = dirfstat(Bfildes(b));		if (d != nil && d->length == 0)			fprint(2, "ar: zero length file %s\n", file);		free(d);		Bseek(b, offset, 0);		return;	}	if (lastobj >= 0 && obj != lastobj) {		fprint(2, "ar: inconsistent object file %s\n", file);		allobj = 0;		Bseek(b, offset, 0);		return;	}	lastobj = obj;	if (!readar(b, obj, offset+size, 0)) {		fprint(2, "ar: invalid symbol reference in file %s\n", file);		allobj = 0;		Bseek(b, offset, 0);		return;	}	Bseek(b, offset, 0);	objtraverse(objsym, ap);}/* *	add text and data symbols to the symbol list */voidobjsym(Sym *s, void *p){	int n;	Arsymref *as;	Arfile *ap;	if (s->type != 'T' &&  s->type != 'D')		return;	ap = (Arfile*)p;	as = (Arsymref*)armalloc(sizeof(Arsymref));	as->offset = ap->size;	n = strlen(s->name);	as->name = armalloc(n+1);	strcpy(as->name, s->name);	if(s->type == 'T' && duplicate(as->name)) {		dupfound = 1;		fprint(2, "duplicate text symbol: %s\n", as->name);		free(as->name);		free(as);		return;	}	as->type = s->type;	symdefsize += 4+(n+1)+1;	as->len = n;	as->next = ap->sym;	ap->sym = as;}/* *	Check the symbol table for duplicate text symbols */intduplicate(char *name){	Hashchain *p;	char *cp;	int h;	h = 0;	for(cp = name; *cp; h += *cp++)		h *= 1119;	if(h < 0)		h = ~h;	h %= NHASH;	for(p = hash[h]; p; p = p->next)

⌨️ 快捷键说明

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