xref: /inferno-os/appl/cmd/install/logs.b (revision 1f44c82a26ff60e012a2ff697cb036a25c0c7f97)
137da2899SCharles.Forsythimplement Logs;
237da2899SCharles.Forsyth
337da2899SCharles.Forsythinclude "sys.m";
437da2899SCharles.Forsyth	sys: Sys;
537da2899SCharles.Forsyth
637da2899SCharles.Forsythinclude "draw.m";
737da2899SCharles.Forsyth
837da2899SCharles.Forsythinclude "bufio.m";
937da2899SCharles.Forsyth	bufio: Bufio;
1037da2899SCharles.Forsyth	Iobuf: import bufio;
1137da2899SCharles.Forsyth
1237da2899SCharles.Forsythinclude "string.m";
1337da2899SCharles.Forsyth	str: String;
1437da2899SCharles.Forsyth
1537da2899SCharles.Forsythinclude "logs.m";
1637da2899SCharles.Forsyth
1737da2899SCharles.ForsythHashsize: con 1024;
1837da2899SCharles.ForsythIncr: con 500;
1937da2899SCharles.Forsyth
2037da2899SCharles.Forsythinit(bio: Bufio): string
2137da2899SCharles.Forsyth{
2237da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
2337da2899SCharles.Forsyth	bufio = bio;
2437da2899SCharles.Forsyth	str = load String String->PATH;
2537da2899SCharles.Forsyth	if(str == nil)
2637da2899SCharles.Forsyth		return sys->sprint("can't load %s: %r", String->PATH);
2737da2899SCharles.Forsyth	return nil;
2837da2899SCharles.Forsyth}
2937da2899SCharles.Forsyth
3037da2899SCharles.ForsythEntry.read(in: ref Iobuf): (ref Entry, string)
3137da2899SCharles.Forsyth{
3237da2899SCharles.Forsyth	if((s := in.gets('\n')) == nil)
3337da2899SCharles.Forsyth		return (nil, nil);
3437da2899SCharles.Forsyth	if(s[len s-1] == '\n')
3537da2899SCharles.Forsyth		s = s[0:len s-1];
3637da2899SCharles.Forsyth
3737da2899SCharles.Forsyth	e := ref Entry;
3837da2899SCharles.Forsyth	e.x = -1;
3937da2899SCharles.Forsyth
4037da2899SCharles.Forsyth	l := str->unquoted(s);
4137da2899SCharles.Forsyth	fields := array[11] of string;
4237da2899SCharles.Forsyth	for(i := 0; l != nil; l = tl l)
4337da2899SCharles.Forsyth		fields[i++] = S(hd l);
4437da2899SCharles.Forsyth
4537da2899SCharles.Forsyth	#  time gen verb path serverpath mode uid gid mtime length
4637da2899SCharles.Forsyth	# 1064889121 4 a sys/src/cmd/ip/httpd/webls.denied - 664 sys sys 1064887847 3
4737da2899SCharles.Forsyth	# time[0] gen[1] op[2] path[3] (serverpath|"-")[4] mode[5] uid[6] gid[7] mtime[8] length[9]
4837da2899SCharles.Forsyth
4937da2899SCharles.Forsyth	if(i < 10 || len fields[2] != 1)
5037da2899SCharles.Forsyth		return (nil, sys->sprint("bad log entry: %q", s));
5137da2899SCharles.Forsyth	e.action = fields[2][0];
5237da2899SCharles.Forsyth	case e.action {
5337da2899SCharles.Forsyth	'a' or 'c' or 'd' or 'm' =>
5437da2899SCharles.Forsyth		;
5537da2899SCharles.Forsyth	* =>
5637da2899SCharles.Forsyth		return (nil, sys->sprint("bad log entry: %q", s));
5737da2899SCharles.Forsyth	}
5837da2899SCharles.Forsyth
5937da2899SCharles.Forsyth	time := bigof(fields[0], 10);
6037da2899SCharles.Forsyth	sgen := bigof(fields[1], 10);
6137da2899SCharles.Forsyth	e.seq = (time << 32) | sgen;	# for easier comparison
6237da2899SCharles.Forsyth
6337da2899SCharles.Forsyth	# time/gen check
6437da2899SCharles.Forsyth	# name check
6537da2899SCharles.Forsyth
6637da2899SCharles.Forsyth	if(fields[4] == "-")	# undocumented
6737da2899SCharles.Forsyth		fields[4] = fields[3];
6837da2899SCharles.Forsyth	e.path = fields[3];
6937da2899SCharles.Forsyth	e.serverpath = fields[4];
7037da2899SCharles.Forsyth	e.d = sys->nulldir;
7137da2899SCharles.Forsyth	{
7237da2899SCharles.Forsyth		e.d.mode = intof(fields[5], 8);
7337da2899SCharles.Forsyth		e.d.qid.qtype = e.d.mode>>24;
7437da2899SCharles.Forsyth		e.d.uid = fields[6];
7537da2899SCharles.Forsyth		if(e.d.uid == "-")
7637da2899SCharles.Forsyth			e.d.uid = "";
7737da2899SCharles.Forsyth		e.d.gid = fields[7];
7837da2899SCharles.Forsyth		if(e.d.gid == "-")
7937da2899SCharles.Forsyth			e.d.gid = "";
8037da2899SCharles.Forsyth		e.d.mtime = intof(fields[8], 10);
8137da2899SCharles.Forsyth		e.d.length = bigof(fields[9], 10);
8237da2899SCharles.Forsyth	}exception ex {
8337da2899SCharles.Forsyth	"log format:*" =>
8437da2899SCharles.Forsyth		return (nil, sys->sprint("%s in log entry %q", ex, s));
8537da2899SCharles.Forsyth	}
8637da2899SCharles.Forsyth	e.contents = fields[10] :: nil;	# optional
8737da2899SCharles.Forsyth	return (e, nil);
8837da2899SCharles.Forsyth}
8937da2899SCharles.Forsyth
9037da2899SCharles.Forsythrev[T](l: list of T): list of T
9137da2899SCharles.Forsyth{
9237da2899SCharles.Forsyth	rl: list of T;
9337da2899SCharles.Forsyth	for(; l != nil; l = tl l)
9437da2899SCharles.Forsyth		rl = hd l :: rl;
9537da2899SCharles.Forsyth	return rl;
9637da2899SCharles.Forsyth}
9737da2899SCharles.Forsyth
9837da2899SCharles.Forsythbigof(s: string, base: int): big
9937da2899SCharles.Forsyth{
10037da2899SCharles.Forsyth	(b, r) := str->tobig(s, base);
10137da2899SCharles.Forsyth	if(r != nil)
10237da2899SCharles.Forsyth		raise "invalid integer field";
10337da2899SCharles.Forsyth	return b;
10437da2899SCharles.Forsyth}
10537da2899SCharles.Forsyth
10637da2899SCharles.Forsythintof(s: string, base: int): int
10737da2899SCharles.Forsyth{
10837da2899SCharles.Forsyth	return int bigof(s, base);
10937da2899SCharles.Forsyth}
11037da2899SCharles.Forsyth
11137da2899SCharles.Forsythmkpath(root: string, name: string): string
11237da2899SCharles.Forsyth{
11337da2899SCharles.Forsyth	if(len root > 0 && root[len root-1] != '/' && (len name == 0 || name[0] != '/'))
11437da2899SCharles.Forsyth		return root+"/"+name;
11537da2899SCharles.Forsyth	return root+name;
11637da2899SCharles.Forsyth}
11737da2899SCharles.Forsyth
11837da2899SCharles.Forsythcontents(e: ref Entry): string
11937da2899SCharles.Forsyth{
12037da2899SCharles.Forsyth	if(e.contents == nil)
12137da2899SCharles.Forsyth		return "";
12237da2899SCharles.Forsyth	s := "";
12337da2899SCharles.Forsyth	for(cl := e.contents; cl != nil; cl = tl cl)
12437da2899SCharles.Forsyth		s += " " + hd cl;
125*1f44c82aSCharles.Forsyth	return s;	# includes initial space
12637da2899SCharles.Forsyth}
12737da2899SCharles.Forsyth
12837da2899SCharles.ForsythEntry.text(e: self ref Entry): string
12937da2899SCharles.Forsyth{
13037da2899SCharles.Forsyth	a := e.action;
13137da2899SCharles.Forsyth	if(a == 0)
13237da2899SCharles.Forsyth		a = '?';
13337da2899SCharles.Forsyth	return sys->sprint("%bd %bd %q [%d] %c m=%uo l=%bd t=%ud c=%q", e.seq>>32, e.seq & 16rFFFFFFFF, e.path, e.x, a, e.d.mode, e.d.length, e.d.mtime, contents(e));
13437da2899SCharles.Forsyth}
13537da2899SCharles.Forsyth
13637da2899SCharles.ForsythEntry.sumtext(e: self ref Entry): string
13737da2899SCharles.Forsyth{
13837da2899SCharles.Forsyth	case e.action {
13937da2899SCharles.Forsyth	'a' or 'm' =>
14037da2899SCharles.Forsyth		return sys->sprint("%c %q %uo %q %q %ud", e.action, e.path, e.d.mode, e.d.uid, e.d.gid, e.d.mtime);
14137da2899SCharles.Forsyth	'd' or 'c' =>
14237da2899SCharles.Forsyth		return sys->sprint("%c %q", e.action, e.path);
14337da2899SCharles.Forsyth	* =>
14437da2899SCharles.Forsyth		return sys->sprint("? %q", e.path);
14537da2899SCharles.Forsyth	}
14637da2899SCharles.Forsyth}
14737da2899SCharles.Forsyth
14837da2899SCharles.ForsythEntry.dbtext(e: self ref Entry): string
14937da2899SCharles.Forsyth{
15037da2899SCharles.Forsyth	#   path dpath|"-" mode uid gid mtime length
15137da2899SCharles.Forsyth	return sys->sprint("%bd %bd %q - %uo %q %q %ud %bd%s", e.seq>>32, e.seq & 16rFFFFFFFF, e.path, e.d.mode, e.d.uid, e.d.gid, e.d.mtime, e.d.length, contents(e));
15237da2899SCharles.Forsyth}
15337da2899SCharles.Forsyth
15437da2899SCharles.ForsythEntry.logtext(e: self ref Entry): string
15537da2899SCharles.Forsyth{
15637da2899SCharles.Forsyth	#   gen n act path spath|"-" dpath|"-" mode uid gid mtime length
15737da2899SCharles.Forsyth	a := e.action;
15837da2899SCharles.Forsyth	if(a == 0)
15937da2899SCharles.Forsyth		a = '?';
16037da2899SCharles.Forsyth	sf := e.serverpath;
16137da2899SCharles.Forsyth	if(sf == nil || sf == e.path)
16237da2899SCharles.Forsyth		sf = "-";
16337da2899SCharles.Forsyth	return sys->sprint("%bd %bd %c %q %q %uo %q %q %ud %bd%s", e.seq>>32, e.seq & 16rFFFFFFFF, a, e.path, sf, e.d.mode, e.d.uid, e.d.gid, e.d.mtime, e.d.length, contents(e));
16437da2899SCharles.Forsyth}
16537da2899SCharles.Forsyth
16637da2899SCharles.ForsythEntry.remove(e: self ref Entry)
16737da2899SCharles.Forsyth{
16837da2899SCharles.Forsyth	e.action = 'd';
16937da2899SCharles.Forsyth}
17037da2899SCharles.Forsyth
17137da2899SCharles.ForsythEntry.removed(e: self ref Entry): int
17237da2899SCharles.Forsyth{
17337da2899SCharles.Forsyth	return e.action == 'd';
17437da2899SCharles.Forsyth}
17537da2899SCharles.Forsyth
17637da2899SCharles.ForsythEntry.update(e: self ref Entry, n: ref Entry)
17737da2899SCharles.Forsyth{
17837da2899SCharles.Forsyth	if(n == nil)
17937da2899SCharles.Forsyth		return;
18037da2899SCharles.Forsyth	if(n.action == 'd')
18137da2899SCharles.Forsyth		e.contents = nil;
18237da2899SCharles.Forsyth	else
18337da2899SCharles.Forsyth		e.d = n.d;
18437da2899SCharles.Forsyth	if(n.action != 'm' || e.action == 'd')
18537da2899SCharles.Forsyth		e.action = n.action;
18637da2899SCharles.Forsyth	e.serverpath = S(n.serverpath);
18737da2899SCharles.Forsyth	for(nl := rev(n.contents); nl != nil; nl = tl nl)
18837da2899SCharles.Forsyth		e.contents = hd nl :: e.contents;
18937da2899SCharles.Forsyth	if(n.seq > e.seq)
19037da2899SCharles.Forsyth		e.seq = n.seq;
19137da2899SCharles.Forsyth}
19237da2899SCharles.Forsyth
19337da2899SCharles.ForsythDb.new(name: string): ref Db
19437da2899SCharles.Forsyth{
19537da2899SCharles.Forsyth	db := ref Db;
19637da2899SCharles.Forsyth	db.name = name;
19737da2899SCharles.Forsyth	db.stateht = array[Hashsize] of list of ref Entry;
19837da2899SCharles.Forsyth	db.nstate = 0;
19937da2899SCharles.Forsyth	db.state = array[50] of ref Entry;
20037da2899SCharles.Forsyth	return db;
20137da2899SCharles.Forsyth}
20237da2899SCharles.Forsyth
20337da2899SCharles.ForsythDb.look(db: self ref Db, name: string): ref Entry
20437da2899SCharles.Forsyth{
20537da2899SCharles.Forsyth	(b, nil) := hash(name, len db.stateht);
20637da2899SCharles.Forsyth	for(l := db.stateht[b]; l != nil; l = tl l)
20737da2899SCharles.Forsyth		if((hd l).path == name)
20837da2899SCharles.Forsyth			return hd l;
20937da2899SCharles.Forsyth	return nil;
21037da2899SCharles.Forsyth}
21137da2899SCharles.Forsyth
21237da2899SCharles.ForsythDb.entry(db: self ref Db, seq: big, name: string, d: Sys->Dir): ref Entry
21337da2899SCharles.Forsyth{
21437da2899SCharles.Forsyth	e := ref Entry;
21537da2899SCharles.Forsyth	e.action = 'a';
21637da2899SCharles.Forsyth	e.seq = seq;
21737da2899SCharles.Forsyth	e.path = name;
21837da2899SCharles.Forsyth	e.d = d;
21937da2899SCharles.Forsyth	e.x = db.nstate++;
22037da2899SCharles.Forsyth	if(e.x >= len db.state){
22137da2899SCharles.Forsyth		a := array[len db.state + Incr] of ref Entry;
22237da2899SCharles.Forsyth		a[0:]  = db.state;
22337da2899SCharles.Forsyth		db.state = a;
22437da2899SCharles.Forsyth	}
22537da2899SCharles.Forsyth	db.state[e.x] = e;
22637da2899SCharles.Forsyth	(b, nil) := hash(name, len db.stateht);
22737da2899SCharles.Forsyth	db.stateht[b] = e :: db.stateht[b];
22837da2899SCharles.Forsyth	return e;
22937da2899SCharles.Forsyth}
23037da2899SCharles.Forsyth
23137da2899SCharles.ForsythDb.sort(db: self ref Db, key: int)
23237da2899SCharles.Forsyth{
23337da2899SCharles.Forsyth	sortentries(db.state[0:db.nstate], key);
23437da2899SCharles.Forsyth}
23537da2899SCharles.Forsyth
23637da2899SCharles.Forsythsortentries(a: array of ref Entry, key: int): (array of ref Entry, int)
23737da2899SCharles.Forsyth{
23837da2899SCharles.Forsyth	mergesort(a, array[len a] of ref Entry, key);
23937da2899SCharles.Forsyth	return (a, len a);
24037da2899SCharles.Forsyth}
24137da2899SCharles.Forsyth
24237da2899SCharles.Forsythmergesort(a, b: array of ref Entry, key: int)
24337da2899SCharles.Forsyth{
24437da2899SCharles.Forsyth	r := len a;
24537da2899SCharles.Forsyth	if(r > 1) {
24637da2899SCharles.Forsyth		m := (r-1)/2 + 1;
24737da2899SCharles.Forsyth		mergesort(a[0:m], b[0:m], key);
24837da2899SCharles.Forsyth		mergesort(a[m:], b[m:], key);
24937da2899SCharles.Forsyth		b[0:] = a;
25037da2899SCharles.Forsyth		for((i, j, k) := (0, m, 0); i < m && j < r; k++) {
25137da2899SCharles.Forsyth			if(key==Byname && b[i].path > b[j].path || key==Byseq && b[i].seq > b[j].seq)
25237da2899SCharles.Forsyth				a[k] = b[j++];
25337da2899SCharles.Forsyth			else
25437da2899SCharles.Forsyth				a[k] = b[i++];
25537da2899SCharles.Forsyth		}
25637da2899SCharles.Forsyth		if(i < m)
25737da2899SCharles.Forsyth			a[k:] = b[i:m];
25837da2899SCharles.Forsyth		else if(j < r)
25937da2899SCharles.Forsyth			a[k:] = b[j:r];
26037da2899SCharles.Forsyth	}
26137da2899SCharles.Forsyth}
26237da2899SCharles.Forsyth
26337da2899SCharles.Forsythstrings:	array of list of string;
26437da2899SCharles.Forsyth
26537da2899SCharles.ForsythS(s: string): string
26637da2899SCharles.Forsyth{
26737da2899SCharles.Forsyth	if(strings == nil)
26837da2899SCharles.Forsyth		strings = array[257] of list of string;
26937da2899SCharles.Forsyth	h := hash(s, len strings).t0;
27037da2899SCharles.Forsyth	for(sl := strings[h]; sl != nil; sl = tl sl)
27137da2899SCharles.Forsyth		if(hd sl == s)
27237da2899SCharles.Forsyth			return hd sl;
27337da2899SCharles.Forsyth	strings[h] = s :: strings[h];
27437da2899SCharles.Forsyth	return s;
27537da2899SCharles.Forsyth}
27637da2899SCharles.Forsyth
27737da2899SCharles.Forsythhash(s: string, n: int): (int, int)
27837da2899SCharles.Forsyth{
27937da2899SCharles.Forsyth	# hashpjw
28037da2899SCharles.Forsyth	h := 0;
28137da2899SCharles.Forsyth	for(i:=0; i<len s; i++){
28237da2899SCharles.Forsyth		h = (h<<4) + s[i];
28337da2899SCharles.Forsyth		if((g := h & int 16rF0000000) != 0)
28437da2899SCharles.Forsyth			h ^= ((g>>24) & 16rFF) | g;
28537da2899SCharles.Forsyth	}
28637da2899SCharles.Forsyth	return ((h&~(1<<31))%n, h);
28737da2899SCharles.Forsyth}
288