]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hjfs/cons.c
hjfs: disable shutdown when listening on network connections
[plan9front.git] / sys / src / cmd / hjfs / cons.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <bio.h>
5 #include "dat.h"
6 #include "fns.h"
7
8 enum { MAXARGS = 16 };
9
10 typedef struct Cmd Cmd;
11 static int echo;
12 extern Fs *fsmain;
13
14 struct Cmd {
15         char *name;
16         int args;
17         int (*f)(int, char **);
18 };
19
20 static int
21 walkpath(Chan *ch, char *path, char **cr)
22 {
23         char buf[NAMELEN], *p, *fp;
24
25         fp = path;
26         if(*path != '/'){
27         noent:
28                 werrstr("%s: %s", fp, Enoent);
29                 return -1;
30         }
31         path++;
32         for(;;){
33                 p = strchr(path, '/');
34                 if(p == nil){
35                         if(cr != nil){
36                                 if(*path == 0){
37                                         werrstr("%s: trailing slash", fp);
38                                         return -1;
39                                 }
40                                 *cr = path;
41                                 break;
42                         }
43                         p = path + strlen(path);
44                 }
45                 if(*path == '/'){
46                         path++;
47                         continue;
48                 }
49                 if(*path == 0)
50                         break;
51                 if(p - path >= NAMELEN)
52                         goto noent;
53                 memset(buf, 0, sizeof buf);
54                 memcpy(buf, path, p - path);
55                 if(chanwalk(ch, buf) <= 0){
56                         werrstr("%s: %r", fp);
57                         return -1;
58                 }
59                 if(*p == 0)
60                         break;
61                 path = p + 1;
62         }
63         return 1;
64 }
65
66 int
67 cmdsync(int, char **)
68 {
69         sync(1);
70         dprint("hjfs: sync\n");
71         return 0;
72 }
73
74 int
75 cmdhalt(int, char **)
76 {
77         shutdown();
78         return 0;
79 }
80
81 int
82 cmddump(int, char **)
83 {
84         fsdump(fsmain);
85         dprint("hjfs: dumped\n");
86         return 0;
87 }
88
89 int
90 cmdallow(int, char **)
91 {
92         fsmain->flags |= FSNOPERM | FSCHOWN;
93         dprint("hjfs: allow\n");
94         return 0;
95 }
96
97 int
98 cmdchatty(int, char **)
99 {
100         extern int chatty9p;
101
102         chatty9p = !chatty9p;
103         return 0;
104 }
105
106 int
107 cmddisallow(int, char **)
108 {
109         fsmain->flags &= ~(FSNOPERM | FSCHOWN);
110         dprint("hjfs: disallow\n");
111         return 0;
112 }
113
114 int
115 cmdnoauth(int, char **)
116 {
117         fsmain->flags ^= FSNOAUTH;
118         if((fsmain->flags & FSNOAUTH) == 0)
119                 dprint("hjfs: auth enabled\n");
120         else
121                 dprint("hjfs: auth disabled\n");
122         return 1;
123 }
124
125 int
126 cmdcreate(int argc, char **argv)
127 {
128         Chan *ch;
129         char *n;
130         short uid, gid;
131         ulong perm;
132         Dir di;
133
134         if(argc != 5 && argc != 6)
135                 return -9001;
136         perm = strtol(argv[4], &n, 8) & 0777;
137         if(*n != 0)
138                 return -9001;
139         if(argc == 6)
140                 for(n = argv[5]; *n != 0; n++)
141                         switch(*n){
142                         case 'l': perm |= DMEXCL; break;
143                         case 'd': perm |= DMDIR; break;
144                         case 'a': perm |= DMAPPEND; break;
145                         default: return -9001;
146                         }
147         if(name2uid(fsmain, argv[2], &uid) < 0)
148                 return -1;
149         if(name2uid(fsmain, argv[3], &gid) < 0)
150                 return -1;
151         ch = chanattach(fsmain, 0);
152         if(ch == nil)
153                 return -1;
154         ch->uid = uid;
155         if(walkpath(ch, argv[1], &n) < 0){
156                 chanclunk(ch);
157                 return -1;
158         }
159         if(chancreat(ch, n, perm, OREAD) < 0){
160                 chanclunk(ch);
161                 return -1;
162         }
163         nulldir(&di);
164         di.gid = argv[3];
165         chanwstat(ch, &di);
166         chanclunk(ch);
167         return 1;
168 }
169
170 int
171 cmdecho(int, char **argv)
172 {
173         echo = strcmp(argv[1], "on") == 0;
174         return 1;
175 }
176
177 int
178 cmddf(int, char **)
179 {
180         uvlong n;
181         uvlong i;
182         int j;
183         Buf *b, *sb;
184
185         wlock(fsmain);
186         sb = getbuf(fsmain->d, SUPERBLK, TSUPERBLOCK, 0);
187         if(sb == nil){
188                 wunlock(fsmain);
189                 return -1;
190         }
191         n = 0;
192         for(i = sb->sb.fstart; i < sb->sb.fend; i++){
193                 b = getbuf(fsmain->d, i, TREF, 0);
194                 if(b == nil)
195                         continue;
196                 for(j = 0; j < REFPERBLK; j++)
197                         if(b->refs[j] == 0)
198                                 n++;
199                 putbuf(b);
200         }
201         dprint("hjfs: (blocks) free %ulld, used %ulld, total %ulld\n", n, sb->sb.size - n, sb->sb.size);
202         dprint("hjfs: (MB) free %ulld, used %ulld, total %ulld\n", n * BLOCK / 1048576, (sb->sb.size - n) * BLOCK / 1048576, sb->sb.size * BLOCK / 1048576);
203         putbuf(sb);
204         wunlock(fsmain);
205         return 1;
206 }
207
208 int
209 cmddebugdeind(int, char **argv)
210 {
211         Chan *ch;
212         Buf *b;
213         Dentry *d;
214
215         ch = chanattach(fsmain, 0);
216         if(ch == nil)
217                 return -1;
218         ch->uid = -1;
219         if(walkpath(ch, argv[1], nil) < 0)
220                 goto error;
221         rlock(fsmain);
222         dprint("hjfs: loc %ulld / %uld, offset %ulld\n", ch->loc->blk, ch->loc->deind, BLOCK * ch->loc->blk + (RBLOCK - BLOCK) + DENTRYSIZ * ch->loc->deind);
223         b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
224         if(b == nil){
225                 runlock(fsmain);
226                 goto error;
227         }
228         d = &b->de[ch->loc->deind];
229         dprint("hjfs: name %s\n", d->name);
230         dprint("hjfs: uid %d, muid %d, gid %d\n", d->uid, d->muid, d->gid);
231         dprint("hjfs: mode %#o, qid %ulld, type %#x, version %d\n", d->mode, d->path, d->type, d->vers);
232         dprint("hjfs: size %d\n", d->size);
233         dprint("hjfs: atime %ulld, mtime %ulld\n", d->atime, d->mtime);
234         putbuf(b);
235         runlock(fsmain);
236         chanclunk(ch);
237         return 0;
238 error:
239         chanclunk(ch);
240         return -1;
241 }
242
243 int
244 cmddebugchdeind(int, char **argv)
245 {
246         Chan *ch;
247         uchar *c;
248         Buf *b;
249         int loc, new;
250
251         loc = strtol(argv[2], nil, 0);
252         new = strtol(argv[3], nil, 0);
253         if(loc >= DENTRYSIZ)
254                 return -9001;
255         ch = chanattach(fsmain, 0);
256         if(ch == nil)
257                 return -1;
258         ch->uid = -1;
259         if(walkpath(ch, argv[1], nil) < 0)
260                 goto error;
261         rlock(fsmain);
262         b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
263         if(b == nil){
264                 runlock(fsmain);
265                 goto error;
266         }
267         c = (uchar *) &b->de[ch->loc->deind];
268         dprint("hjfs: loc %d, old value %#.2x, new value %#.2x\n", loc, c[loc], new);
269         c[loc] = new;
270         b->op |= BDELWRI;
271         putbuf(b);
272         runlock(fsmain);
273         chanclunk(ch);
274         return 0;
275 error:
276         chanclunk(ch);
277         return -1;
278 }
279
280 int
281 cmddebuggetblk(int argc, char **argv)
282 {
283         Chan *ch;
284         Buf *b;
285         int rc;
286         uvlong r, start, end, i;
287
288         if(argc != 3 && argc != 4)
289                 return -9001;
290         start = atoll(argv[2]);
291         if(argc == 4)
292                 end = atoll(argv[3]);
293         else
294                 end = start;
295         ch = chanattach(fsmain, 0);
296         if(ch == nil)
297                 return -1;
298         ch->uid = -1;
299         if(walkpath(ch, argv[1], nil) < 0)
300                 goto error;
301         rlock(fsmain);
302         b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
303         if(b == nil){
304                 runlock(fsmain);
305                 goto error;
306         }
307         for(i = start; i <= end; i++){
308                 rc = getblk(fsmain, ch->loc, b, i, &r, GBREAD);
309                 if(rc > 0)
310                         dprint("hjfs: getblk %ulld = %ulld\n", i, r);
311                 if(rc == 0)
312                         dprint("hjfs: getblk %ulld not found\n", i);
313                 if(rc < 0)
314                         dprint("hjfs: getblk %ulld: %r\n", i);
315         }
316         putbuf(b);
317         runlock(fsmain);
318         chanclunk(ch);
319         return 0;
320 error:
321         chanclunk(ch);
322         return -1;
323 }
324
325 extern int cmdnewuser(int, char **);
326
327 Cmd cmds[] = {
328         {"allow", 1, cmdallow},
329         {"noauth", 1, cmdnoauth},
330         {"chatty", 1, cmdchatty},
331         {"create", 0, cmdcreate},
332         {"disallow", 1, cmddisallow},
333         {"dump", 1, cmddump},
334         {"sync", 1, cmdsync},
335         {"halt", 1, cmdhalt},
336         {"newuser", 0, cmdnewuser},
337         {"echo", 2, cmdecho},
338         {"df", 1, cmddf},
339         {"debug-deind", 2, cmddebugdeind},
340         {"debug-getblk", 0, cmddebuggetblk},
341         {"debug-chdeind", 4, cmddebugchdeind},
342 };
343
344
345 static void
346 consproc(void *v)
347 {
348         Biobuf *in;
349         Cmd *c;
350         char *s;
351         char *args[MAXARGS];
352         int rc;
353         
354         in = (Biobuf *) v;
355         for(;;){
356                 s = Brdstr(in, '\n', 1);
357                 if(s == nil)
358                         continue;
359                 if(echo)
360                         dprint("hjfs: >%s\n", s);
361                 rc = tokenize(s, args, MAXARGS);
362                 if(rc == 0)
363                         goto syntax;
364                 for(c = cmds; c < cmds + nelem(cmds); c++)
365                         if(strcmp(c->name, args[0]) == 0){
366                                 if(c->args != 0 && c->args != rc)
367                                         goto syntax;
368                                 if(c->f != nil){
369                                         rc = c->f(rc, args);
370                                         if(rc == -9001)
371                                                 goto syntax;
372                                         if(rc < 0)
373                                                 dprint("hjfs: %r\n");
374                                         goto done;
375                                 }
376                         }
377         syntax:
378                 dprint("hjfs: syntax error\n");
379         done:
380                 free(s);
381         }
382 }
383
384 void
385 initcons(char *service)
386 {
387         int fd, pfd[2];
388         static Biobuf bio;
389         char buf[512];
390
391         snprint(buf, sizeof(buf), "/srv/%s.cmd", service);
392         fd = create(buf, OWRITE|ORCLOSE, 0600);
393         if(fd < 0)
394                 return;
395         pipe(pfd);
396         fprint(fd, "%d", pfd[1]);
397         Binit(&bio, pfd[0], OREAD);
398         proccreate(consproc, &bio, mainstacksize);
399 }