1 #include <u.h>
2 #include <libc.h>
3 #include <fcall.h>
4 #include <thread.h>
5 #include <9p.h>
6
7 uint time0;
8
9 enum
10 {
11 Qroot = 0,
12 Qkid,
13 };
14
15 char *kidname;
16 uint kidmode;
17
18 void
fsattach(Req * r)19 fsattach(Req *r)
20 {
21 char *spec;
22
23 spec = r->ifcall.aname;
24 if(spec && spec[0]){
25 respond(r, "invalid attach specifier");
26 return;
27 }
28 r->ofcall.qid = (Qid){Qroot, 0, QTDIR};
29 r->fid->qid = r->ofcall.qid;
30 respond(r, nil);
31 }
32
33 char*
fswalk1(Fid * fid,char * name,Qid * qid)34 fswalk1(Fid *fid, char *name, Qid *qid)
35 {
36 switch((int)fid->qid.path){
37 default:
38 return "path not found";
39 case Qroot:
40 if(strcmp(name, "..") == 0)
41 break;
42 if(strcmp(name, kidname) == 0){
43 fid->qid = (Qid){Qkid, 0, kidmode>>24};
44 break;
45 }
46 return "path not found";
47 case Qkid:
48 if(strcmp(name, "..") == 0){
49 fid->qid = (Qid){Qroot, 0, QTDIR};
50 break;
51 }
52 return "path not found";
53 }
54 *qid = fid->qid;
55 return nil;
56 }
57
58 void
fsstat(Req * r)59 fsstat(Req *r)
60 {
61 int q;
62 Dir *d;
63
64 d = &r->d;
65 memset(d, 0, sizeof *d);
66 q = r->fid->qid.path;
67 d->qid = r->fid->qid;
68 switch(q){
69 case Qroot:
70 d->name = estrdup9p("/");
71 d->mode = DMDIR|0777;
72 break;
73
74 case Qkid:
75 d->name = estrdup9p(kidname);
76 d->mode = kidmode;
77 break;
78 }
79
80 d->atime = d->mtime = time0;
81 d->uid = estrdup9p("stub");
82 d->gid = estrdup9p("stub");
83 d->muid = estrdup9p("");
84 respond(r, nil);
85 }
86
87 int
dirgen(int off,Dir * d,void *)88 dirgen(int off, Dir *d, void*)
89 {
90 if(off != 0)
91 return -1;
92
93 memset(d, 0, sizeof *d);
94 d->atime = d->mtime = time0;
95 d->name = estrdup9p(kidname);
96 d->mode = kidmode;
97 d->qid = (Qid){Qkid, 0, kidmode>>24};
98 d->qid.type = d->mode>>24;
99 d->uid = estrdup9p("stub");
100 d->gid = estrdup9p("stub");
101 d->muid = estrdup9p("");
102 return 0;
103 }
104
105 void
fsread(Req * r)106 fsread(Req *r)
107 {
108 int q;
109
110 q = r->fid->qid.path;
111 switch(q){
112 default:
113 respond(r, "bug");
114 return;
115
116 case Qroot:
117 dirread9p(r, dirgen, nil);
118 respond(r, nil);
119 return;
120 }
121 }
122
123 void
fswrite(Req * r)124 fswrite(Req *r)
125 {
126 respond(r, "no writing");
127 }
128
129 void
fsopen(Req * r)130 fsopen(Req *r)
131 {
132 if(r->fid->qid.path != Qroot){
133 respond(r, "permission denied");
134 return;
135 }
136
137 if(r->ifcall.mode != OREAD)
138 respond(r, "permission denied");
139 else
140 respond(r, nil);
141 }
142
143 Srv fs = {
144 .attach= fsattach,
145 .open= fsopen,
146 .read= fsread,
147 .write= fswrite,
148 .stat= fsstat,
149 .walk1= fswalk1,
150 };
151
152 void
usage(void)153 usage(void)
154 {
155 fprint(2, "usage: aux/stub [-Dd] path/name\n");
156 exits("usage");
157 }
158
159 void
main(int argc,char ** argv)160 main(int argc, char **argv)
161 {
162 char *p, *mtpt;
163
164 quotefmtinstall();
165
166 time0 = time(0);
167 ARGBEGIN{
168 case 'D':
169 chatty9p++;
170 break;
171 case 'd':
172 kidmode = DMDIR;
173 break;
174 default:
175 usage();
176 }ARGEND
177
178 if(argc != 1)
179 usage();
180
181 if((p = strrchr(argv[0], '/')) == 0){
182 mtpt = ".";
183 kidname = argv[0];
184 }else if(p == argv[0]){
185 mtpt = "/";
186 kidname = argv[0]+1;
187 }else{
188 mtpt = argv[0];
189 *p++ = '\0';
190 kidname = p;
191 }
192 /* don't leave standard descriptors open to confuse mk */
193 close(0);
194 close(1);
195 close(2);
196 postmountsrv(&fs, nil, mtpt, MBEFORE);
197 exits(nil);
198 }
199