forsyth20121205-174063a80cc13 years agoHistory
684 lines · 13.0 KB · Brainfuck
RawDownload
implement Wrap; include "sys.m";	sys : Sys;include "draw.m";include "bufio.m";	bufio : Bufio;	Iobuf : import bufio;include "keyring.m";	keyring : Keyring;include "sh.m";include "arch.m";	arch : Arch;include "wrap.m";include "archfs.m"; archpid := -1;gzfd: ref Sys->FD;gzfile: string; init(bio: Bufio){	sys = load Sys Sys->PATH;	if(bio == nil)		bufio = load Bufio Bufio->PATH;	else		bufio = bio;	keyring = load Keyring Keyring->PATH;	arch = load Arch Arch->PATH;	arch->init(bufio);} end(){	if(gzfile != nil)		sys->remove(gzfile);	if (archpid > 0){		fd := sys->open("#p/" + string archpid + "/ctl", sys->OWRITE);		if (fd != nil)			sys->fprint(fd, "killgrp");	}} archfs(f : string, mtpt : string, all : int, c : chan of int){	sys->pctl(Sys->NEWPGRP, nil);	cmd := "/dis/install/archfs.dis";	m := load Archfs Archfs->PATH;	if(m == nil) {		c <-= -1;		return;	}	ch := chan of int;	if (all)		spawn m->initc(cmd :: "-m" :: mtpt :: f :: nil, ch);	else		spawn m->initc(cmd :: "-s" :: "-m" :: mtpt :: f :: "/wrap" :: nil, ch);	pid := <- ch;	c <-= pid;} mountarch(f : string, mtpt : string, all : int) : int{	c := chan of int;	spawn archfs(f, mtpt, all, c);	pid := <- c;	if (pid < 0) {		if(pid == -1)			sys->fprint(sys->fildes(2), "fatal: cannot run archfs\n");		# else probably not an archive file		return -1;	}	archpid = pid;	return 0;}	openmount(f : string, d : string) : ref Wrapped{	if (f == nil) {		p := d+"/wrap";		f = getfirstdir(p);		if (f == nil)			return nil;	}	w := ref Wrapped;	w.name = f;	w.root = d;	# p := d + "/wrap/" + f;	p := pathcat(d, pathcat("wrap", f));	(w.u, w.nu, w.tfull) = openupdate(p);	if (w.nu < 0) {		closewrap(w);		return nil;	}	return w;} closewrap(w : ref Wrapped){	w = nil;} openwraphdr(f : string, d : string, argl : list of string, all : int) : ref Wrapped{	argl = nil;	(ok, dir) := sys->stat(f);	if (ok < 0 || dir.mode & Sys->DMDIR)		return openwrap(f, d, all);	(nf, fd) := arch->openarchgz(f);	if (nf != nil) {		gzfile = nf;		f = nf;		gzfd = fd;	}	return openwrap(f, "/mnt/wrap", all);} openwrap(f : string, d : string, all : int) : ref Wrapped{	if (d == nil)		d = "/";	if((w := openmount(f, d)) != nil)		return w;		# don't mess about if /wrap/ structure exists	(ok, dir) := sys->stat(f);	if (ok < 0)		return nil;	# accept root/ or root/wrap/pkgname	if (dir.mode & Sys->DMDIR) {		d = f;		if ((i := strstr(f, "/wrap/")) >= 0) {			f = f[i+6:];			d = d[0:i+6];		}		else			f = nil;		return openmount(f, d);	}	(ok, dir) = sys->stat(f);	if (ok < 0 || dir.mode & Sys->DMDIR)		return openmount(f, d);		# ?	if (mountarch(f, d, all) < 0)		return nil;	return openmount(nil, d);} getfirstdir(d : string) : string{	if ((fd := sys->open(d, Sys->OREAD)) == nil)		return nil;	for(;;){		(n, dir) := sys->dirread(fd);		if(n <= 0)			break;		for(i:=0; i<n; i++)			if(dir[i].mode & Sys->DMDIR)				return dir[i].name;	}	return nil;} NONE : con 0; sniffdir(base : string, elem : string) : (int, int){	# t := int elem;	t := string2now(elem, 0);	if (t == 0)		return (NONE, 0);	# buf := sys->sprint("%ud", t);	# if (buf != elem)	#	return (NONE, 0);	rv := NONE;	p := base + "/" + elem + "/package";	(ok, nil) := sys->stat(p);	if (ok >= 0)		rv |= FULL;	p = base + "/" + elem + "/update";	(ok, nil) = sys->stat(p);	if (ok >= 0)		rv |= UPD;	return (rv, t);} openupdate(d : string) : (array of Update, int, int){	u : array of Update; 	if ((fd := sys->open(d, Sys->OREAD)) == nil)		return (nil, -1, 0);	#	# We are looking to find the most recent full	# package; anything before that is irrelevant.	# Also figure out the most recent package update.	# Non-package updates before that are irrelevant.	# If there are no packages installed, 	# grab all the updates we can find.	#	tbase := -1;	tfull := -1;	nu := 0;	for(;;){		(n, dir) := sys->dirread(fd);		if(n <= 0)			break;		for(i := 0; i < n; i++){			(k, t) := sniffdir(d, dir[i].name);			case (k) {				FULL =>					nu++;					if (t > tfull)						tfull = t;					if (t > tbase)						tbase = t;				FULL|UPD =>					nu++;					if (t > tfull)						tfull = t;				UPD =>					nu++;			}		}	}	if (nu == 0)		return (nil, -1, 0);	u = nil;	nu = 0;	if ((fd = sys->open(d, Sys->OREAD)) == nil)		return (nil, -1, 0);	for(;;){		(n, dir) := sys->dirread(fd);		if(n <= 0)			break;		for(i := 0; i < n; i++){			(k, t) := sniffdir(d, dir[i].name);			if (k == 0)				continue;			if (t < tbase)				continue;			if (t < tfull && k == UPD)				continue;			if (nu%8 == 0) {				newu := array[nu+8] of Update;				newu[0:] = u[0:nu];				u = newu;			}			u[nu].typ = k;			if (readupdate(u, nu, d, dir[i].name) != nil)				nu++;		}	}	if (nu == 0)		return (nil, -1, 0);	qsort(u, nu);	return (u, nu, tfull);} readupdate(u : array of Update, ui : int, base : string, elem : string) : array of Update{	# u[ui].dir = base + "/" + elem;	u[ui].dir = pathcat(base, elem);	p := u[ui].dir + "/desc";	u[ui].desc = readfile(p);	# u[ui].time = int elem;	u[ui].time = string2now(elem, 0);	p = u[ui].dir + "/md5sum";	u[ui].bmd5 = bufio->open(p, Bufio->OREAD);	p = u[ui].dir + "/update";	q := readfile(p);	if (q != nil)		u[ui].utime = int q;	else		u[ui].utime = 0;	if (u[ui].bmd5 == nil)		return nil;	return u;} readfile(s : string) : string{	(ok, d) := sys->stat(s);	if (ok < 0)		return nil;	buf := array[int d.length] of byte;	if ((fd := sys->open(s, Sys->OREAD)) == nil || sys->read(fd, buf, int d.length) != int d.length)		return nil;	s = string buf;	ls := len s;	if (s[ls-1] == '\n')		s = s[0:ls-1];	return s;}	hex(c : int) : int{	if (c >= '0' && c <= '9')		return c-'0';	if (c >= 'a' && c <= 'f')		return c-'a'+10;	if (c >= 'A' && c <= 'F')		return c-'A'+10;	return -1;} getfileinfo(w : ref Wrapped, f : string, rdigest : array of byte, wdigest : array of byte, ardigest: array of byte) : (int, int){	p : string; 	if (w == nil)		return (-1, 0);	digest := array[keyring->MD5dlen] of { * => byte 0 };	for (i := w.nu-1; i >= 0; i--){		if ((p = bsearch(w.u[i].bmd5, f)) == nil)			continue;		if (p == nil)			continue;		k := 0;		while (k < len p && p[k] != ' ')			k++;		if (k == len p)			continue;		q := p[k+1:];		if (q == nil)			continue;		if (len q != 2*Keyring->MD5dlen+1)			continue;		for (j := 0; j < Keyring->MD5dlen; j++) {			a := hex(q[2*j]);			b := hex(q[2*j+1]);			if (a < 0 || b < 0)				break;			digest[j] = byte ((a<<4)|b);		}		if(j != Keyring->MD5dlen)			continue;		if(rdigest == nil || memcmp(rdigest, digest, keyring->MD5dlen) == 0 || (ardigest != nil && memcmp(ardigest, digest, keyring->MD5dlen) == 0))			break;		else			return (-1, 0);	# NEW	}	if(i < 0)		return (-1, 0);	if(wdigest != nil)		wdigest[0:] = rdigest;	return (0, w.u[i].time);			} bsearch(b : ref Bufio->Iobuf, p : string) : string{	if (b == nil)		return nil;	lo := 0;	b.seek(big 0, Bufio->SEEKEND);	hi := int b.offset();	l := len p;	while (lo < hi) {		m := (lo+hi)/2;		b.seek(big m, Bufio->SEEKSTART);		b.gets('\n');		if (int b.offset() == hi) {			bgetbackc(b);			m = int b.offset();			while (m-- > lo) {				if (bgetbackc(b) == '\n') {					b.getc();					break;				}			}		}		s := b.gets('\n');		if (len s >= l+1 && s[0:l] == p && (s[l] == ' ' || s[l] == '\n'))			return s;		if (s < p)			lo = int b.offset();		else			hi = int b.offset()-len s;	}	return nil;} bgetbackc(b : ref Bufio->Iobuf) : int{	m := int b.offset();	b.seek(big (m-1), Bufio->SEEKSTART);	c := b.getc();	b.ungetc();	return c;} strstr(s : string, p : string) : int{	lp := len p;	ls := len s;	for (i := 0; i < ls-lp; i++)		if (s[i:i+lp] == p)			return i;	return -1;} qsort(a : array of Update, n : int){	i, j : int;	t : Update; 	while(n > 1) {		i = n>>1;		t = a[0]; a[0] = a[i]; a[i] = t;		i = 0;		j = n;		for(;;) {			do				i++;			while(i < n && a[i].time < a[0].time);			do				j--;			while(j > 0 && a[j].time > a[0].time);			if(j < i)				break;			t = a[i]; a[i] = a[j]; a[j] = t;		}		t = a[0]; a[0] = a[j]; a[j] = t;		n = n-j-1;		if(j >= n) {			qsort(a, j);			a = a[j+1:];		} else {			qsort(a[j+1:], n);			n = j;		}	}} md5file(file : string, digest : array of byte) : int{	(ok, d) := sys->stat(file);	if (ok < 0)		return -1;	if (d.mode & Sys->DMDIR)		return 0;	bio := bufio->open(file, Bufio->OREAD);	if (bio == nil)		return -1;	# return md5sum(bio, digest, d.length);	buff := array[Sys->ATOMICIO] of byte;	ds := keyring->md5(nil, 0, nil, nil);	while ((n := bio.read(buff, len buff)) > 0)		keyring->md5(buff, n, nil, ds);	keyring->md5(nil, 0, digest, ds);	bio = nil;	return 0;} md5sum(b : ref Iobuf, digest : array of byte, leng : int) : int{	ds := keyring->md5(nil, 0, nil, nil);	buff := array[Sys->ATOMICIO] of byte;	while (leng > 0) {		if (leng > len buff)			n := len buff;		else			n = leng;		if ((n = b.read(buff, n)) <= 0)			return -1;		keyring->md5(buff, n, nil, ds);		leng -= n;	}	keyring->md5(nil, 0, digest, ds);	return 0;}		md5conv(d : array of byte) : string{	s : string = nil; 	for (i := 0; i < keyring->MD5dlen; i++)		s += sys->sprint("%.2ux", int d[i]);	return s;}	 zd : Sys->Dir; newd(time : int, uid : string, gid : string) : ref Sys->Dir{	d := ref Sys->Dir;	*d = zd;	d.uid = uid;	d.gid = gid;	d.mtime = time;	return d;} putwrapfile(b : ref Iobuf, name : string, time : int, elem : string, file : string, uid : string, gid : string){	d := newd(time, uid, gid);	d.mode = 8r444;	(ok, dir) := sys->stat(file);	if (ok < 0)		sys->fprint(sys->fildes(2), "cannot stat %s: %r", file);	d.length = dir.length;

Lines 1–500 of 684.