xref: /plan9-contrib/sys/src/9/port/devsrv.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 #include	"devtab.h"
9 
10 typedef struct Srv Srv;
11 struct Srv
12 {
13 	char	name[NAMELEN];
14 	char	owner[NAMELEN];
15 	ulong	perm;
16 	Chan	*chan;
17 	Srv	*link;
18 	ulong	path;
19 };
20 
21 static QLock	srvlk;
22 static Srv	*srv;
23 static int	path;
24 
25 int
26 srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
27 {
28 	Srv *sp;
29 
30 	USED(tab);
31 	USED(ntab);
32 	qlock(&srvlk);
33 	for(sp = srv; sp && s; sp = sp->link)
34 		s--;
35 
36 	if(sp == 0) {
37 		qunlock(&srvlk);
38 		return -1;
39 	}
40 	devdir(c, (Qid){sp->path, 0}, sp->name, 0, sp->owner, sp->perm, dp);
41 	qunlock(&srvlk);
42 	return 1;
43 }
44 
45 void
46 srvinit(void)
47 {
48 	path = 1;
49 }
50 
51 void
52 srvreset(void)
53 {
54 }
55 
56 Chan*
57 srvattach(char *spec)
58 {
59 	return devattach('s', spec);
60 }
61 
62 Chan*
63 srvclone(Chan *c, Chan *nc)
64 {
65 	return devclone(c, nc);
66 }
67 
68 int
69 srvwalk(Chan *c, char *name)
70 {
71 	return devwalk(c, name, 0, 0, srvgen);
72 }
73 
74 void
75 srvstat(Chan *c, char *db)
76 {
77 	devstat(c, db, 0, 0, srvgen);
78 }
79 
80 Chan*
81 srvopen(Chan *c, int omode)
82 {
83 	Srv *sp;
84 
85 	if(c->qid.path == CHDIR){
86 		if(omode != OREAD)
87 			error(Eisdir);
88 		c->mode = omode;
89 		c->flag |= COPEN;
90 		c->offset = 0;
91 		return c;
92 	}
93 	qlock(&srvlk);
94 	if(waserror()){
95 		qunlock(&srvlk);
96 		nexterror();
97 	}
98 
99 	for(sp = srv; sp; sp = sp->link)
100 		if(sp->path == c->qid.path)
101 			break;
102 
103 	if(sp == 0 || sp->chan == 0)
104 		error(Eshutdown);
105 
106 	if(omode&OTRUNC)
107 		error(Eperm);
108 	if(omode!=sp->chan->mode && sp->chan->mode!=ORDWR)
109 		error(Eperm);
110 
111 	close(c);
112 	incref(sp->chan);
113 	qunlock(&srvlk);
114 	poperror();
115 	return sp->chan;
116 }
117 
118 void
119 srvcreate(Chan *c, char *name, int omode, ulong perm)
120 {
121 	Srv *sp;
122 
123 	if(omode != OWRITE)
124 		error(Eperm);
125 
126 	sp = malloc(sizeof(Srv));
127 	if(sp == 0)
128 		error(Enomem);
129 
130 	qlock(&srvlk);
131 	if(waserror()){
132 		qunlock(&srvlk);
133 		nexterror();
134 	}
135 	sp->path = path++;
136 	sp->link = srv;
137 	c->qid.path = sp->path;
138 	srv = sp;
139 	qunlock(&srvlk);
140 	poperror();
141 
142 	strncpy(sp->name, name, NAMELEN);
143 	strncpy(sp->owner, u->p->user, NAMELEN);
144 	sp->perm = perm&0777;
145 
146 	c->flag |= COPEN;
147 	c->mode = OWRITE;
148 }
149 
150 void
151 srvremove(Chan *c)
152 {
153 	Srv *sp, **l;
154 
155 	if(c->qid.path == CHDIR)
156 		error(Eperm);
157 
158 	qlock(&srvlk);
159 	if(waserror()){
160 		qunlock(&srvlk);
161 		nexterror();
162 	}
163 	l = &srv;
164 	for(sp = *l; sp; sp = sp->link) {
165 		if(sp->path == c->qid.path)
166 			break;
167 
168 		l = &sp->link;
169 	}
170 	if(sp == 0)
171 		error(Enonexist);
172 
173 	if(strcmp(sp->name, "boot") == 0)
174 		error(Eperm);
175 
176 	*l = sp->link;
177 	qunlock(&srvlk);
178 	poperror();
179 
180 	if(sp->chan)
181 		close(sp->chan);
182 	free(sp);
183 }
184 
185 void
186 srvwstat(Chan *c, char *dp)
187 {
188 	USED(c, dp);
189 	error(Egreg);
190 }
191 
192 void
193 srvclose(Chan *c)
194 {
195 	USED(c);
196 }
197 
198 long
199 srvread(Chan *c, void *va, long n, ulong offset)
200 {
201 	USED(offset);
202 	isdir(c);
203 	return devdirread(c, va, n, 0, 0, srvgen);
204 }
205 
206 long
207 srvwrite(Chan *c, void *va, long n, ulong offset)
208 {
209 	Srv *sp;
210 	Chan *c1;
211 	int fd;
212 	char buf[32];
213 
214 	USED(offset);
215 	if(n >= sizeof buf)
216 		error(Egreg);
217 	memmove(buf, va, n);	/* so we can NUL-terminate */
218 	buf[n] = 0;
219 	fd = strtoul(buf, 0, 0);
220 
221 	c1 = fdtochan(fd, -1, 0, 1);	/* error check only */
222 
223 	qlock(&srvlk);
224 	if(waserror()) {
225 		qunlock(&srvlk);
226 		close(c1);
227 		nexterror();
228 	}
229 	for(sp = srv; sp; sp = sp->link)
230 		if(sp->path == c->qid.path)
231 			break;
232 
233 	if(sp == 0)
234 		error(Enonexist);
235 
236 	if(sp->chan)
237 		panic("srvwrite");
238 
239 	sp->chan = c1;
240 	qunlock(&srvlk);
241 	poperror();
242 	return n;
243 }
244