henesyinit from p9f47575dc5 years agoHistory
185 lines · 3.6 KB · C
RawDownload
/* * rl.c -- rl */#include <u.h>#include <libc.h>#include <ar.h>#include <bio.h>#include <mach.h> enum{	RLENTSIZE	 = 4 + NNAME + 4,}; char	symname[]="__.SYMDEF";	/* table of contents file name */char	*libname;		/* current archive */char	firstname[NNAME];	/* first file in archive */char	*errs;			/* exit status */char	verbose;int	nextern;		/* number of 'T' & 'D' symbols */int	symsize;		/* size of __.SYMDEF archive member */ int	readrl(Biobuf *bp);void	writerl(void),	setoffsets(Sym *, int),	fexec(char *, char *, ...); voidmain(int argc, char *argv[]){	int i;	Biobuf	*bin; 	argv0 = argv[0];	ARGBEGIN {	case 'v':		verbose = 1;		break;	} ARGEND	for(i=0; i<argc; i++){		libname = argv[i];		bin = Bopen(libname, OREAD);		if(bin == 0){			fprint(2, "%s: cannot open %s\n", argv0, libname);			errs = "errors";			continue;		}		if (isar(bin)) {			if (readrl(bin) < 0)				errs = "errors";			else				writerl();		}else{			fprint(2, "%s: not an archive: %s\n", argv0, libname);			errs = "errors";		}		Bclose(bin);	}	exits(errs);} /* * read an archive file, * processing the symbols for each intermediate file in it. */intreadrl(Biobuf *bp){	int i, j, offset, size, obj, lastobj;	Sym *s;	char membername[NNAME]; 	offset = BOFFSET(bp);	symsize = 0;	lastobj = -1;	objreset();	j = 0;	for (i = 0;;i++) {		size = nextar(bp, offset, membername);		if (size < 0) {			fprint(2, "%s: phase error on ar header %ld\n", argv0, offset);			return -1;		}		if (size == 0)			return 1;		if (i == 0)		/* first time through */			strcpy(firstname, membername);		if (strcmp(membername, symname) == 0) {			symsize = size;		/* skip symbol table */			offset += size;			continue;		}		obj = objtype(bp);		if (lastobj < 0)	/* force match first time & after err */			lastobj = obj;		if (obj < 0 || obj != lastobj) {			fprint(2, "%s: inconsistent file %s in %s\n", argv0,					membername, libname);			return -1;		}		lastobj = obj;		if (!readar(bp, obj, offset+size)) {			fprint(2, "%s: invalid symbol reference in file %s\n", membername);			return -1;		}		while (s = objsym(j)) {			if (s->type == 'T' || s->type == 'D') {				s->value = offset-symsize;				nextern++;			}			j++;		}		offset += size;	}	return 1;} voidwriterl(void){	Biobuf b;	Sym *s;	long new, off;	int fd, i; 	fd = create(symname, 1, 0664);	if(fd < 0){		fprint(2, "%s: cannot create %s\n", argv0, symname);		return;	}	Binit(&b, fd, OWRITE);	new = nextern * RLENTSIZE + SAR_HDR;	for(i=0; s = objsym(i); i++) {		if(s->type != 'T' && s->type != 'D')			continue;		off = s->value + new;		if(verbose)			print("%10s %d %ld\n", s->name, s->type == 'D', off);		Bputc(&b, off);		Bputc(&b, off>>8);		Bputc(&b, off>>16);		Bputc(&b, off>>24);		if (Bwrite(&b, s->name, NNAME) != NNAME) {			fprint(2, "%s: short write to %s\n", argv0, symname);			errs = "errors";		}		if(s->type == 'T')			Bputc(&b, 0);		else			Bputc(&b, 1);		/* padding */		Bputc(&b, 0); Bputc(&b, 0); Bputc(&b, 0);	}	Bclose(&b);	close(fd);	if(strcmp(firstname, symname) != 0)		if(symsize == 0)			fexec("/bin/ar", "ar", "rb", firstname, libname, symname, 0);		else{			fexec("/bin/ar", "ar", "mb", firstname, libname, symname, 0);			fexec("/bin/ar", "ar", "r", libname, symname, 0);		}	else		fexec("/bin/ar", "ar", "r", libname, symname, 0);	remove(symname);} voidfexec(char *av0, char *av, ...){	int pid;	Waitmsg w; 	switch(pid = fork()){	case -1:		fprint(2, "%s: can't fork\n", argv0);		exits("fork");	case 0:		exec(av0, &av);		fprint(2, "%s: can't exec\n", argv0);		exits("exec");	}	while(wait(&w) != -1 && atoi(w.pid) != pid)		;}