File:  [MW Coherent from dump] / coherent / d / bin / ranlib.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * Make libraries more accessible to the loader
 * by copying all the globally defined symbols
 * into a special module at the front of the archive.
 * Speed up by simply overwriting the header in the archive
 * if it fits, which it will more often than not.
 */
#include <stdio.h>
#include <ar.h>
#include <canon.h>

static	struct	ldheader	ldh;

main(argc, argv)
int	argc;
char	*argv[];
{
	register int	i, errors = 0;

	if (argc==1) {
		fprintf(stderr, "Usage: %s [ archive]+\n", argv[0]);
		exit(1);
	}
	for (i=1; i<argc; i++) {
		errors += ranlib(argv[i]);
	}
	unlink(HDRNAME);
	exit(errors);
}

static
void
complain(plaint)
char	*plaint;
{
	fprintf(stderr, "ranlib: %r\n", &plaint);
}

static
void
xwrite(sym, fp)
ar_sym	*sym;
FILE	*fp;
{
	if (fwrite(sym, sizeof(ar_sym), 1, fp)!=1) {
		complain("write error on header file");
		exit(1);
	}
}

static
void
addhdr(base, arhp, hdrfp, arfp, archive)
fsize_t	base;
struct	ar_hdr	*arhp;
FILE	*hdrfp, *arfp;
char	*archive;
{
	fsize_t	off;
	int	seg, nsym;
	fsize_t	offset;

	cansize(arhp->ar_size);
	arhp->ar_size += off = ftell(arfp);
	off -= base;
	ldh.l_magic = 0;	/* in case fread fails */
	if (fread(&ldh, sizeof ldh, 1, arfp)!=1)
		goto done;
	canshort(ldh.l_magic);
	if (ldh.l_magic!=L_MAGIC)
		goto done;
	canshort(ldh.l_flag);
	if ((ldh.l_flag & LF_32) == 0)
		ldh.l_tbase = sizeof(ldh) - 2*sizeof(short);
	else
		canshort(ldh.l_tbase);
	offset = ldh.l_tbase - (fsize_t)sizeof(ldh);
	for (seg=0; seg<L_SYM; seg++) {
		if (seg==L_BSSI || seg==L_BSSD)
			continue;
		cansize(ldh.l_ssize[seg]);
		offset += ldh.l_ssize[seg];
	}
	fseek(arfp, offset, 1);
	cansize(ldh.l_ssize[L_SYM]);
	if ((ldh.l_flag & LF_32) == 0)
		nsym = ldh.l_ssize[L_SYM]
		    / (sizeof(struct ldsym) - sizeof(short));
	else
		nsym = ldh.l_ssize[L_SYM]/sizeof(struct ldsym);
	while (nsym--) {
		union	{struct ldsym u_ldsym; ar_sym u_ar_sym;} sym;

		if (readsym((struct ldsym *)&sym, arfp) == 0) {
			complain("truncated module %.*s in %s",
			    DIRSIZ, arhp->ar_name, archive);
			exit(1);
		}
		if ((sym.ls_type&L_GLOBAL) == 0)
			continue;
		if ((sym.ls_type&LR_SEG) != L_REF) {
			sym.ar_off = off;
			cansize(sym.ar_off);
			xwrite(&sym, hdrfp);
		}
	}
done:
	fseek(arfp, arhp->ar_size, 0);	/* to end of module */
	return;
}

static
readsym(sp, fp)
register struct ldsym *sp;
FILE *fp;
{
	register int r;
	union { long l; unsigned u[2]; } u;

	if ((ldh.l_flag & LF_32) == 0) {
		r = fread(sp, sizeof(struct ldsym)-sizeof(short), 1, fp);
		u.l = sp->ls_addr;
		canshort(u.u[0]);
		sp->ls_addr = u.u[0];
	} else {
		r = fread(sp, sizeof(struct ldsym), 1, fp);
		canlong(sp->ls_addr);
	}
	canshort(sp->ls_type);
	return (r);
}

static
int
ranlib(archive)
char	*archive;
{
	FILE	*arfile, *hdrfile;
	char	arcmd[256];
	struct	ar_hdr	arhdr;
	struct	ar_sym	arsym;
	fsize_t	ohdrsize, nhdrsize;
	int	armagic = 0;
	fsize_t	arbase = sizeof armagic+sizeof arhdr;
	extern time_t time();

	if ((arfile=fopen(archive, "rb"))==NULL) {
		complain("can't open archive %s", archive);
		return (1);
	}
	fread(&armagic, sizeof armagic, 1, arfile);
	canint(armagic);
	if (armagic!=ARMAG) {
		complain("%s is not an archive", archive);
		fclose(arfile);
		return (1);
	}
	if (fread(&arhdr, sizeof arhdr, 1, arfile)!=1) {
		fclose(arfile);	/* void archive */
		return (0);
	}
	if ((hdrfile=fopen(HDRNAME, "wb"))==NULL) {
		complain("can't create header file");
		fclose(arfile);
		exit(1);
	}
	if (strncmp(arhdr.ar_name, HDRNAME, DIRSIZ)==0) {
		sprintf(arcmd, "ar ru %s %s", archive, HDRNAME);
		cansize(arhdr.ar_size);
		ohdrsize = arhdr.ar_size;
		fseek(arfile, arhdr.ar_size, 1);
		arbase += arhdr.ar_size+sizeof arhdr;
	} else {
		sprintf(arcmd, "ar rub %.*s %s %s", DIRSIZ, arhdr.ar_name,
			archive, HDRNAME);
		ohdrsize = 0;
		addhdr(arbase, &arhdr, hdrfile, arfile, archive);
	}
	while(fread(&arhdr, sizeof arhdr, 1, arfile)==1)
		addhdr(arbase, &arhdr, hdrfile, arfile, archive);
	nhdrsize = ftell(hdrfile);
	if (fclose(hdrfile)==EOF) {
		complain("close error on header file");
		exit(1);
	}
	if (ferror(arfile)) {
		complain("read error on archive %s", archive);
		fclose(arfile);
		return (1);
	}
	fclose(arfile);
	if (ohdrsize < nhdrsize)
		return system(arcmd);
	if (ohdrsize == 0) {
		complain("zero length header file");
		return (0);
	}
	if ((arfile=fopen(archive, "rwb"))==NULL) {
		complain("can't reopen archive %s", archive);
		return (1);
	}
	fread(&armagic, sizeof armagic, 1, arfile);
	canint(armagic);
	if (armagic!=ARMAG) {
		complain("%s is no longer an archive", archive);
		fclose(arfile);
		return (1);
	}
	if ((hdrfile=fopen(HDRNAME, "rb"))==NULL) {
		complain("can't reopen header file");
		fclose(arfile);
		exit(1);
	}
	if (fread(&arhdr, sizeof arhdr, 1, arfile)!=1) {
		complain("can't read archive: %s", archive);
		fclose(arfile);
		fclose(hdrfile);
		return (1);
	}
	arhdr.ar_date = time(NULL);
	cantime(arhdr.ar_date);
	fseek(arfile, (long)-sizeof arhdr, 1);
	fwrite(&arhdr, sizeof arhdr, 1, arfile);
	while (fread(&arsym, sizeof arsym, 1, hdrfile) == 1) {
		fwrite(&arsym, sizeof arsym, 1, arfile);
		ohdrsize -= sizeof arsym;
	}
	while (ohdrsize > 0) {
		fwrite(&arsym, sizeof arsym, 1, arfile);
		ohdrsize -= sizeof arsym;
	}
	if (fclose(arfile) == EOF)
		complain("close error on overwritten archive: %s", archive);
	if (fclose(hdrfile) == EOF)
		complain("close error on reread header file");
	return (0);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.