10 typedef struct Cmd Cmd;
17 int (*f)(int, char **);
21 walkpath(Chan *ch, char *path, char **cr)
23 char buf[NAMELEN], *p, *fp;
28 werrstr("%s: %s", fp, Enoent);
33 p = strchr(path, '/');
37 werrstr("%s: trailing slash", fp);
43 p = path + strlen(path);
51 if(p - path >= NAMELEN)
53 memset(buf, 0, sizeof buf);
54 memcpy(buf, path, p - path);
55 if(chanwalk(ch, buf) <= 0){
56 werrstr("%s: %r", fp);
90 cmdallow(int, char **)
92 fsmain->flags |= FSNOPERM | FSCHOWN;
98 cmdchatty(int, char **)
102 chatty9p = !chatty9p;
107 checkfile(FLoc *l, Buf *b)
117 dprint("checkfile: bad entry: %r\n");
120 if((d->type & QTDIR) == 0){
123 blocks = HOWMANY(d->size);
130 for(i = 0; i < blocks; i++){
131 rc = getblk(fsmain, l, b, i, &r, GBREAD);
133 dprint("bad block %ulld of %ulld in %s %s with directory entry index %d in block %ulld: %r\n", i, blocks, ftype, d->name, l->deind, l->blk);
137 dprint("block %ulld of %ulld not found in %s %s with directory index %d in block %ulld\n", i, blocks, ftype, d->name, l->deind, l->blk);
140 c = getbuf(fsmain->d, r, btype, 0);
142 dprint("bad block %ulld of %ulld in %s %s with directory entry index %d in block %ulld: %r\n", i, blocks, ftype, d->name, l->deind, l->blk);
144 if(chref(fsmain, r, 0) == 0)
145 dprint("block %ulld of %ulld in %s %s with directory entry index %d in block %ulld has a reference count of 0", i, blocks, ftype, d->name, l->deind, l->blk);
157 b = getbuf(fsmain->d, blk, TDONTCARE, 0);
160 switch(type = b->type){
163 dprint("checkblk: should not have found superblock at %ulld\n", blk);
167 for(i = 0; i < DEPERBLK; i++){
169 if((d->mode & (DGONE | DALLOC)) == 0)
182 cmdcheck(int, char**)
184 static ulong refs[REFPERBLK];
185 uvlong fblk, fend, blk;
186 uvlong ndentry, nindir, nraw, nref, nsuperblock;
191 sb = getbuf(fsmain->d, SUPERBLK, TSUPERBLOCK, 0);
196 fblk = sb->sb.fstart;
205 for(blk = 0; fblk < fend; fblk++){
206 b = getbuf(fsmain->d, fblk, TREF, 0);
211 memcpy(refs, b->refs, sizeof(refs));
213 for(j = 0; j < REFPERBLK; j++, blk++){
214 if(refs[j] > 0 && refs[j] != REFSENTINEL){
215 switch(checkblk(blk)){
236 dprint("%T block count %ulld\n", TDENTRY, ndentry);
237 dprint("%T block count %ulld\n", TINDIR, nindir);
238 dprint("%T block count %ulld\n", TRAW, nraw);
239 dprint("%T block count %ulld\n", TREF, nref);
240 dprint("%T block count %ulld\n", TSUPERBLOCK, nsuperblock);
245 cmddisallow(int, char **)
247 fsmain->flags &= ~(FSNOPERM | FSCHOWN);
248 dprint("disallow\n");
253 cmdnoauth(int, char **)
255 fsmain->flags ^= FSNOAUTH;
256 if((fsmain->flags & FSNOAUTH) == 0)
257 dprint("auth enabled\n");
259 dprint("auth disabled\n");
264 cmdcreate(int argc, char **argv)
272 if(argc != 5 && argc != 6)
274 perm = strtol(argv[4], &n, 8) & 0777;
278 for(n = argv[5]; *n != 0; n++)
280 case 'l': perm |= DMEXCL; break;
281 case 'd': perm |= DMDIR; break;
282 case 'a': perm |= DMAPPEND; break;
283 default: return -9001;
285 if(name2uid(fsmain, argv[2], &uid) < 0)
287 if(name2uid(fsmain, argv[3], &gid) < 0)
289 ch = chanattach(fsmain, CHFNOPERM);
293 if(walkpath(ch, argv[1], &n) < 0){
297 if(chancreat(ch, n, perm, OREAD) < 0){
309 cmdecho(int, char **argv)
311 echo = strcmp(argv[1], "on") == 0;
324 sb = getbuf(fsmain->d, SUPERBLK, TSUPERBLOCK, 0);
330 for(i = sb->sb.fstart; i < sb->sb.fend; i++){
331 b = getbuf(fsmain->d, i, TREF, 0);
334 for(j = 0; j < REFPERBLK; j++)
339 dprint("(blocks) free %ulld, used %ulld, total %ulld\n", n, sb->sb.size - n, sb->sb.size);
340 dprint("(MB) free %ulld, used %ulld, total %ulld\n", n * BLOCK / 1048576, (sb->sb.size - n) * BLOCK / 1048576, sb->sb.size * BLOCK / 1048576);
347 cmddebugdeind(int, char **argv)
353 ch = chanattach(fsmain, 0);
357 if(walkpath(ch, argv[1], nil) < 0)
360 dprint("loc %ulld / %uld, offset %ulld\n", ch->loc->blk, ch->loc->deind, BLOCK * ch->loc->blk + (RBLOCK - BLOCK) + DENTRYSIZ * ch->loc->deind);
361 b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
366 d = &b->de[ch->loc->deind];
367 dprint("name %s\n", d->name);
368 dprint("uid %d, muid %d, gid %d\n", d->uid, d->muid, d->gid);
369 dprint("mode %#o, qid %ulld, type %#x, version %d\n", d->mode, d->path, d->type, d->vers);
370 dprint("size %d\n", d->size);
371 dprint("atime %ulld, mtime %ulld\n", d->atime, d->mtime);
382 cmddebugchdeind(int, char **argv)
389 loc = strtol(argv[2], nil, 0);
390 new = strtol(argv[3], nil, 0);
393 ch = chanattach(fsmain, 0);
397 if(walkpath(ch, argv[1], nil) < 0)
400 b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
405 c = (uchar *) &b->de[ch->loc->deind];
406 dprint("loc %d, old value %#.2x, new value %#.2x\n", loc, c[loc], new);
419 cmddebuggetblk(int argc, char **argv)
424 uvlong r, start, end, i;
426 if(argc != 3 && argc != 4)
428 start = atoll(argv[2]);
430 end = atoll(argv[3]);
433 ch = chanattach(fsmain, 0);
437 if(walkpath(ch, argv[1], nil) < 0)
440 b = getbuf(fsmain->d, ch->loc->blk, TDENTRY, 0);
445 for(i = start; i <= end; i++){
446 rc = getblk(fsmain, ch->loc, b, i, &r, GBREAD);
448 dprint("getblk %ulld = %ulld\n", i, r);
450 dprint("getblk %ulld not found\n", i);
452 dprint("getblk %ulld: %r\n", i);
464 cmdusers(int, char**)
470 extern int cmdnewuser(int, char **);
473 {"allow", 1, cmdallow},
474 {"noauth", 1, cmdnoauth},
475 {"chatty", 1, cmdchatty},
476 // {"check", 0, cmdcheck},
477 {"create", 0, cmdcreate},
478 {"disallow", 1, cmddisallow},
479 {"dump", 1, cmddump},
480 {"sync", 1, cmdsync},
481 {"halt", 1, cmdhalt},
482 {"newuser", 0, cmdnewuser},
483 {"users", 1, cmdusers},
484 {"echo", 2, cmdecho},
486 {"debug-deind", 2, cmddebugdeind},
487 {"debug-getblk", 0, cmddebuggetblk},
488 {"debug-chdeind", 4, cmddebugchdeind},
503 s = Brdstr(in, '\n', 1);
508 rc = tokenize(s, args, MAXARGS);
511 for(c = cmds; c < cmds + nelem(cmds); c++)
512 if(strcmp(c->name, args[0]) == 0){
513 if(c->args != 0 && c->args != rc)
525 dprint("syntax error\n");
532 initcons(char *service)
538 snprint(buf, sizeof(buf), "/srv/%s.cmd", service);
539 fd = create(buf, OWRITE|ORCLOSE, 0600);
543 fprint(fd, "%d", pfd[1]);
544 Binit(&bio, pfd[0], OREAD);
545 proccreate(consproc, &bio, mainstacksize);