xref: /inferno-os/os/port/devroot.c (revision 7ef44d652ae9e5e1f5b3465d73684e4a54de73c0)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"../port/error.h"
7 
8 extern Rootdata rootdata[];
9 extern Dirtab roottab[];
10 extern int	rootmaxq;
11 
12 static Chan*
13 rootattach(char *spec)
14 {
15 	int i;
16 	ulong len;
17 	Rootdata *r;
18 
19 	if(*spec)
20 		error(Ebadspec);
21 	for (i = 0; i < rootmaxq; i++){
22 		r = &rootdata[i];
23 		if (r->sizep){
24 			len = *r->sizep;
25 			r->size = len;
26 			roottab[i].length = len;
27 		}
28 	}
29 	return devattach('/', spec);
30 }
31 
32 static int
33 rootgen(Chan *c, char *name, Dirtab *tab, int nd, int s, Dir *dp)
34 {
35 	int p, i;
36 	Rootdata *r;
37 
38 	if(s == DEVDOTDOT){
39 		p = rootdata[c->qid.path].dotdot;
40 		c->qid.path = p;
41 		c->qid.type = QTDIR;
42 		name = "#/";
43 		if(p != 0){
44 			for(i = 0; i < rootmaxq; i++)
45 				if(roottab[i].qid.path == c->qid.path){
46 					name = roottab[i].name;
47 					break;
48 				}
49 		}
50 		devdir(c, c->qid, name, 0, eve, 0555, dp);
51 		return 1;
52 	}
53 	if(name != nil){
54 		isdir(c);
55 		r = &rootdata[(int)c->qid.path];
56 		tab = r->ptr;
57 		for(i=0; i<r->size; i++, tab++)
58 			if(strcmp(tab->name, name) == 0){
59 				devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
60 				return 1;
61 			}
62 		return -1;
63 	}
64 	if(s >= nd)
65 		return -1;
66 	tab += s;
67 	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
68 	return 1;
69 }
70 
71 static Walkqid*
72 rootwalk(Chan *c, Chan *nc, char **name, int nname)
73 {
74 	ulong p;
75 
76 	p = c->qid.path;
77 	if(nname == 0)
78 		p = rootdata[p].dotdot;
79 	return devwalk(c, nc, name, nname, rootdata[p].ptr, rootdata[p].size, rootgen);
80 }
81 
82 static int
83 rootstat(Chan *c, uchar *dp, int n)
84 {
85 	int p;
86 
87 	p = rootdata[c->qid.path].dotdot;
88 	return devstat(c, dp, n, rootdata[p].ptr, rootdata[p].size, rootgen);
89 }
90 
91 static Chan*
92 rootopen(Chan *c, int omode)
93 {
94 	int p;
95 
96 	p = rootdata[c->qid.path].dotdot;
97 	return devopen(c, omode, rootdata[p].ptr, rootdata[p].size, rootgen);
98 }
99 
100 /*
101  * sysremove() knows this is a nop
102  */
103 static void
104 rootclose(Chan*)
105 {
106 }
107 
108 static long
109 rootread(Chan *c, void *buf, long n, vlong offset)
110 {
111 	ulong p, len;
112 	uchar *data;
113 
114 	p = c->qid.path;
115 	if(c->qid.type & QTDIR)
116 		return devdirread(c, buf, n, rootdata[p].ptr, rootdata[p].size, rootgen);
117 	len = rootdata[p].size;
118 	if(offset < 0 || offset >= len)
119 		return 0;
120 	if(offset+n > len)
121 		n = len - offset;
122 	data = rootdata[p].ptr;
123 	memmove(buf, data+offset, n);
124 	return n;
125 }
126 
127 static long
128 rootwrite(Chan*, void*, long, vlong)
129 {
130 	error(Eperm);
131 	return 0;
132 }
133 
134 Dev rootdevtab = {
135 	'/',
136 	"root",
137 
138 	devreset,
139 	devinit,
140 	devshutdown,
141 	rootattach,
142 	rootwalk,
143 	rootstat,
144 	rootopen,
145 	devcreate,
146 	rootclose,
147 	rootread,
148 	devbread,
149 	rootwrite,
150 	devbwrite,
151 	devremove,
152 	devwstat,
153 };
154