xref: /inferno-os/appl/cmd/install/wrap2list.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1#
2# Copyright © 2001 Vita Nuova (Holdings) Limited.  All rights reserved.
3#
4
5implement Wrap2list;
6
7# make a version list suitable for SDS from /wrap
8
9include "sys.m";
10	sys : Sys;
11include "draw.m";
12include "bufio.m";
13	bufio : Bufio;
14	Iobuf : import bufio;
15include "crc.m";
16	crcm : Crc;
17include "wrap.m";
18	wrap: Wrap;
19
20Wrap2list: module
21{
22	init : fn(ctxt: ref Draw->Context, argv: list of string);
23};
24
25stderr: ref Sys->FD;
26
27HASHSZ: con 64;
28
29Element: type string;
30
31Hash: adt{
32	elems: array of Element;
33	nelems: int;
34};
35
36List: adt{
37	tabs: array of ref Hash;
38	init: fn(l: self ref List);
39	add: fn(l: self ref List, e: Element);
40	subtract: fn(l: self ref List, e: Element);
41	end: fn(l: self ref List): array of Element;
42};
43
44flist: ref List;
45
46hash(s: string): int
47{
48	h := 0;
49	n := len s;
50	for(i := 0; i < n; i++)
51		h += s[i];
52	if(h < 0)
53		h = -h;
54	return h%HASHSZ;
55}
56
57List.init(l: self ref List)
58{
59	ts := l.tabs = array[HASHSZ] of ref Hash;
60	for(i := 0; i < HASHSZ; i++){
61		t := ts[i] = ref Hash;
62		t.elems = array[HASHSZ] of Element;
63		t.nelems = 0;
64	}
65}
66
67List.add(l: self ref List, e: Element)
68{
69	h := hash(e);
70	t := l.tabs[h];
71	n := t.nelems;
72	es := t.elems;
73	for(i := 0; i < n; i++){
74		if(e == es[i])
75			return;
76	}
77	if(n == len es)
78		es = t.elems = (array[2*n] of Element)[0:] = es;
79	es[t.nelems++] = e;
80# sys->print("+ %s\n", e);
81}
82
83List.subtract(l: self ref List, e: Element)
84{
85	h := hash(e);
86	t := l.tabs[h];
87	n := t.nelems;
88	es := t.elems;
89	for(i := 0; i < n; i++){
90		if(e == es[i]){
91			es[i] = nil;
92			break;
93		}
94	}
95# sys->print("- %s\n", e);
96}
97
98List.end(l: self ref List): array of Element
99{
100	tot := 0;
101	ts := l.tabs;
102	for(i := 0; i < HASHSZ; i++)
103		tot += ts[i].nelems;
104	a := array[tot] of Element;
105	m := 0;
106	for(i = 0; i < HASHSZ; i++){
107		t := ts[i];
108		n := t.nelems;
109		es := t.elems;
110		a[m:] = es[0: n];
111		m += n;
112	}
113	return a;
114}
115
116usage()
117{
118	sys->fprint(stderr, "Usage: wrap2list [ file ... ]\n");
119	exit;
120}
121
122init(nil: ref Draw->Context, argv: list of string)
123{
124	sys = load Sys Sys->PATH;
125	bufio = load Bufio Bufio->PATH;
126	crcm = load Crc Crc->PATH;
127	wrap = load Wrap Wrap->PATH;
128	wrap->init(bufio);
129	if(argv != nil)
130		argv = tl argv;
131	init := 0;
132	if(argv != nil && hd argv == "-i"){
133		init = 1;
134		argv = tl argv;
135	}
136	stderr = sys->fildes(2);
137	# root := "/";
138	flist = ref List;
139	flist.init();
140	fd := sys->open("/wrap", Sys->OREAD);
141	for(;;){
142		(nd, d) := sys->dirread(fd);
143		if(nd <= 0)
144			break;
145		for(i:=0; i<nd; i++){
146			if((d[0].mode & Sys->DMDIR) && (w := wrap->openwrap(d[i].name, "/", 1)) != nil){
147				# sys->fprint(stderr, "%s %s %d %d\n", w.name, w.root, w.tfull, w.nu);
148				for(j := 0; j < w.nu; j++){
149					addfiles(w.u[j].bmd5);
150					if((b := bufio->open(w.u[j].dir+"/remove", Bufio->OREAD)) != nil)
151						subtractfiles(b);
152					# sys->fprint(stderr, "%d: %s %s %d %d %d\n", i, w.u[j].desc, w.u[j].dir, w.u[j].time, w.u[j].utime, w.u[j].typ);
153				}
154			}
155		}
156	}
157	for( ; argv != nil; argv = tl argv){
158		if((b := bufio->open(hd argv, Bufio->OREAD)) != nil)
159			addfiles(b);
160	}
161	out(uniq(rmnil(sort(flist.end()))), init);
162}
163
164addfiles(b: ref Bufio->Iobuf)
165{
166	b.seek(big 0, Bufio->SEEKSTART);
167	while((s := b.gets('\n')) != nil){
168		(n, l) := sys->tokenize(s, " \n");
169		if(n > 0)
170			flist.add(hd l);
171	}
172}
173
174subtractfiles(b: ref Bufio->Iobuf)
175{
176	b.seek(big 0, Bufio->SEEKSTART);
177	while((s := b.gets('\n')) != nil){
178		(n, l) := sys->tokenize(s, " \n");
179		if(n > 0)
180			flist.subtract(hd l);
181	}
182}
183
184out(fs: array of Element, init: int)
185{
186	nf := len fs;
187	for(i := 0; i < nf; i++){
188		f := fs[i];
189		outl(f, nil, init);
190		l := len f;
191		if(l >= 7 && f[l-7:] == "emu.new"){
192			g := f;
193			f[l-3] = 'e';
194			f[l-2] = 'x';
195			f[l-1] = 'e';
196			outl(f, g, init);		# try emu.exe
197			outl(f[0: l-4], g, init);	# try emu
198# sys->fprint(sys->fildes(2), "%s %s\n", f, g);
199		}
200	}
201}
202
203outl(f: string, g: string, init: int)
204{
205	(ok, d) := sys->stat(f);
206	if(ok < 0){
207		# sys->fprint(stderr, "cannot open %s\n", f);
208		return;
209	}
210	if(g == nil)
211		g = "-";
212	if(d.mode & Sys->DMDIR)
213		d.length = big 0;
214	if(init)
215		mtime := 0;
216	else
217		mtime = d.mtime;
218	sys->print("%s	%s	%d	%d	%d	%d	%d\n", f, g, int d.length, d.mode, mtime, crc(f, d), 0);
219}
220
221crc(f: string, d: Sys->Dir): int
222{
223	crcs := crcm->init(0, int 16rffffffff);
224	if(d.mode & Sys->DMDIR)
225		return 0;
226	fd := sys->open(f, Sys->OREAD);
227	if(fd == nil){
228		sys->fprint(stderr, "cannot open %s\n", f);
229		return 0;
230	}
231	crc := 0;
232	buf := array[Sys->ATOMICIO] of byte;
233	for(;;){
234		nr := sys->read(fd, buf, len buf);
235		if(nr < 0){
236			sys->fprint(stderr, "bad read on %s : %r\n", f);
237			return 0;
238		}
239		if(nr <= 0)
240			break;
241		crc = crcm->crc(crcs, buf, nr);
242	}
243	crcm->reset(crcs);
244	return crc;
245}
246
247sort(a: array of Element): array of Element
248{
249	qsort(a, len a);
250	return a;
251}
252
253rmnil(a: array of Element): array of Element
254{
255	n := len a;
256	for(i := 0; i < n; i++)
257		if(a[i] != nil)
258			break;
259	return a[i: n];
260}
261
262uniq(a: array of Element): array of Element
263{
264	n := len a;
265	for(i := 0; i < n-1; ){
266		if(a[i] == a[i+1])
267			a[i+1:] = a[i+2: n--];
268		else
269			i++;
270	}
271	return a[0: n];
272}
273
274qsort(a: array of Element, n: int)
275{
276	i, j: int;
277	t: Element;
278
279	while(n > 1){
280		i = n>>1;
281		t = a[0]; a[0] = a[i]; a[i] = t;
282		i = 0;
283		j = n;
284		for(;;){
285			do
286				i++;
287			while(i < n && a[i] < a[0]);
288			do
289				j--;
290			while(j > 0 && a[j] > a[0]);
291			if(j < i)
292				break;
293			t = a[i]; a[i] = a[j]; a[j] = t;
294		}
295		t = a[0]; a[0] = a[j]; a[j] = t;
296		n = n-j-1;
297		if(j >= n){
298			qsort(a, j);
299			a = a[j+1:];
300		}else{
301			qsort(a[j+1:], n);
302			n = j;
303		}
304	}
305}
306