xref: /inferno-os/os/port/devroot.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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