xref: /inferno-os/appl/cmd/install/mkproto.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1#
2# Copyright © 2000 Vita Nuova (Holdings) Limited.  All rights reserved.
3#
4
5implement Mkproto;
6
7# make a proto description of the directory or file
8
9include "sys.m";
10	sys: Sys;
11
12include "draw.m";
13
14include "readdir.m";
15	readdir: Readdir;
16
17include "bufio.m";
18	bufio: Bufio;
19	Iobuf: import bufio;
20
21Mkproto: module
22{
23	init: fn(ctxt: ref Draw->Context, argv: list of string);
24};
25
26usage()
27{
28	sys->fprint(sys->fildes(2), "Usage: mkproto [ file|directory ... ]\n");
29	raise "fail:usage";
30}
31
32not: list of string;
33bout: ref Iobuf;
34
35init(nil: ref Draw->Context, argv: list of string)
36{
37	sys = load Sys Sys->PATH;
38	readdir = load Readdir Readdir->PATH;
39	bufio = load Bufio Bufio->PATH;
40
41	bout = bufio->fopen(sys->fildes(1), Bufio->OWRITE);
42	argv = tl argv;
43	while (argv != nil && hd argv != nil && (hd argv)[0] == '-') {
44		not = (hd argv)[1:] :: not;
45		argv = tl argv;
46	}
47	if (argv == nil)
48		visit(".", nil, -1);
49	else if (tl argv == nil)
50		visit(hd argv, nil, -1);
51	else {
52		for ( ; argv != nil; argv = tl argv)
53			visit(hd argv, hd argv, 0);
54	}
55	bout.flush();
56}
57
58warn(s: string)
59{
60	sys->fprint(sys->fildes(2), "mkproto: %s\n", s);
61}
62
63visit(fulln: string, reln: string, depth: int)
64{
65	if (depth == 0) {
66		for (n := not; n != nil; n = tl n) {
67			if (hd n == reln) {
68				# sys->fprint(stderr, "skipping %s\n", reln);
69				return;
70			}
71		}
72		# sys->fprint(stderr, "doing %s\n", reln);
73	}
74	(ok, d) := sys->stat(fulln);
75	if(ok < 0){
76		warn(sys->sprint("cannot stat %s: %r", fulln));
77		return;
78	}
79	if (depth >= 0)
80		visitf(fulln, reln, d, depth);
81	if (d.mode & Sys->DMDIR)
82		visitd(fulln, reln, d, depth);
83}
84
85visitd(fulln: string, nil: string, nil: Sys->Dir, depth: int)
86{
87	(dir, n) := readdir->init(fulln, Readdir->NAME|Readdir->COMPACT);
88	for (i := 0; i < n; i++) {
89		path := "/"+dir[i].name;
90		visit(fulln+path, dir[i].name, depth+1);
91	}
92}
93
94visitf(nil: string, reln: string, nil: Sys->Dir, depth: int)
95{
96	for (i := 0; i < depth; i++)
97		bout.putc('\t');
98	bout.puts(sys->sprint("%q\n", reln));
99}
100