1715d0f95SDavid du Colombier /*
2715d0f95SDavid du Colombier * partfs - serve an underlying file, with devsd-style partitions
3715d0f95SDavid du Colombier */
4715d0f95SDavid du Colombier #include <u.h>
5715d0f95SDavid du Colombier #include <libc.h>
6715d0f95SDavid du Colombier #include <auth.h>
7715d0f95SDavid du Colombier #include <fcall.h>
8715d0f95SDavid du Colombier #include <thread.h>
9715d0f95SDavid du Colombier #include <9p.h>
10715d0f95SDavid du Colombier
11715d0f95SDavid du Colombier typedef struct Part Part;
12715d0f95SDavid du Colombier struct Part
13715d0f95SDavid du Colombier {
14715d0f95SDavid du Colombier int inuse;
15715d0f95SDavid du Colombier int vers;
16715d0f95SDavid du Colombier ulong mode;
17715d0f95SDavid du Colombier char *name;
18715d0f95SDavid du Colombier vlong offset; /* in sectors */
19715d0f95SDavid du Colombier vlong length; /* in sectors */
20715d0f95SDavid du Colombier };
21715d0f95SDavid du Colombier
22715d0f95SDavid du Colombier enum
23715d0f95SDavid du Colombier {
24715d0f95SDavid du Colombier Qroot = 0,
25715d0f95SDavid du Colombier Qdir,
26715d0f95SDavid du Colombier Qctl,
27715d0f95SDavid du Colombier Qpart,
28715d0f95SDavid du Colombier };
29715d0f95SDavid du Colombier
30715d0f95SDavid du Colombier int fd = -1, ctlfd = -1;
31715d0f95SDavid du Colombier int rdonly;
32715d0f95SDavid du Colombier ulong ctlmode = 0666;
33715d0f95SDavid du Colombier ulong time0;
34715d0f95SDavid du Colombier vlong nsect, sectsize;
35715d0f95SDavid du Colombier
36715d0f95SDavid du Colombier char *inquiry = "partfs hard drive";
37715d0f95SDavid du Colombier char *sdname = "sdXX";
38715d0f95SDavid du Colombier Part tab[64];
39715d0f95SDavid du Colombier
40715d0f95SDavid du Colombier char*
ctlstring(void)41715d0f95SDavid du Colombier ctlstring(void)
42715d0f95SDavid du Colombier {
43715d0f95SDavid du Colombier Part *p;
44715d0f95SDavid du Colombier Fmt fmt;
45715d0f95SDavid du Colombier
46715d0f95SDavid du Colombier fmtstrinit(&fmt);
47715d0f95SDavid du Colombier fmtprint(&fmt, "inquiry %s\n", inquiry);
48715d0f95SDavid du Colombier fmtprint(&fmt, "geometry %lld %lld\n", nsect, sectsize);
49715d0f95SDavid du Colombier for (p = tab; p < tab + nelem(tab); p++)
50715d0f95SDavid du Colombier if (p->inuse)
51715d0f95SDavid du Colombier fmtprint(&fmt, "part %s %lld %lld\n",
52715d0f95SDavid du Colombier p->name, p->offset, p->length);
53715d0f95SDavid du Colombier return fmtstrflush(&fmt);
54715d0f95SDavid du Colombier }
55715d0f95SDavid du Colombier
56715d0f95SDavid du Colombier int
addpart(char * name,vlong start,vlong end)57715d0f95SDavid du Colombier addpart(char *name, vlong start, vlong end)
58715d0f95SDavid du Colombier {
59715d0f95SDavid du Colombier Part *p;
60715d0f95SDavid du Colombier
61715d0f95SDavid du Colombier if(start < 0 || start > end || end > nsect){
62715d0f95SDavid du Colombier werrstr("bad partition boundaries");
63715d0f95SDavid du Colombier return -1;
64715d0f95SDavid du Colombier }
65715d0f95SDavid du Colombier
66715d0f95SDavid du Colombier if (strcmp(name, "ctl") == 0 || strcmp(name, "data") == 0) {
67715d0f95SDavid du Colombier werrstr("partition name already in use");
68715d0f95SDavid du Colombier return -1;
69715d0f95SDavid du Colombier }
70715d0f95SDavid du Colombier for (p = tab; p < tab + nelem(tab) && p->inuse; p++)
71715d0f95SDavid du Colombier if (strcmp(p->name, name) == 0) {
72715d0f95SDavid du Colombier werrstr("partition name already in use");
73715d0f95SDavid du Colombier return -1;
74715d0f95SDavid du Colombier }
75715d0f95SDavid du Colombier if(p == tab + nelem(tab)){
76715d0f95SDavid du Colombier werrstr("no free partition slots");
77715d0f95SDavid du Colombier return -1;
78715d0f95SDavid du Colombier }
79715d0f95SDavid du Colombier
80715d0f95SDavid du Colombier p->inuse = 1;
81715d0f95SDavid du Colombier free(p->name);
82715d0f95SDavid du Colombier p->name = estrdup9p(name);
83715d0f95SDavid du Colombier p->offset = start;
84715d0f95SDavid du Colombier p->length = end - start;
85715d0f95SDavid du Colombier p->mode = ctlmode;
86715d0f95SDavid du Colombier p->vers++;
87715d0f95SDavid du Colombier return 0;
88715d0f95SDavid du Colombier }
89715d0f95SDavid du Colombier
90715d0f95SDavid du Colombier int
delpart(char * s)91715d0f95SDavid du Colombier delpart(char *s)
92715d0f95SDavid du Colombier {
93715d0f95SDavid du Colombier Part *p;
94715d0f95SDavid du Colombier
95715d0f95SDavid du Colombier for (p = tab; p < tab + nelem(tab); p++)
96715d0f95SDavid du Colombier if(p->inuse && strcmp(p->name, s) == 0)
97715d0f95SDavid du Colombier break;
98715d0f95SDavid du Colombier if(p == tab + nelem(tab)){
99715d0f95SDavid du Colombier werrstr("partition not found");
100715d0f95SDavid du Colombier return -1;
101715d0f95SDavid du Colombier }
102715d0f95SDavid du Colombier
103715d0f95SDavid du Colombier p->inuse = 0;
104715d0f95SDavid du Colombier free(p->name);
105715d0f95SDavid du Colombier p->name = nil;
106715d0f95SDavid du Colombier return 0;
107715d0f95SDavid du Colombier }
108715d0f95SDavid du Colombier
109715d0f95SDavid du Colombier static void
addparts(char * buf)110*8c055935SDavid du Colombier addparts(char *buf)
111*8c055935SDavid du Colombier {
112*8c055935SDavid du Colombier char *f[4], *p, *q;
113*8c055935SDavid du Colombier
114*8c055935SDavid du Colombier /*
115*8c055935SDavid du Colombier * Use partitions passed from boot program,
116*8c055935SDavid du Colombier * e.g.
117*8c055935SDavid du Colombier * sdC0part=dos 63 123123/plan9 123123 456456
118*8c055935SDavid du Colombier * This happens before /boot sets hostname so the
119*8c055935SDavid du Colombier * partitions will have the null-string for user.
120*8c055935SDavid du Colombier */
121*8c055935SDavid du Colombier for(p = buf; p != nil; p = q){
122*8c055935SDavid du Colombier if(q = strchr(p, '/'))
123*8c055935SDavid du Colombier *q++ = '\0';
124*8c055935SDavid du Colombier if(tokenize(p, f, nelem(f)) >= 3 &&
125*8c055935SDavid du Colombier addpart(f[0], strtoull(f[1], 0, 0), strtoull(f[2], 0, 0)) < 0)
126*8c055935SDavid du Colombier fprint(2, "%s: addpart %s: %r\n", argv0, f[0]);
127*8c055935SDavid du Colombier }
128*8c055935SDavid du Colombier }
129*8c055935SDavid du Colombier
130*8c055935SDavid du Colombier static void
ctlwrite0(Req * r,char * msg,Cmdbuf * cb)131715d0f95SDavid du Colombier ctlwrite0(Req *r, char *msg, Cmdbuf *cb)
132715d0f95SDavid du Colombier {
133715d0f95SDavid du Colombier vlong start, end;
134715d0f95SDavid du Colombier Part *p;
135715d0f95SDavid du Colombier
136715d0f95SDavid du Colombier r->ofcall.count = r->ifcall.count;
137715d0f95SDavid du Colombier
138715d0f95SDavid du Colombier if(cb->nf < 1){
139715d0f95SDavid du Colombier respond(r, "empty control message");
140715d0f95SDavid du Colombier return;
141715d0f95SDavid du Colombier }
142715d0f95SDavid du Colombier
143715d0f95SDavid du Colombier if(strcmp(cb->f[0], "part") == 0){
144715d0f95SDavid du Colombier if(cb->nf != 4){
145715d0f95SDavid du Colombier respondcmderror(r, cb, "part takes 3 args");
146715d0f95SDavid du Colombier return;
147715d0f95SDavid du Colombier }
148715d0f95SDavid du Colombier start = strtoll(cb->f[2], 0, 0);
149715d0f95SDavid du Colombier end = strtoll(cb->f[3], 0, 0);
150715d0f95SDavid du Colombier if(addpart(cb->f[1], start, end) < 0){
151715d0f95SDavid du Colombier respondcmderror(r, cb, "%r");
152715d0f95SDavid du Colombier return;
153715d0f95SDavid du Colombier }
154715d0f95SDavid du Colombier }
155715d0f95SDavid du Colombier else if(strcmp(cb->f[0], "delpart") == 0){
156715d0f95SDavid du Colombier if(cb->nf != 2){
157715d0f95SDavid du Colombier respondcmderror(r, cb, "delpart takes 1 arg");
158715d0f95SDavid du Colombier return;
159715d0f95SDavid du Colombier }
160715d0f95SDavid du Colombier if(delpart(cb->f[1]) < 0){
161715d0f95SDavid du Colombier respondcmderror(r, cb, "%r");
162715d0f95SDavid du Colombier return;
163715d0f95SDavid du Colombier }
164715d0f95SDavid du Colombier }
165715d0f95SDavid du Colombier else if(strcmp(cb->f[0], "inquiry") == 0){
166715d0f95SDavid du Colombier if(cb->nf != 2){
167715d0f95SDavid du Colombier respondcmderror(r, cb, "inquiry takes 1 arg");
168715d0f95SDavid du Colombier return;
169715d0f95SDavid du Colombier }
170715d0f95SDavid du Colombier free(inquiry);
171715d0f95SDavid du Colombier inquiry = estrdup9p(cb->f[1]);
172715d0f95SDavid du Colombier }
173715d0f95SDavid du Colombier else if(strcmp(cb->f[0], "geometry") == 0){
174715d0f95SDavid du Colombier if(cb->nf != 3){
175715d0f95SDavid du Colombier respondcmderror(r, cb, "geometry takes 2 args");
176715d0f95SDavid du Colombier return;
177715d0f95SDavid du Colombier }
178715d0f95SDavid du Colombier nsect = strtoll(cb->f[1], 0, 0);
179715d0f95SDavid du Colombier sectsize = strtoll(cb->f[2], 0, 0);
180715d0f95SDavid du Colombier if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 &&
181715d0f95SDavid du Colombier tab[0].vers == 0){
182715d0f95SDavid du Colombier tab[0].offset = 0;
183715d0f95SDavid du Colombier tab[0].length = nsect;
184715d0f95SDavid du Colombier }
185715d0f95SDavid du Colombier for(p = tab; p < tab + nelem(tab); p++)
186715d0f95SDavid du Colombier if(p->inuse && p->offset + p->length > nsect){
187715d0f95SDavid du Colombier p->inuse = 0;
188715d0f95SDavid du Colombier free(p->name);
189715d0f95SDavid du Colombier p->name = nil;
190715d0f95SDavid du Colombier }
191715d0f95SDavid du Colombier } else
192715d0f95SDavid du Colombier /* pass through to underlying ctl file, if any */
193715d0f95SDavid du Colombier if (write(ctlfd, msg, r->ifcall.count) != r->ifcall.count) {
194715d0f95SDavid du Colombier respondcmderror(r, cb, "%r");
195715d0f95SDavid du Colombier return;
196715d0f95SDavid du Colombier }
197715d0f95SDavid du Colombier respond(r, nil);
198715d0f95SDavid du Colombier }
199715d0f95SDavid du Colombier
200715d0f95SDavid du Colombier void
ctlwrite(Req * r)201715d0f95SDavid du Colombier ctlwrite(Req *r)
202715d0f95SDavid du Colombier {
203715d0f95SDavid du Colombier char *msg;
204715d0f95SDavid du Colombier Cmdbuf *cb;
205715d0f95SDavid du Colombier
206715d0f95SDavid du Colombier r->ofcall.count = r->ifcall.count;
207715d0f95SDavid du Colombier
208715d0f95SDavid du Colombier msg = emalloc9p(r->ifcall.count+1);
209715d0f95SDavid du Colombier memmove(msg, r->ifcall.data, r->ifcall.count);
210715d0f95SDavid du Colombier msg[r->ifcall.count] = '\0';
211715d0f95SDavid du Colombier
212715d0f95SDavid du Colombier cb = parsecmd(r->ifcall.data, r->ifcall.count);
213715d0f95SDavid du Colombier ctlwrite0(r, msg, cb);
214715d0f95SDavid du Colombier
215715d0f95SDavid du Colombier free(cb);
216715d0f95SDavid du Colombier free(msg);
217715d0f95SDavid du Colombier }
218715d0f95SDavid du Colombier
219715d0f95SDavid du Colombier int
rootgen(int off,Dir * d,void *)220715d0f95SDavid du Colombier rootgen(int off, Dir *d, void*)
221715d0f95SDavid du Colombier {
222715d0f95SDavid du Colombier memset(d, 0, sizeof *d);
223715d0f95SDavid du Colombier d->atime = time0;
224715d0f95SDavid du Colombier d->mtime = time0;
225715d0f95SDavid du Colombier if(off == 0){
226715d0f95SDavid du Colombier d->name = estrdup9p(sdname);
227715d0f95SDavid du Colombier d->mode = DMDIR|0777;
228715d0f95SDavid du Colombier d->qid.path = Qdir;
229715d0f95SDavid du Colombier d->qid.type = QTDIR;
230715d0f95SDavid du Colombier d->uid = estrdup9p("partfs");
231715d0f95SDavid du Colombier d->gid = estrdup9p("partfs");
232715d0f95SDavid du Colombier d->muid = estrdup9p("");
233715d0f95SDavid du Colombier return 0;
234715d0f95SDavid du Colombier }
235715d0f95SDavid du Colombier return -1;
236715d0f95SDavid du Colombier }
237715d0f95SDavid du Colombier
238715d0f95SDavid du Colombier int
dirgen(int off,Dir * d,void *)239715d0f95SDavid du Colombier dirgen(int off, Dir *d, void*)
240715d0f95SDavid du Colombier {
241715d0f95SDavid du Colombier int n;
242715d0f95SDavid du Colombier Part *p;
243715d0f95SDavid du Colombier
244715d0f95SDavid du Colombier memset(d, 0, sizeof *d);
245715d0f95SDavid du Colombier d->atime = time0;
246715d0f95SDavid du Colombier d->mtime = time0;
247715d0f95SDavid du Colombier if(off == 0){
248715d0f95SDavid du Colombier d->name = estrdup9p("ctl");
249715d0f95SDavid du Colombier d->mode = ctlmode;
250715d0f95SDavid du Colombier d->qid.path = Qctl;
251715d0f95SDavid du Colombier goto Have;
252715d0f95SDavid du Colombier }
253715d0f95SDavid du Colombier
254715d0f95SDavid du Colombier off--;
255715d0f95SDavid du Colombier n = 0;
256715d0f95SDavid du Colombier for(p = tab; p < tab + nelem(tab); p++, n++){
257715d0f95SDavid du Colombier if(!p->inuse)
258715d0f95SDavid du Colombier continue;
259715d0f95SDavid du Colombier if(n == off){
260715d0f95SDavid du Colombier d->name = estrdup9p(p->name);
261715d0f95SDavid du Colombier d->length = p->length*sectsize;
262715d0f95SDavid du Colombier d->mode = p->mode;
263715d0f95SDavid du Colombier d->qid.path = Qpart + p - tab;
264715d0f95SDavid du Colombier d->qid.vers = p->vers;
265715d0f95SDavid du Colombier goto Have;
266715d0f95SDavid du Colombier }
267715d0f95SDavid du Colombier }
268715d0f95SDavid du Colombier return -1;
269715d0f95SDavid du Colombier
270715d0f95SDavid du Colombier Have:
271715d0f95SDavid du Colombier d->uid = estrdup9p("partfs");
272715d0f95SDavid du Colombier d->gid = estrdup9p("partfs");
273715d0f95SDavid du Colombier d->muid = estrdup9p("");
274715d0f95SDavid du Colombier return 0;
275715d0f95SDavid du Colombier }
276715d0f95SDavid du Colombier
277715d0f95SDavid du Colombier int
rdwrpart(Req * r)278715d0f95SDavid du Colombier rdwrpart(Req *r)
279715d0f95SDavid du Colombier {
280715d0f95SDavid du Colombier int q;
281715d0f95SDavid du Colombier long count, tot;
282715d0f95SDavid du Colombier vlong offset;
283715d0f95SDavid du Colombier uchar *dat;
284715d0f95SDavid du Colombier Part *p;
285715d0f95SDavid du Colombier
286715d0f95SDavid du Colombier q = r->fid->qid.path - Qpart;
287715d0f95SDavid du Colombier if(q < 0 || q > nelem(tab) || !tab[q].inuse ||
288715d0f95SDavid du Colombier tab[q].vers != r->fid->qid.vers){
289715d0f95SDavid du Colombier respond(r, "unknown partition");
290715d0f95SDavid du Colombier return -1;
291715d0f95SDavid du Colombier }
292715d0f95SDavid du Colombier p = &tab[q];
293715d0f95SDavid du Colombier
294715d0f95SDavid du Colombier offset = r->ifcall.offset;
295715d0f95SDavid du Colombier count = r->ifcall.count;
296715d0f95SDavid du Colombier if(offset < 0){
297715d0f95SDavid du Colombier respond(r, "negative offset");
298715d0f95SDavid du Colombier return -1;
299715d0f95SDavid du Colombier }
300715d0f95SDavid du Colombier if(count < 0){
301715d0f95SDavid du Colombier respond(r, "negative count");
302715d0f95SDavid du Colombier return -1;
303715d0f95SDavid du Colombier }
304715d0f95SDavid du Colombier if(offset > p->length*sectsize){
305715d0f95SDavid du Colombier respond(r, "offset past end of partition");
306715d0f95SDavid du Colombier return -1;
307715d0f95SDavid du Colombier }
308715d0f95SDavid du Colombier if(offset+count > p->length*sectsize)
309715d0f95SDavid du Colombier count = p->length*sectsize - offset;
310715d0f95SDavid du Colombier offset += p->offset*sectsize;
311715d0f95SDavid du Colombier
312715d0f95SDavid du Colombier if(r->ifcall.type == Tread)
313715d0f95SDavid du Colombier dat = (uchar*)r->ofcall.data;
314715d0f95SDavid du Colombier else
315715d0f95SDavid du Colombier dat = (uchar*)r->ifcall.data;
316715d0f95SDavid du Colombier
317715d0f95SDavid du Colombier /* pass i/o through to underlying file */
318715d0f95SDavid du Colombier seek(fd, offset, 0);
319715d0f95SDavid du Colombier if (r->ifcall.type == Twrite) {
320715d0f95SDavid du Colombier tot = write(fd, dat, count);
321715d0f95SDavid du Colombier if (tot != count) {
322715d0f95SDavid du Colombier respond(r, "%r");
323715d0f95SDavid du Colombier return -1;
324715d0f95SDavid du Colombier }
325715d0f95SDavid du Colombier } else {
326715d0f95SDavid du Colombier tot = read(fd, dat, count);
327715d0f95SDavid du Colombier if (tot < 0) {
328715d0f95SDavid du Colombier respond(r, "%r");
329715d0f95SDavid du Colombier return -1;
330715d0f95SDavid du Colombier }
331715d0f95SDavid du Colombier }
332715d0f95SDavid du Colombier r->ofcall.count = tot;
333715d0f95SDavid du Colombier respond(r, nil);
334715d0f95SDavid du Colombier return 0;
335715d0f95SDavid du Colombier }
336715d0f95SDavid du Colombier
337715d0f95SDavid du Colombier void
fsread(Req * r)338715d0f95SDavid du Colombier fsread(Req *r)
339715d0f95SDavid du Colombier {
340715d0f95SDavid du Colombier char *s;
341715d0f95SDavid du Colombier
342715d0f95SDavid du Colombier switch((int)r->fid->qid.path){
343715d0f95SDavid du Colombier case Qroot:
344715d0f95SDavid du Colombier dirread9p(r, rootgen, nil);
345715d0f95SDavid du Colombier break;
346715d0f95SDavid du Colombier case Qdir:
347715d0f95SDavid du Colombier dirread9p(r, dirgen, nil);
348715d0f95SDavid du Colombier break;
349715d0f95SDavid du Colombier case Qctl:
350715d0f95SDavid du Colombier s = ctlstring();
351715d0f95SDavid du Colombier readstr(r, s);
352715d0f95SDavid du Colombier free(s);
353715d0f95SDavid du Colombier break;
354715d0f95SDavid du Colombier default:
355715d0f95SDavid du Colombier rdwrpart(r);
356715d0f95SDavid du Colombier return;
357715d0f95SDavid du Colombier }
358715d0f95SDavid du Colombier respond(r, nil);
359715d0f95SDavid du Colombier }
360715d0f95SDavid du Colombier
361715d0f95SDavid du Colombier void
fswrite(Req * r)362715d0f95SDavid du Colombier fswrite(Req *r)
363715d0f95SDavid du Colombier {
364715d0f95SDavid du Colombier switch((int)r->fid->qid.path){
365715d0f95SDavid du Colombier case Qroot:
366715d0f95SDavid du Colombier case Qdir:
367715d0f95SDavid du Colombier respond(r, "write to a directory?");
368715d0f95SDavid du Colombier break;
369715d0f95SDavid du Colombier case Qctl:
370715d0f95SDavid du Colombier ctlwrite(r);
371715d0f95SDavid du Colombier break;
372715d0f95SDavid du Colombier default:
373715d0f95SDavid du Colombier rdwrpart(r);
374715d0f95SDavid du Colombier break;
375715d0f95SDavid du Colombier }
376715d0f95SDavid du Colombier }
377715d0f95SDavid du Colombier
378715d0f95SDavid du Colombier void
fsopen(Req * r)379715d0f95SDavid du Colombier fsopen(Req *r)
380715d0f95SDavid du Colombier {
381715d0f95SDavid du Colombier if(r->ifcall.mode&ORCLOSE)
382715d0f95SDavid du Colombier respond(r, "cannot open ORCLOSE");
383715d0f95SDavid du Colombier
384715d0f95SDavid du Colombier switch((int)r->fid->qid.path){
385715d0f95SDavid du Colombier case Qroot:
386715d0f95SDavid du Colombier case Qdir:
387715d0f95SDavid du Colombier if(r->ifcall.mode != OREAD){
388715d0f95SDavid du Colombier respond(r, "bad mode for directory open");
389715d0f95SDavid du Colombier return;
390715d0f95SDavid du Colombier }
391715d0f95SDavid du Colombier }
392715d0f95SDavid du Colombier
393715d0f95SDavid du Colombier respond(r, nil);
394715d0f95SDavid du Colombier }
395715d0f95SDavid du Colombier
396715d0f95SDavid du Colombier void
fsstat(Req * r)397715d0f95SDavid du Colombier fsstat(Req *r)
398715d0f95SDavid du Colombier {
399715d0f95SDavid du Colombier int q;
400715d0f95SDavid du Colombier Dir *d;
401715d0f95SDavid du Colombier Part *p;
402715d0f95SDavid du Colombier
403715d0f95SDavid du Colombier d = &r->d;
404715d0f95SDavid du Colombier memset(d, 0, sizeof *d);
405715d0f95SDavid du Colombier d->qid = r->fid->qid;
406715d0f95SDavid du Colombier d->atime = d->mtime = time0;
407715d0f95SDavid du Colombier q = r->fid->qid.path;
408715d0f95SDavid du Colombier switch(q){
409715d0f95SDavid du Colombier case Qroot:
410715d0f95SDavid du Colombier d->name = estrdup9p("/");
411715d0f95SDavid du Colombier d->mode = DMDIR|0777;
412715d0f95SDavid du Colombier break;
413715d0f95SDavid du Colombier
414715d0f95SDavid du Colombier case Qdir:
415715d0f95SDavid du Colombier d->name = estrdup9p(sdname);
416715d0f95SDavid du Colombier d->mode = DMDIR|0777;
417715d0f95SDavid du Colombier break;
418715d0f95SDavid du Colombier
419715d0f95SDavid du Colombier case Qctl:
420715d0f95SDavid du Colombier d->name = estrdup9p("ctl");
421715d0f95SDavid du Colombier d->mode = 0666;
422715d0f95SDavid du Colombier break;
423715d0f95SDavid du Colombier
424715d0f95SDavid du Colombier default:
425715d0f95SDavid du Colombier q -= Qpart;
426715d0f95SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse == 0 ||
427715d0f95SDavid du Colombier r->fid->qid.vers != tab[q].vers){
428715d0f95SDavid du Colombier respond(r, "partition no longer exists");
429715d0f95SDavid du Colombier return;
430715d0f95SDavid du Colombier }
431715d0f95SDavid du Colombier p = &tab[q];
432715d0f95SDavid du Colombier d->name = estrdup9p(p->name);
433715d0f95SDavid du Colombier d->length = p->length * sectsize;
434715d0f95SDavid du Colombier d->mode = p->mode;
435715d0f95SDavid du Colombier break;
436715d0f95SDavid du Colombier }
437715d0f95SDavid du Colombier
438715d0f95SDavid du Colombier d->uid = estrdup9p("partfs");
439715d0f95SDavid du Colombier d->gid = estrdup9p("partfs");
440715d0f95SDavid du Colombier d->muid = estrdup9p("");
441715d0f95SDavid du Colombier respond(r, nil);
442715d0f95SDavid du Colombier }
443715d0f95SDavid du Colombier
444715d0f95SDavid du Colombier void
fsattach(Req * r)445715d0f95SDavid du Colombier fsattach(Req *r)
446715d0f95SDavid du Colombier {
447715d0f95SDavid du Colombier char *spec;
448715d0f95SDavid du Colombier
449715d0f95SDavid du Colombier spec = r->ifcall.aname;
450715d0f95SDavid du Colombier if(spec && spec[0]){
451715d0f95SDavid du Colombier respond(r, "invalid attach specifier");
452715d0f95SDavid du Colombier return;
453715d0f95SDavid du Colombier }
454715d0f95SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR};
455715d0f95SDavid du Colombier r->fid->qid = r->ofcall.qid;
456715d0f95SDavid du Colombier respond(r, nil);
457715d0f95SDavid du Colombier }
458715d0f95SDavid du Colombier
459715d0f95SDavid du Colombier char*
fswalk1(Fid * fid,char * name,Qid * qid)460715d0f95SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid)
461715d0f95SDavid du Colombier {
462715d0f95SDavid du Colombier Part *p;
463715d0f95SDavid du Colombier
464715d0f95SDavid du Colombier switch((int)fid->qid.path){
465715d0f95SDavid du Colombier case Qroot:
466715d0f95SDavid du Colombier if(strcmp(name, sdname) == 0){
467715d0f95SDavid du Colombier fid->qid.path = Qdir;
468715d0f95SDavid du Colombier fid->qid.type = QTDIR;
469715d0f95SDavid du Colombier *qid = fid->qid;
470715d0f95SDavid du Colombier return nil;
471715d0f95SDavid du Colombier }
472715d0f95SDavid du Colombier break;
473715d0f95SDavid du Colombier case Qdir:
474715d0f95SDavid du Colombier if(strcmp(name, "ctl") == 0){
475715d0f95SDavid du Colombier fid->qid.path = Qctl;
476715d0f95SDavid du Colombier fid->qid.vers = 0;
477715d0f95SDavid du Colombier fid->qid.type = 0;
478715d0f95SDavid du Colombier *qid = fid->qid;
479715d0f95SDavid du Colombier return nil;
480715d0f95SDavid du Colombier }
481715d0f95SDavid du Colombier for(p = tab; p < tab + nelem(tab); p++)
482715d0f95SDavid du Colombier if(p->inuse && strcmp(p->name, name) == 0){
483715d0f95SDavid du Colombier fid->qid.path = p - tab + Qpart;
484715d0f95SDavid du Colombier fid->qid.vers = p->vers;
485715d0f95SDavid du Colombier fid->qid.type = 0;
486715d0f95SDavid du Colombier *qid = fid->qid;
487715d0f95SDavid du Colombier return nil;
488715d0f95SDavid du Colombier }
489715d0f95SDavid du Colombier break;
490715d0f95SDavid du Colombier }
491715d0f95SDavid du Colombier return "file not found";
492715d0f95SDavid du Colombier }
493715d0f95SDavid du Colombier
494715d0f95SDavid du Colombier Srv fs = {
495715d0f95SDavid du Colombier .attach=fsattach,
496715d0f95SDavid du Colombier .open= fsopen,
497715d0f95SDavid du Colombier .read= fsread,
498715d0f95SDavid du Colombier .write= fswrite,
499715d0f95SDavid du Colombier .stat= fsstat,
500715d0f95SDavid du Colombier .walk1= fswalk1,
501715d0f95SDavid du Colombier };
502715d0f95SDavid du Colombier
503715d0f95SDavid du Colombier char *mtpt = "/dev";
504715d0f95SDavid du Colombier char *srvname;
505715d0f95SDavid du Colombier
506715d0f95SDavid du Colombier void
usage(void)507715d0f95SDavid du Colombier usage(void)
508715d0f95SDavid du Colombier {
509*8c055935SDavid du Colombier fprint(2, "usage: %s [-Dr] [-d sdname] [-m mtpt] [-p 9parts] "
510*8c055935SDavid du Colombier "[-s srvname] diskimage\n", argv0);
511715d0f95SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n");
512715d0f95SDavid du Colombier exits("usage");
513715d0f95SDavid du Colombier }
514715d0f95SDavid du Colombier
515715d0f95SDavid du Colombier void
main(int argc,char ** argv)516715d0f95SDavid du Colombier main(int argc, char **argv)
517715d0f95SDavid du Colombier {
518715d0f95SDavid du Colombier int isdir;
519*8c055935SDavid du Colombier char *file, *cname, *parts;
520715d0f95SDavid du Colombier Dir *dir;
521715d0f95SDavid du Colombier
522715d0f95SDavid du Colombier quotefmtinstall();
523715d0f95SDavid du Colombier time0 = time(0);
524*8c055935SDavid du Colombier parts = nil;
525715d0f95SDavid du Colombier
526715d0f95SDavid du Colombier ARGBEGIN{
527715d0f95SDavid du Colombier case 'D':
528715d0f95SDavid du Colombier chatty9p++;
529715d0f95SDavid du Colombier break;
530950da38cSDavid du Colombier case 'd':
531950da38cSDavid du Colombier sdname = EARGF(usage());
532715d0f95SDavid du Colombier break;
533715d0f95SDavid du Colombier case 'm':
534715d0f95SDavid du Colombier mtpt = EARGF(usage());
535715d0f95SDavid du Colombier break;
536*8c055935SDavid du Colombier case 'p':
537*8c055935SDavid du Colombier parts = EARGF(usage());
538*8c055935SDavid du Colombier break;
539715d0f95SDavid du Colombier case 'r':
540715d0f95SDavid du Colombier rdonly = 1;
541715d0f95SDavid du Colombier break;
542715d0f95SDavid du Colombier case 's':
543715d0f95SDavid du Colombier srvname = EARGF(usage());
544715d0f95SDavid du Colombier break;
545715d0f95SDavid du Colombier default:
546715d0f95SDavid du Colombier usage();
547715d0f95SDavid du Colombier }ARGEND
548715d0f95SDavid du Colombier
549950da38cSDavid du Colombier if(argc != 1)
550715d0f95SDavid du Colombier usage();
551950da38cSDavid du Colombier file = argv[0];
552715d0f95SDavid du Colombier dir = dirstat(file);
553715d0f95SDavid du Colombier if(!dir)
554715d0f95SDavid du Colombier sysfatal("%s: %r", file);
555715d0f95SDavid du Colombier isdir = (dir->mode & DMDIR) != 0;
556715d0f95SDavid du Colombier free(dir);
557715d0f95SDavid du Colombier
558715d0f95SDavid du Colombier if (isdir) {
559715d0f95SDavid du Colombier cname = smprint("%s/ctl", file);
560715d0f95SDavid du Colombier if ((ctlfd = open(cname, ORDWR)) < 0)
561715d0f95SDavid du Colombier sysfatal("open %s: %r", cname);
562715d0f95SDavid du Colombier file = smprint("%s/data", file);
563715d0f95SDavid du Colombier }
564715d0f95SDavid du Colombier if((fd = open(file, rdonly? OREAD: ORDWR)) < 0)
565715d0f95SDavid du Colombier sysfatal("open %s: %r", file);
566715d0f95SDavid du Colombier
567715d0f95SDavid du Colombier sectsize = 512; /* conventional */
568715d0f95SDavid du Colombier dir = dirfstat(fd);
569715d0f95SDavid du Colombier if (dir)
570715d0f95SDavid du Colombier nsect = dir->length / sectsize;
571715d0f95SDavid du Colombier free(dir);
572715d0f95SDavid du Colombier
573715d0f95SDavid du Colombier inquiry = estrdup9p(inquiry);
574715d0f95SDavid du Colombier tab[0].inuse = 1;
575715d0f95SDavid du Colombier tab[0].name = estrdup9p("data");
576715d0f95SDavid du Colombier tab[0].mode = 0666;
577715d0f95SDavid du Colombier tab[0].length = nsect;
578715d0f95SDavid du Colombier
579*8c055935SDavid du Colombier /*
580*8c055935SDavid du Colombier * hack for booting from usb: add 9load partitions.
581*8c055935SDavid du Colombier */
582*8c055935SDavid du Colombier if(parts != nil)
583*8c055935SDavid du Colombier addparts(parts);
584*8c055935SDavid du Colombier
585715d0f95SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE);
586715d0f95SDavid du Colombier exits(nil);
587715d0f95SDavid du Colombier }
588