19a747e4fSDavid du Colombier #include "all.h"
29a747e4fSDavid du Colombier #include "9p1.h"
39a747e4fSDavid du Colombier
49a747e4fSDavid du Colombier /*
59a747e4fSDavid du Colombier * buggery to give false qid for
69a747e4fSDavid du Colombier * the top 2 levels of the dump fs
79a747e4fSDavid du Colombier */
89a747e4fSDavid du Colombier void
mkqid(Qid * qid,Dentry * d,int buggery)99a747e4fSDavid du Colombier mkqid(Qid* qid, Dentry *d, int buggery)
109a747e4fSDavid du Colombier {
119a747e4fSDavid du Colombier int c;
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier if(buggery && d->qid.path == QPROOT && (d->qid.path & QPDIR)){
149a747e4fSDavid du Colombier c = d->name[0];
159a747e4fSDavid du Colombier if(c >= '0' && c <= '9'){
169a747e4fSDavid du Colombier qid->path = 3;
179a747e4fSDavid du Colombier qid->vers = d->qid.version;
189a747e4fSDavid du Colombier qid->type = QTDIR;
199a747e4fSDavid du Colombier
209a747e4fSDavid du Colombier c = (c-'0')*10 + (d->name[1]-'0');
219a747e4fSDavid du Colombier if(c >= 1 && c <= 12)
229a747e4fSDavid du Colombier qid->path = 4;
239a747e4fSDavid du Colombier return;
249a747e4fSDavid du Colombier }
259a747e4fSDavid du Colombier }
269a747e4fSDavid du Colombier
279a747e4fSDavid du Colombier mkqid9p2(qid, &d->qid, d->mode);
289a747e4fSDavid du Colombier }
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier int
mkqidcmp(Qid * qid,Dentry * d)319a747e4fSDavid du Colombier mkqidcmp(Qid* qid, Dentry *d)
329a747e4fSDavid du Colombier {
339a747e4fSDavid du Colombier Qid tmp;
349a747e4fSDavid du Colombier
359a747e4fSDavid du Colombier mkqid(&tmp, d, 1);
369a747e4fSDavid du Colombier if(qid->path==tmp.path && (qid->type&QTDIR)==(tmp.type&QTDIR))
379a747e4fSDavid du Colombier return 0;
389a747e4fSDavid du Colombier return Eqid;
399a747e4fSDavid du Colombier }
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier void
f_nop(Chan * cp,Oldfcall * in,Oldfcall * ou)429a747e4fSDavid du Colombier f_nop(Chan *cp, Oldfcall *in, Oldfcall *ou)
439a747e4fSDavid du Colombier {
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier USED(in);
469a747e4fSDavid du Colombier USED(ou);
479a747e4fSDavid du Colombier if(CHAT(cp))
489a747e4fSDavid du Colombier print("c_nop %d\n", cp->chan);
499a747e4fSDavid du Colombier }
509a747e4fSDavid du Colombier
519a747e4fSDavid du Colombier void
f_flush(Chan * cp,Oldfcall * in,Oldfcall * ou)529a747e4fSDavid du Colombier f_flush(Chan *cp, Oldfcall *in, Oldfcall *ou)
539a747e4fSDavid du Colombier {
549a747e4fSDavid du Colombier
559a747e4fSDavid du Colombier USED(in);
569a747e4fSDavid du Colombier USED(ou);
579a747e4fSDavid du Colombier if(CHAT(cp))
589a747e4fSDavid du Colombier print("c_flush %d\n", cp->chan);
599a747e4fSDavid du Colombier runlock(&cp->reflock);
609a747e4fSDavid du Colombier wlock(&cp->reflock);
619a747e4fSDavid du Colombier wunlock(&cp->reflock);
629a747e4fSDavid du Colombier rlock(&cp->reflock);
639a747e4fSDavid du Colombier }
649a747e4fSDavid du Colombier
659a747e4fSDavid du Colombier void
f_session(Chan * cp,Oldfcall * in,Oldfcall * ou)669a747e4fSDavid du Colombier f_session(Chan *cp, Oldfcall *in, Oldfcall *ou)
679a747e4fSDavid du Colombier {
689a747e4fSDavid du Colombier if(CHAT(cp))
699a747e4fSDavid du Colombier print("c_session %d\n", cp->chan);
709a747e4fSDavid du Colombier
719a747e4fSDavid du Colombier memmove(cp->rchal, in->chal, sizeof(cp->rchal));
725d459b5aSDavid du Colombier if(wstatallow || cp == cons.srvchan){
73d9306527SDavid du Colombier memset(ou->chal, 0, sizeof(ou->chal));
749a747e4fSDavid du Colombier memset(ou->authid, 0, sizeof(ou->authid));
755d459b5aSDavid du Colombier }else{
765d459b5aSDavid du Colombier mkchallenge(cp);
77d9306527SDavid du Colombier memmove(ou->chal, cp->chal, sizeof(ou->chal));
789a747e4fSDavid du Colombier memmove(ou->authid, nvr.authid, sizeof(ou->authid));
795d459b5aSDavid du Colombier }
809a747e4fSDavid du Colombier sprint(ou->authdom, "%s.%s", service, nvr.authdom);
819a747e4fSDavid du Colombier fileinit(cp);
829a747e4fSDavid du Colombier }
839a747e4fSDavid du Colombier
849a747e4fSDavid du Colombier void
f_attach(Chan * cp,Oldfcall * in,Oldfcall * ou)859a747e4fSDavid du Colombier f_attach(Chan *cp, Oldfcall *in, Oldfcall *ou)
869a747e4fSDavid du Colombier {
879a747e4fSDavid du Colombier Iobuf *p;
889a747e4fSDavid du Colombier Dentry *d;
899a747e4fSDavid du Colombier File *f;
909a747e4fSDavid du Colombier int u;
919a747e4fSDavid du Colombier Filsys *fs;
929a747e4fSDavid du Colombier long raddr;
939a747e4fSDavid du Colombier
949a747e4fSDavid du Colombier if(CHAT(cp)) {
959a747e4fSDavid du Colombier print("c_attach %d\n", cp->chan);
969a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
979a747e4fSDavid du Colombier print(" uid = %s\n", in->uname);
989a747e4fSDavid du Colombier print(" arg = %s\n", in->aname);
999a747e4fSDavid du Colombier }
1009a747e4fSDavid du Colombier
1019a747e4fSDavid du Colombier ou->qid = QID9P1(0,0);
1029a747e4fSDavid du Colombier ou->fid = in->fid;
1039a747e4fSDavid du Colombier if(!in->aname[0]) /* default */
1049a747e4fSDavid du Colombier strncpy(in->aname, filesys[0].name, sizeof(in->aname));
1059a747e4fSDavid du Colombier p = 0;
1069a747e4fSDavid du Colombier f = filep(cp, in->fid, 1);
1079a747e4fSDavid du Colombier if(!f) {
1089a747e4fSDavid du Colombier ou->err = Efid;
1099a747e4fSDavid du Colombier goto out;
1109a747e4fSDavid du Colombier }
1119a747e4fSDavid du Colombier u = -1;
1129a747e4fSDavid du Colombier if(cp != cons.chan){
1135d459b5aSDavid du Colombier if(authorize(cp, in, ou) == 0 || strcmp(in->uname, "adm") == 0){
1149a747e4fSDavid du Colombier ou->err = Eauth;
1159a747e4fSDavid du Colombier goto out;
1169a747e4fSDavid du Colombier }
1179a747e4fSDavid du Colombier u = strtouid(in->uname);
1189a747e4fSDavid du Colombier if(u < 0){
1199a747e4fSDavid du Colombier ou->err = Ebadu;
1209a747e4fSDavid du Colombier goto out;
1219a747e4fSDavid du Colombier }
1229a747e4fSDavid du Colombier }
1239a747e4fSDavid du Colombier
1249a747e4fSDavid du Colombier fs = fsstr(in->aname);
1259a747e4fSDavid du Colombier if(fs == 0) {
1269a747e4fSDavid du Colombier ou->err = Ebadspc;
1279a747e4fSDavid du Colombier goto out;
1289a747e4fSDavid du Colombier }
1299a747e4fSDavid du Colombier raddr = getraddr(fs->dev);
1309a747e4fSDavid du Colombier p = getbuf(fs->dev, raddr, Bread);
1319a747e4fSDavid du Colombier d = getdir(p, 0);
1329a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) {
1339a747e4fSDavid du Colombier ou->err = Ealloc;
1349a747e4fSDavid du Colombier goto out;
1359a747e4fSDavid du Colombier }
1369a747e4fSDavid du Colombier f->uid = u;
1379a747e4fSDavid du Colombier if(iaccess(f, d, DREAD)) {
1389a747e4fSDavid du Colombier ou->err = Eaccess;
1399a747e4fSDavid du Colombier goto out;
1409a747e4fSDavid du Colombier }
1419a747e4fSDavid du Colombier accessdir(p, d, FREAD);
1429a747e4fSDavid du Colombier mkqid(&f->qid, d, 1);
1439a747e4fSDavid du Colombier f->fs = fs;
1449a747e4fSDavid du Colombier f->addr = raddr;
1459a747e4fSDavid du Colombier f->slot = 0;
1469a747e4fSDavid du Colombier f->open = 0;
1479a747e4fSDavid du Colombier freewp(f->wpath);
1489a747e4fSDavid du Colombier f->wpath = 0;
1499a747e4fSDavid du Colombier
1509a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &f->qid);
1519a747e4fSDavid du Colombier
1529a747e4fSDavid du Colombier out:
1539a747e4fSDavid du Colombier if(p)
1549a747e4fSDavid du Colombier putbuf(p);
1559a747e4fSDavid du Colombier if(f) {
1569a747e4fSDavid du Colombier qunlock(f);
1579a747e4fSDavid du Colombier if(ou->err)
1589a747e4fSDavid du Colombier freefp(f);
1599a747e4fSDavid du Colombier }
1609a747e4fSDavid du Colombier }
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier void
f_clone(Chan * cp,Oldfcall * in,Oldfcall * ou)1639a747e4fSDavid du Colombier f_clone(Chan *cp, Oldfcall *in, Oldfcall *ou)
1649a747e4fSDavid du Colombier {
1659a747e4fSDavid du Colombier File *f1, *f2;
1669a747e4fSDavid du Colombier int fid, fid1;
1679a747e4fSDavid du Colombier
1689a747e4fSDavid du Colombier if(CHAT(cp)) {
1699a747e4fSDavid du Colombier print("c_clone %d\n", cp->chan);
1709a747e4fSDavid du Colombier print(" old fid = %d\n", in->fid);
1719a747e4fSDavid du Colombier print(" new fid = %d\n", in->newfid);
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier
1749a747e4fSDavid du Colombier fid = in->fid;
1759a747e4fSDavid du Colombier fid1 = in->newfid;
1769a747e4fSDavid du Colombier
1779a747e4fSDavid du Colombier f1 = 0;
1789a747e4fSDavid du Colombier f2 = 0;
1799a747e4fSDavid du Colombier if(fid < fid1) {
1809a747e4fSDavid du Colombier f1 = filep(cp, fid, 0);
1819a747e4fSDavid du Colombier f2 = filep(cp, fid1, 1);
1829a747e4fSDavid du Colombier } else
1839a747e4fSDavid du Colombier if(fid1 < fid) {
1849a747e4fSDavid du Colombier f2 = filep(cp, fid1, 1);
1859a747e4fSDavid du Colombier f1 = filep(cp, fid, 0);
1869a747e4fSDavid du Colombier }
1879a747e4fSDavid du Colombier if(!f1 || !f2) {
1889a747e4fSDavid du Colombier ou->err = Efid;
1899a747e4fSDavid du Colombier goto out;
1909a747e4fSDavid du Colombier }
1919a747e4fSDavid du Colombier
1929a747e4fSDavid du Colombier
1939a747e4fSDavid du Colombier f2->fs = f1->fs;
1949a747e4fSDavid du Colombier f2->addr = f1->addr;
1959a747e4fSDavid du Colombier f2->open = f1->open & ~FREMOV;
1969a747e4fSDavid du Colombier f2->uid = f1->uid;
1979a747e4fSDavid du Colombier f2->slot = f1->slot;
1989a747e4fSDavid du Colombier f2->qid = f1->qid;
1999a747e4fSDavid du Colombier
2009a747e4fSDavid du Colombier freewp(f2->wpath);
2019a747e4fSDavid du Colombier f2->wpath = getwp(f1->wpath);
2029a747e4fSDavid du Colombier
2039a747e4fSDavid du Colombier out:
2049a747e4fSDavid du Colombier ou->fid = fid;
2059a747e4fSDavid du Colombier if(f1)
2069a747e4fSDavid du Colombier qunlock(f1);
2079a747e4fSDavid du Colombier if(f2)
2089a747e4fSDavid du Colombier qunlock(f2);
2099a747e4fSDavid du Colombier }
2109a747e4fSDavid du Colombier
2119a747e4fSDavid du Colombier void
f_walk(Chan * cp,Oldfcall * in,Oldfcall * ou)2129a747e4fSDavid du Colombier f_walk(Chan *cp, Oldfcall *in, Oldfcall *ou)
2139a747e4fSDavid du Colombier {
2149a747e4fSDavid du Colombier Iobuf *p, *p1;
2159a747e4fSDavid du Colombier Dentry *d, *d1;
2169a747e4fSDavid du Colombier File *f;
2179a747e4fSDavid du Colombier Wpath *w, *ow;
2189a747e4fSDavid du Colombier int slot;
2199a747e4fSDavid du Colombier long addr;
2209a747e4fSDavid du Colombier
2219a747e4fSDavid du Colombier if(CHAT(cp)) {
2229a747e4fSDavid du Colombier print("c_walk %d\n", cp->chan);
2239a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
2249a747e4fSDavid du Colombier print(" name = %s\n", in->name);
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier
2279a747e4fSDavid du Colombier ou->fid = in->fid;
2289a747e4fSDavid du Colombier ou->qid = QID9P1(0,0);
2299a747e4fSDavid du Colombier p = 0;
2309a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
2319a747e4fSDavid du Colombier if(!f) {
2329a747e4fSDavid du Colombier ou->err = Efid;
2339a747e4fSDavid du Colombier goto out;
2349a747e4fSDavid du Colombier }
2359a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
2369a747e4fSDavid du Colombier d = getdir(p, f->slot);
2379a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
2389a747e4fSDavid du Colombier ou->err = Ealloc;
2399a747e4fSDavid du Colombier goto out;
2409a747e4fSDavid du Colombier }
2419a747e4fSDavid du Colombier if(!(d->mode & DDIR)) {
2429a747e4fSDavid du Colombier ou->err = Edir1;
2439a747e4fSDavid du Colombier goto out;
2449a747e4fSDavid du Colombier }
2459a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
2469a747e4fSDavid du Colombier goto out;
2479a747e4fSDavid du Colombier if(cp != cons.chan && iaccess(f, d, DEXEC)) {
2489a747e4fSDavid du Colombier ou->err = Eaccess;
2499a747e4fSDavid du Colombier goto out;
2509a747e4fSDavid du Colombier }
2519a747e4fSDavid du Colombier accessdir(p, d, FREAD);
2529a747e4fSDavid du Colombier if(strcmp(in->name, ".") == 0)
2539a747e4fSDavid du Colombier goto setdot;
2549a747e4fSDavid du Colombier if(strcmp(in->name, "..") == 0) {
2559a747e4fSDavid du Colombier if(f->wpath == 0)
2569a747e4fSDavid du Colombier goto setdot;
2579a747e4fSDavid du Colombier putbuf(p);
2589a747e4fSDavid du Colombier p = 0;
2599a747e4fSDavid du Colombier addr = f->wpath->addr;
2609a747e4fSDavid du Colombier slot = f->wpath->slot;
2619a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, addr, Bread);
2629a747e4fSDavid du Colombier d1 = getdir(p1, slot);
2639a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
2649a747e4fSDavid du Colombier if(p1)
2659a747e4fSDavid du Colombier putbuf(p1);
2669a747e4fSDavid du Colombier ou->err = Ephase;
2679a747e4fSDavid du Colombier goto out;
2689a747e4fSDavid du Colombier }
2699a747e4fSDavid du Colombier ow = f->wpath;
2709a747e4fSDavid du Colombier f->wpath = ow->up;
2719a747e4fSDavid du Colombier putwp(ow);
2729a747e4fSDavid du Colombier goto found;
2739a747e4fSDavid du Colombier }
2749a747e4fSDavid du Colombier for(addr=0;; addr++) {
2759a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0);
2769a747e4fSDavid du Colombier if(!p1 || checktag(p1, Tdir, d->qid.path) ) {
2779a747e4fSDavid du Colombier if(p1)
2789a747e4fSDavid du Colombier putbuf(p1);
2799a747e4fSDavid du Colombier ou->err = Eentry;
2809a747e4fSDavid du Colombier goto out;
2819a747e4fSDavid du Colombier }
2829a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) {
2839a747e4fSDavid du Colombier d1 = getdir(p1, slot);
2849a747e4fSDavid du Colombier if(!(d1->mode & DALLOC))
2859a747e4fSDavid du Colombier continue;
2869a747e4fSDavid du Colombier if(strncmp(in->name, d1->name, sizeof(in->name)))
2879a747e4fSDavid du Colombier continue;
2889a747e4fSDavid du Colombier /*
2899a747e4fSDavid du Colombier * update walk path
2909a747e4fSDavid du Colombier */
2919a747e4fSDavid du Colombier w = newwp();
2929a747e4fSDavid du Colombier if(!w) {
2939a747e4fSDavid du Colombier ou->err = Ewalk;
2949a747e4fSDavid du Colombier putbuf(p1);
2959a747e4fSDavid du Colombier goto out;
2969a747e4fSDavid du Colombier }
2979a747e4fSDavid du Colombier w->addr = f->addr;
2989a747e4fSDavid du Colombier w->slot = f->slot;
2999a747e4fSDavid du Colombier w->up = f->wpath;
3009a747e4fSDavid du Colombier f->wpath = w;
3019a747e4fSDavid du Colombier slot += DIRPERBUF*addr;
3029a747e4fSDavid du Colombier goto found;
3039a747e4fSDavid du Colombier }
3049a747e4fSDavid du Colombier putbuf(p1);
3059a747e4fSDavid du Colombier }
3069a747e4fSDavid du Colombier
3079a747e4fSDavid du Colombier found:
3089a747e4fSDavid du Colombier f->addr = p1->addr;
3099a747e4fSDavid du Colombier mkqid(&f->qid, d1, 1);
3109a747e4fSDavid du Colombier putbuf(p1);
3119a747e4fSDavid du Colombier f->slot = slot;
3129a747e4fSDavid du Colombier
3139a747e4fSDavid du Colombier setdot:
3149a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &f->qid);
3159a747e4fSDavid du Colombier f->open = 0;
3169a747e4fSDavid du Colombier
3179a747e4fSDavid du Colombier out:
3189a747e4fSDavid du Colombier if(p)
3199a747e4fSDavid du Colombier putbuf(p);
3209a747e4fSDavid du Colombier if(f)
3219a747e4fSDavid du Colombier qunlock(f);
3229a747e4fSDavid du Colombier }
3239a747e4fSDavid du Colombier
3249a747e4fSDavid du Colombier void
f_clunk(Chan * cp,Oldfcall * in,Oldfcall * ou)3259a747e4fSDavid du Colombier f_clunk(Chan *cp, Oldfcall *in, Oldfcall *ou)
3269a747e4fSDavid du Colombier {
3279a747e4fSDavid du Colombier File *f;
3289a747e4fSDavid du Colombier Tlock *t;
3299a747e4fSDavid du Colombier long tim;
3309a747e4fSDavid du Colombier
3319a747e4fSDavid du Colombier if(CHAT(cp)) {
3329a747e4fSDavid du Colombier print("c_clunk %d\n", cp->chan);
3339a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
3349a747e4fSDavid du Colombier }
3359a747e4fSDavid du Colombier
3369a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
3379a747e4fSDavid du Colombier if(!f) {
3389a747e4fSDavid du Colombier print("%p\n", f);
3399a747e4fSDavid du Colombier ou->err = Efid;
3409a747e4fSDavid du Colombier goto out;
3419a747e4fSDavid du Colombier }
3429a747e4fSDavid du Colombier if(t = f->tlock) {
3439a747e4fSDavid du Colombier tim = time(0);
3449a747e4fSDavid du Colombier if(t->time < tim || t->file != f)
3459a747e4fSDavid du Colombier ou->err = Ebroken;
3469a747e4fSDavid du Colombier t->time = 0; /* free the lock */
3479a747e4fSDavid du Colombier f->tlock = 0;
3489a747e4fSDavid du Colombier }
3499a747e4fSDavid du Colombier if(f->open & FREMOV)
3509a747e4fSDavid du Colombier ou->err = doremove(f, 0);
3519a747e4fSDavid du Colombier f->open = 0;
3529a747e4fSDavid du Colombier freewp(f->wpath);
3539a747e4fSDavid du Colombier freefp(f);
3549a747e4fSDavid du Colombier
3559a747e4fSDavid du Colombier out:
3569a747e4fSDavid du Colombier if(f)
3579a747e4fSDavid du Colombier qunlock(f);
3589a747e4fSDavid du Colombier ou->fid = in->fid;
3599a747e4fSDavid du Colombier }
3609a747e4fSDavid du Colombier
3619a747e4fSDavid du Colombier void
f_clwalk(Chan * cp,Oldfcall * in,Oldfcall * ou)3629a747e4fSDavid du Colombier f_clwalk(Chan *cp, Oldfcall *in, Oldfcall *ou)
3639a747e4fSDavid du Colombier {
3649a747e4fSDavid du Colombier int er, fid;
3659a747e4fSDavid du Colombier
3669a747e4fSDavid du Colombier if(CHAT(cp))
3679a747e4fSDavid du Colombier print("c_clwalk macro\n");
3689a747e4fSDavid du Colombier
3699a747e4fSDavid du Colombier f_clone(cp, in, ou); /* sets tag, fid */
3709a747e4fSDavid du Colombier if(ou->err)
3719a747e4fSDavid du Colombier return;
3729a747e4fSDavid du Colombier fid = in->fid;
3739a747e4fSDavid du Colombier in->fid = in->newfid;
3749a747e4fSDavid du Colombier f_walk(cp, in, ou); /* sets tag, fid, qid */
3759a747e4fSDavid du Colombier er = ou->err;
3769a747e4fSDavid du Colombier if(er == Eentry) {
3779a747e4fSDavid du Colombier /*
3789a747e4fSDavid du Colombier * if error is "no entry"
3799a747e4fSDavid du Colombier * return non error and fid
3809a747e4fSDavid du Colombier */
3819a747e4fSDavid du Colombier ou->err = 0;
3829a747e4fSDavid du Colombier f_clunk(cp, in, ou); /* sets tag, fid */
3839a747e4fSDavid du Colombier ou->err = 0;
3849a747e4fSDavid du Colombier ou->fid = fid;
3859a747e4fSDavid du Colombier if(CHAT(cp))
3869a747e4fSDavid du Colombier print(" error: %s\n", errstring[er]);
3879a747e4fSDavid du Colombier return;
3889a747e4fSDavid du Colombier }
3899a747e4fSDavid du Colombier if(er) {
3909a747e4fSDavid du Colombier /*
3919a747e4fSDavid du Colombier * if any other error
3929a747e4fSDavid du Colombier * return an error
3939a747e4fSDavid du Colombier */
3949a747e4fSDavid du Colombier ou->err = 0;
3959a747e4fSDavid du Colombier f_clunk(cp, in, ou); /* sets tag, fid */
3969a747e4fSDavid du Colombier ou->err = er;
3979a747e4fSDavid du Colombier return;
3989a747e4fSDavid du Colombier }
3999a747e4fSDavid du Colombier /*
4009a747e4fSDavid du Colombier * non error
4019a747e4fSDavid du Colombier * return newfid
4029a747e4fSDavid du Colombier */
4039a747e4fSDavid du Colombier }
4049a747e4fSDavid du Colombier
4059a747e4fSDavid du Colombier void
f_open(Chan * cp,Oldfcall * in,Oldfcall * ou)4069a747e4fSDavid du Colombier f_open(Chan *cp, Oldfcall *in, Oldfcall *ou)
4079a747e4fSDavid du Colombier {
4089a747e4fSDavid du Colombier Iobuf *p;
4099a747e4fSDavid du Colombier Dentry *d;
4109a747e4fSDavid du Colombier File *f;
4119a747e4fSDavid du Colombier Tlock *t;
4129a747e4fSDavid du Colombier Qid qid;
4139a747e4fSDavid du Colombier int ro, fmod;
4149a747e4fSDavid du Colombier
4159a747e4fSDavid du Colombier if(CHAT(cp)) {
4169a747e4fSDavid du Colombier print("c_open %d\n", cp->chan);
4179a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
4189a747e4fSDavid du Colombier print(" mode = %o\n", in->mode);
4199a747e4fSDavid du Colombier }
4209a747e4fSDavid du Colombier
4219a747e4fSDavid du Colombier p = 0;
4229a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
4239a747e4fSDavid du Colombier if(!f) {
4249a747e4fSDavid du Colombier ou->err = Efid;
4259a747e4fSDavid du Colombier goto out;
4269a747e4fSDavid du Colombier }
4279a747e4fSDavid du Colombier
4289a747e4fSDavid du Colombier /*
4299a747e4fSDavid du Colombier * if remove on close, check access here
4309a747e4fSDavid du Colombier */
4315d459b5aSDavid du Colombier ro = isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup));
4329a747e4fSDavid du Colombier if(in->mode & MRCLOSE) {
4339a747e4fSDavid du Colombier if(ro) {
4349a747e4fSDavid du Colombier ou->err = Eronly;
4359a747e4fSDavid du Colombier goto out;
4369a747e4fSDavid du Colombier }
4379a747e4fSDavid du Colombier /*
4389a747e4fSDavid du Colombier * check on parent directory of file to be deleted
4399a747e4fSDavid du Colombier */
4409a747e4fSDavid du Colombier if(f->wpath == 0 || f->wpath->addr == f->addr) {
4419a747e4fSDavid du Colombier ou->err = Ephase;
4429a747e4fSDavid du Colombier goto out;
4439a747e4fSDavid du Colombier }
4449a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->wpath->addr, Bread);
4459a747e4fSDavid du Colombier d = getdir(p, f->wpath->slot);
4469a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
4479a747e4fSDavid du Colombier ou->err = Ephase;
4489a747e4fSDavid du Colombier goto out;
4499a747e4fSDavid du Colombier }
4509a747e4fSDavid du Colombier if(iaccess(f, d, DWRITE)) {
4519a747e4fSDavid du Colombier ou->err = Eaccess;
4529a747e4fSDavid du Colombier goto out;
4539a747e4fSDavid du Colombier }
4549a747e4fSDavid du Colombier putbuf(p);
4559a747e4fSDavid du Colombier }
4569a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
4579a747e4fSDavid du Colombier d = getdir(p, f->slot);
4589a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
4599a747e4fSDavid du Colombier ou->err = Ealloc;
4609a747e4fSDavid du Colombier goto out;
4619a747e4fSDavid du Colombier }
4629a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
4639a747e4fSDavid du Colombier goto out;
4649a747e4fSDavid du Colombier mkqid(&qid, d, 1);
4659a747e4fSDavid du Colombier switch(in->mode & 7) {
4669a747e4fSDavid du Colombier
4679a747e4fSDavid du Colombier case MREAD:
4689a747e4fSDavid du Colombier if(iaccess(f, d, DREAD) && !writeallow)
4699a747e4fSDavid du Colombier goto badaccess;
4709a747e4fSDavid du Colombier fmod = FREAD;
4719a747e4fSDavid du Colombier break;
4729a747e4fSDavid du Colombier
4739a747e4fSDavid du Colombier case MWRITE:
4749a747e4fSDavid du Colombier if((d->mode & DDIR) ||
4759a747e4fSDavid du Colombier (iaccess(f, d, DWRITE) && !writeallow))
4769a747e4fSDavid du Colombier goto badaccess;
4779a747e4fSDavid du Colombier if(ro) {
4789a747e4fSDavid du Colombier ou->err = Eronly;
4799a747e4fSDavid du Colombier goto out;
4809a747e4fSDavid du Colombier }
4819a747e4fSDavid du Colombier fmod = FWRITE;
4829a747e4fSDavid du Colombier break;
4839a747e4fSDavid du Colombier
4849a747e4fSDavid du Colombier case MBOTH:
4859a747e4fSDavid du Colombier if((d->mode & DDIR) ||
4869a747e4fSDavid du Colombier (iaccess(f, d, DREAD) && !writeallow) ||
4879a747e4fSDavid du Colombier (iaccess(f, d, DWRITE) && !writeallow))
4889a747e4fSDavid du Colombier goto badaccess;
4899a747e4fSDavid du Colombier if(ro) {
4909a747e4fSDavid du Colombier ou->err = Eronly;
4919a747e4fSDavid du Colombier goto out;
4929a747e4fSDavid du Colombier }
4939a747e4fSDavid du Colombier fmod = FREAD+FWRITE;
4949a747e4fSDavid du Colombier break;
4959a747e4fSDavid du Colombier
4969a747e4fSDavid du Colombier case MEXEC:
4979a747e4fSDavid du Colombier if((d->mode & DDIR) ||
4989a747e4fSDavid du Colombier iaccess(f, d, DEXEC))
4999a747e4fSDavid du Colombier goto badaccess;
5009a747e4fSDavid du Colombier fmod = FREAD;
5019a747e4fSDavid du Colombier break;
5029a747e4fSDavid du Colombier
5039a747e4fSDavid du Colombier default:
5049a747e4fSDavid du Colombier ou->err = Emode;
5059a747e4fSDavid du Colombier goto out;
5069a747e4fSDavid du Colombier }
5079a747e4fSDavid du Colombier if(in->mode & MTRUNC) {
5089a747e4fSDavid du Colombier if((d->mode & DDIR) ||
5099a747e4fSDavid du Colombier (iaccess(f, d, DWRITE) && !writeallow))
5109a747e4fSDavid du Colombier goto badaccess;
5119a747e4fSDavid du Colombier if(ro) {
5129a747e4fSDavid du Colombier ou->err = Eronly;
5139a747e4fSDavid du Colombier goto out;
5149a747e4fSDavid du Colombier }
5159a747e4fSDavid du Colombier }
5169a747e4fSDavid du Colombier t = 0;
5179a747e4fSDavid du Colombier if(d->mode & DLOCK) {
5189a747e4fSDavid du Colombier t = tlocked(p, d);
5199a747e4fSDavid du Colombier if(t == 0) {
5209a747e4fSDavid du Colombier ou->err = Elocked;
5219a747e4fSDavid du Colombier goto out;
5229a747e4fSDavid du Colombier }
5239a747e4fSDavid du Colombier t->file = f;
5249a747e4fSDavid du Colombier }
5259a747e4fSDavid du Colombier if(in->mode & MRCLOSE)
5269a747e4fSDavid du Colombier fmod |= FREMOV;
5279a747e4fSDavid du Colombier f->open = fmod;
5289a747e4fSDavid du Colombier if(in->mode & MTRUNC)
5299a747e4fSDavid du Colombier if(!(d->mode & DAPND))
5309a747e4fSDavid du Colombier dtrunc(p, d);
5319a747e4fSDavid du Colombier f->tlock = t;
5329a747e4fSDavid du Colombier f->lastra = 0;
5339a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &qid);
5349a747e4fSDavid du Colombier goto out;
5359a747e4fSDavid du Colombier
5369a747e4fSDavid du Colombier badaccess:
5379a747e4fSDavid du Colombier ou->err = Eaccess;
5389a747e4fSDavid du Colombier f->open = 0;
5399a747e4fSDavid du Colombier
5409a747e4fSDavid du Colombier out:
5419a747e4fSDavid du Colombier if(p)
5429a747e4fSDavid du Colombier putbuf(p);
5439a747e4fSDavid du Colombier if(f)
5449a747e4fSDavid du Colombier qunlock(f);
5459a747e4fSDavid du Colombier ou->fid = in->fid;
5469a747e4fSDavid du Colombier }
5479a747e4fSDavid du Colombier
5489a747e4fSDavid du Colombier void
f_create(Chan * cp,Oldfcall * in,Oldfcall * ou)5499a747e4fSDavid du Colombier f_create(Chan *cp, Oldfcall *in, Oldfcall *ou)
5509a747e4fSDavid du Colombier {
5519a747e4fSDavid du Colombier Iobuf *p, *p1;
5529a747e4fSDavid du Colombier Dentry *d, *d1;
5539a747e4fSDavid du Colombier File *f;
5549a747e4fSDavid du Colombier int slot, slot1, fmod;
5559a747e4fSDavid du Colombier long addr, addr1, path;
5569a747e4fSDavid du Colombier Qid qid;
5579a747e4fSDavid du Colombier Tlock *t;
5589a747e4fSDavid du Colombier Wpath *w;
5599a747e4fSDavid du Colombier
5609a747e4fSDavid du Colombier if(CHAT(cp)) {
5619a747e4fSDavid du Colombier print("c_create %d\n", cp->chan);
5629a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
5639a747e4fSDavid du Colombier print(" name = %s\n", in->name);
5649a747e4fSDavid du Colombier print(" perm = %lx+%lo\n", (in->perm>>28)&0xf,
5659a747e4fSDavid du Colombier in->perm&0777);
5669a747e4fSDavid du Colombier print(" mode = %d\n", in->mode);
5679a747e4fSDavid du Colombier }
5689a747e4fSDavid du Colombier
5699a747e4fSDavid du Colombier p = 0;
5709a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
5719a747e4fSDavid du Colombier if(!f) {
5729a747e4fSDavid du Colombier ou->err = Efid;
5739a747e4fSDavid du Colombier goto out;
5749a747e4fSDavid du Colombier }
5755d459b5aSDavid du Colombier if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
5769a747e4fSDavid du Colombier ou->err = Eronly;
5779a747e4fSDavid du Colombier goto out;
5789a747e4fSDavid du Colombier }
5799a747e4fSDavid du Colombier
5809a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
5819a747e4fSDavid du Colombier d = getdir(p, f->slot);
5829a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
5839a747e4fSDavid du Colombier ou->err = Ealloc;
5849a747e4fSDavid du Colombier goto out;
5859a747e4fSDavid du Colombier }
5869a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
5879a747e4fSDavid du Colombier goto out;
5889a747e4fSDavid du Colombier if(!(d->mode & DDIR)) {
5899a747e4fSDavid du Colombier ou->err = Edir2;
5909a747e4fSDavid du Colombier goto out;
5919a747e4fSDavid du Colombier }
5929a747e4fSDavid du Colombier if(cp != cons.chan && iaccess(f, d, DWRITE) && !writeallow) {
5939a747e4fSDavid du Colombier ou->err = Eaccess;
5949a747e4fSDavid du Colombier goto out;
5959a747e4fSDavid du Colombier }
5969a747e4fSDavid du Colombier accessdir(p, d, FREAD);
5979a747e4fSDavid du Colombier if(!strncmp(in->name, ".", sizeof(in->name)) ||
5989a747e4fSDavid du Colombier !strncmp(in->name, "..", sizeof(in->name))) {
5999a747e4fSDavid du Colombier ou->err = Edot;
6009a747e4fSDavid du Colombier goto out;
6019a747e4fSDavid du Colombier }
6029a747e4fSDavid du Colombier if(checkname(in->name)) {
6039a747e4fSDavid du Colombier ou->err = Ename;
6049a747e4fSDavid du Colombier goto out;
6059a747e4fSDavid du Colombier }
6069a747e4fSDavid du Colombier addr1 = 0;
6079a747e4fSDavid du Colombier slot1 = 0; /* set */
6089a747e4fSDavid du Colombier for(addr=0;; addr++) {
6099a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0);
6109a747e4fSDavid du Colombier if(!p1) {
6119a747e4fSDavid du Colombier if(addr1)
6129a747e4fSDavid du Colombier break;
6139a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, Tdir);
6149a747e4fSDavid du Colombier }
6159a747e4fSDavid du Colombier if(p1 == 0) {
6169a747e4fSDavid du Colombier ou->err = Efull;
6179a747e4fSDavid du Colombier goto out;
6189a747e4fSDavid du Colombier }
6199a747e4fSDavid du Colombier if(checktag(p1, Tdir, d->qid.path)) {
6209a747e4fSDavid du Colombier putbuf(p1);
6219a747e4fSDavid du Colombier goto phase;
6229a747e4fSDavid du Colombier }
6239a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) {
6249a747e4fSDavid du Colombier d1 = getdir(p1, slot);
6259a747e4fSDavid du Colombier if(!(d1->mode & DALLOC)) {
6269a747e4fSDavid du Colombier if(!addr1) {
6279a747e4fSDavid du Colombier addr1 = p1->addr;
6289a747e4fSDavid du Colombier slot1 = slot + addr*DIRPERBUF;
6299a747e4fSDavid du Colombier }
6309a747e4fSDavid du Colombier continue;
6319a747e4fSDavid du Colombier }
6329a747e4fSDavid du Colombier if(!strncmp(in->name, d1->name, sizeof(in->name))) {
6339a747e4fSDavid du Colombier putbuf(p1);
6349a747e4fSDavid du Colombier ou->err = Eexist;
6359a747e4fSDavid du Colombier goto out;
6369a747e4fSDavid du Colombier }
6379a747e4fSDavid du Colombier }
6389a747e4fSDavid du Colombier putbuf(p1);
6399a747e4fSDavid du Colombier }
6409a747e4fSDavid du Colombier switch(in->mode & 7) {
6419a747e4fSDavid du Colombier case MEXEC:
6429a747e4fSDavid du Colombier case MREAD: /* seems only useful to make directories */
6439a747e4fSDavid du Colombier fmod = FREAD;
6449a747e4fSDavid du Colombier break;
6459a747e4fSDavid du Colombier
6469a747e4fSDavid du Colombier case MWRITE:
6479a747e4fSDavid du Colombier fmod = FWRITE;
6489a747e4fSDavid du Colombier break;
6499a747e4fSDavid du Colombier
6509a747e4fSDavid du Colombier case MBOTH:
6519a747e4fSDavid du Colombier fmod = FREAD+FWRITE;
6529a747e4fSDavid du Colombier break;
6539a747e4fSDavid du Colombier
6549a747e4fSDavid du Colombier default:
6559a747e4fSDavid du Colombier ou->err = Emode;
6569a747e4fSDavid du Colombier goto out;
6579a747e4fSDavid du Colombier }
6589a747e4fSDavid du Colombier if(in->perm & PDIR)
6599a747e4fSDavid du Colombier if((in->mode & MTRUNC) || (in->perm & PAPND) || (fmod & FWRITE))
6609a747e4fSDavid du Colombier goto badaccess;
6619a747e4fSDavid du Colombier /*
6629a747e4fSDavid du Colombier * do it
6639a747e4fSDavid du Colombier */
6649a747e4fSDavid du Colombier path = qidpathgen(&f->fs->dev);
6659a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, addr1, Bread|Bimm|Bmod);
6669a747e4fSDavid du Colombier d1 = getdir(p1, slot1);
6679a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, d->qid.path)) {
6689a747e4fSDavid du Colombier if(p1)
6699a747e4fSDavid du Colombier putbuf(p1);
6709a747e4fSDavid du Colombier goto phase;
6719a747e4fSDavid du Colombier }
6729a747e4fSDavid du Colombier if(d1->mode & DALLOC) {
6739a747e4fSDavid du Colombier putbuf(p1);
6749a747e4fSDavid du Colombier goto phase;
6759a747e4fSDavid du Colombier }
6769a747e4fSDavid du Colombier
6779a747e4fSDavid du Colombier strncpy(d1->name, in->name, sizeof(in->name));
6789a747e4fSDavid du Colombier /*
6799a747e4fSDavid du Colombier * bogus argument passing -- see console.c
6809a747e4fSDavid du Colombier */
6819a747e4fSDavid du Colombier if(cp == cons.chan) {
6829a747e4fSDavid du Colombier d1->uid = cons.uid;
6839a747e4fSDavid du Colombier d1->gid = cons.gid;
6849a747e4fSDavid du Colombier } else {
6859a747e4fSDavid du Colombier d1->uid = f->uid;
6869a747e4fSDavid du Colombier d1->gid = d->gid;
6879a747e4fSDavid du Colombier in->perm &= d->mode | ~0666;
6889a747e4fSDavid du Colombier if(in->perm & PDIR)
6899a747e4fSDavid du Colombier in->perm &= d->mode | ~0777;
6909a747e4fSDavid du Colombier }
6919a747e4fSDavid du Colombier d1->qid.path = path;
6929a747e4fSDavid du Colombier d1->qid.version = 0;
6939a747e4fSDavid du Colombier d1->mode = DALLOC | (in->perm & 0777);
6949a747e4fSDavid du Colombier if(in->perm & PDIR) {
6959a747e4fSDavid du Colombier d1->mode |= DDIR;
6969a747e4fSDavid du Colombier d1->qid.path |= QPDIR;
6979a747e4fSDavid du Colombier }
6989a747e4fSDavid du Colombier if(in->perm & PAPND)
6999a747e4fSDavid du Colombier d1->mode |= DAPND;
7009a747e4fSDavid du Colombier t = 0;
7019a747e4fSDavid du Colombier if(in->perm & PLOCK) {
7029a747e4fSDavid du Colombier d1->mode |= DLOCK;
7039a747e4fSDavid du Colombier t = tlocked(p1, d1);
7049a747e4fSDavid du Colombier }
7059a747e4fSDavid du Colombier accessdir(p1, d1, FWRITE);
7069a747e4fSDavid du Colombier mkqid(&qid, d1, 0);
7079a747e4fSDavid du Colombier putbuf(p1);
7089a747e4fSDavid du Colombier accessdir(p, d, FWRITE);
7099a747e4fSDavid du Colombier
7109a747e4fSDavid du Colombier /*
7119a747e4fSDavid du Colombier * do a walk to new directory entry
7129a747e4fSDavid du Colombier */
7139a747e4fSDavid du Colombier w = newwp();
7149a747e4fSDavid du Colombier if(!w) {
7159a747e4fSDavid du Colombier ou->err = Ewalk;
7169a747e4fSDavid du Colombier goto out;
7179a747e4fSDavid du Colombier }
7189a747e4fSDavid du Colombier w->addr = f->addr;
7199a747e4fSDavid du Colombier w->slot = f->slot;
7209a747e4fSDavid du Colombier w->up = f->wpath;
7219a747e4fSDavid du Colombier f->wpath = w;
7229a747e4fSDavid du Colombier f->qid = qid;
7239a747e4fSDavid du Colombier f->tlock = t;
7249a747e4fSDavid du Colombier f->lastra = 0;
7259a747e4fSDavid du Colombier if(in->mode & MRCLOSE)
7269a747e4fSDavid du Colombier fmod |= FREMOV;
7279a747e4fSDavid du Colombier f->open = fmod;
7289a747e4fSDavid du Colombier f->addr = addr1;
7299a747e4fSDavid du Colombier f->slot = slot1;
7309a747e4fSDavid du Colombier if(t)
7319a747e4fSDavid du Colombier t->file = f;
7329a747e4fSDavid du Colombier mkqid9p1(&ou->qid, &qid);
7339a747e4fSDavid du Colombier goto out;
7349a747e4fSDavid du Colombier
7359a747e4fSDavid du Colombier badaccess:
7369a747e4fSDavid du Colombier ou->err = Eaccess;
7379a747e4fSDavid du Colombier goto out;
7389a747e4fSDavid du Colombier
7399a747e4fSDavid du Colombier phase:
7409a747e4fSDavid du Colombier ou->err = Ephase;
7419a747e4fSDavid du Colombier
7429a747e4fSDavid du Colombier out:
7439a747e4fSDavid du Colombier if(p)
7449a747e4fSDavid du Colombier putbuf(p);
7459a747e4fSDavid du Colombier if(f)
7469a747e4fSDavid du Colombier qunlock(f);
7479a747e4fSDavid du Colombier ou->fid = in->fid;
7489a747e4fSDavid du Colombier }
7499a747e4fSDavid du Colombier
7509a747e4fSDavid du Colombier void
f_read(Chan * cp,Oldfcall * in,Oldfcall * ou)7519a747e4fSDavid du Colombier f_read(Chan *cp, Oldfcall *in, Oldfcall *ou)
7529a747e4fSDavid du Colombier {
7539a747e4fSDavid du Colombier Iobuf *p, *p1;
7549a747e4fSDavid du Colombier File *f;
7559a747e4fSDavid du Colombier Dentry *d, *d1;
7569a747e4fSDavid du Colombier Tlock *t;
7579a747e4fSDavid du Colombier long addr, offset, tim;
7589a747e4fSDavid du Colombier int nread, count, n, o, slot;
7599a747e4fSDavid du Colombier
7609a747e4fSDavid du Colombier if(CHAT(cp)) {
7619a747e4fSDavid du Colombier print("c_read %d\n", cp->chan);
7629a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
7639a747e4fSDavid du Colombier print(" offset = %ld\n", in->offset);
7649a747e4fSDavid du Colombier print(" count = %ld\n", in->count);
7659a747e4fSDavid du Colombier }
7669a747e4fSDavid du Colombier
7679a747e4fSDavid du Colombier p = 0;
7689a747e4fSDavid du Colombier count = in->count;
7699a747e4fSDavid du Colombier offset = in->offset;
7709a747e4fSDavid du Colombier nread = 0;
7719a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
7729a747e4fSDavid du Colombier if(!f) {
7739a747e4fSDavid du Colombier ou->err = Efid;
7749a747e4fSDavid du Colombier goto out;
7759a747e4fSDavid du Colombier }
7769a747e4fSDavid du Colombier if(!(f->open & FREAD)) {
7779a747e4fSDavid du Colombier ou->err = Eopen;
7789a747e4fSDavid du Colombier goto out;
7799a747e4fSDavid du Colombier }
7809a747e4fSDavid du Colombier if(count < 0 || count > MAXDAT) {
7819a747e4fSDavid du Colombier ou->err = Ecount;
7829a747e4fSDavid du Colombier goto out;
7839a747e4fSDavid du Colombier }
7849a747e4fSDavid du Colombier if(offset < 0) {
7859a747e4fSDavid du Colombier ou->err = Eoffset;
7869a747e4fSDavid du Colombier goto out;
7879a747e4fSDavid du Colombier }
7889a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
7899a747e4fSDavid du Colombier d = getdir(p, f->slot);
7909a747e4fSDavid du Colombier if(!d || !(d->mode & DALLOC)) {
7919a747e4fSDavid du Colombier ou->err = Ealloc;
7929a747e4fSDavid du Colombier goto out;
7939a747e4fSDavid du Colombier }
7949a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
7959a747e4fSDavid du Colombier goto out;
7969a747e4fSDavid du Colombier if(t = f->tlock) {
7979a747e4fSDavid du Colombier tim = time(0);
7989a747e4fSDavid du Colombier if(t->time < tim || t->file != f) {
7999a747e4fSDavid du Colombier ou->err = Ebroken;
8009a747e4fSDavid du Colombier goto out;
8019a747e4fSDavid du Colombier }
8029a747e4fSDavid du Colombier /* renew the lock */
8039a747e4fSDavid du Colombier t->time = tim + TLOCK;
8049a747e4fSDavid du Colombier }
8059a747e4fSDavid du Colombier accessdir(p, d, FREAD);
8069a747e4fSDavid du Colombier if(d->mode & DDIR) {
8079a747e4fSDavid du Colombier addr = 0;
8089a747e4fSDavid du Colombier goto dread;
8099a747e4fSDavid du Colombier }
8109a747e4fSDavid du Colombier if(offset+count > d->size)
8119a747e4fSDavid du Colombier count = d->size - offset;
8129a747e4fSDavid du Colombier while(count > 0) {
8139a747e4fSDavid du Colombier addr = offset / BUFSIZE;
8149a747e4fSDavid du Colombier if(addr == f->lastra+1)
8159a747e4fSDavid du Colombier dbufread(p, d, addr+1);
8169a747e4fSDavid du Colombier f->lastra = addr;
8179a747e4fSDavid du Colombier o = offset % BUFSIZE;
8189a747e4fSDavid du Colombier n = BUFSIZE - o;
8199a747e4fSDavid du Colombier if(n > count)
8209a747e4fSDavid du Colombier n = count;
8219a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0);
8229a747e4fSDavid du Colombier if(p1) {
8239a747e4fSDavid du Colombier if(checktag(p1, Tfile, QPNONE)) {
8249a747e4fSDavid du Colombier ou->err = Ephase;
8259a747e4fSDavid du Colombier putbuf(p1);
8269a747e4fSDavid du Colombier goto out;
8279a747e4fSDavid du Colombier }
8289a747e4fSDavid du Colombier memmove(ou->data+nread, p1->iobuf+o, n);
8299a747e4fSDavid du Colombier putbuf(p1);
8309a747e4fSDavid du Colombier } else
8319a747e4fSDavid du Colombier memset(ou->data+nread, 0, n);
8329a747e4fSDavid du Colombier count -= n;
8339a747e4fSDavid du Colombier nread += n;
8349a747e4fSDavid du Colombier offset += n;
8359a747e4fSDavid du Colombier }
8369a747e4fSDavid du Colombier goto out;
8379a747e4fSDavid du Colombier
8389a747e4fSDavid du Colombier dread:
8399a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0);
8409a747e4fSDavid du Colombier if(!p1)
8419a747e4fSDavid du Colombier goto out;
8429a747e4fSDavid du Colombier if(checktag(p1, Tdir, QPNONE)) {
8439a747e4fSDavid du Colombier ou->err = Ephase;
8449a747e4fSDavid du Colombier putbuf(p1);
8459a747e4fSDavid du Colombier goto out;
8469a747e4fSDavid du Colombier }
8479a747e4fSDavid du Colombier n = DIRREC;
8489a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) {
8499a747e4fSDavid du Colombier d1 = getdir(p1, slot);
8509a747e4fSDavid du Colombier if(!(d1->mode & DALLOC))
8519a747e4fSDavid du Colombier continue;
8529a747e4fSDavid du Colombier if(offset >= n) {
8539a747e4fSDavid du Colombier offset -= n;
8549a747e4fSDavid du Colombier continue;
8559a747e4fSDavid du Colombier }
8569a747e4fSDavid du Colombier if(count < n) {
8579a747e4fSDavid du Colombier putbuf(p1);
8589a747e4fSDavid du Colombier goto out;
8599a747e4fSDavid du Colombier }
8609a747e4fSDavid du Colombier if(convD2M9p1(d1, ou->data+nread) != n)
8619a747e4fSDavid du Colombier print("dirread convD2M\n");
8629a747e4fSDavid du Colombier nread += n;
8639a747e4fSDavid du Colombier count -= n;
8649a747e4fSDavid du Colombier }
8659a747e4fSDavid du Colombier putbuf(p1);
8669a747e4fSDavid du Colombier addr++;
8679a747e4fSDavid du Colombier goto dread;
8689a747e4fSDavid du Colombier
8699a747e4fSDavid du Colombier out:
8709a747e4fSDavid du Colombier count = in->count - nread;
8719a747e4fSDavid du Colombier if(count > 0)
8729a747e4fSDavid du Colombier memset(ou->data+nread, 0, count);
8739a747e4fSDavid du Colombier if(p)
8749a747e4fSDavid du Colombier putbuf(p);
8759a747e4fSDavid du Colombier if(f)
8769a747e4fSDavid du Colombier qunlock(f);
8779a747e4fSDavid du Colombier ou->fid = in->fid;
8789a747e4fSDavid du Colombier ou->count = nread;
8799a747e4fSDavid du Colombier if(CHAT(cp))
8809a747e4fSDavid du Colombier print(" nread = %d\n", nread);
8819a747e4fSDavid du Colombier }
8829a747e4fSDavid du Colombier
8839a747e4fSDavid du Colombier void
f_write(Chan * cp,Oldfcall * in,Oldfcall * ou)8849a747e4fSDavid du Colombier f_write(Chan *cp, Oldfcall *in, Oldfcall *ou)
8859a747e4fSDavid du Colombier {
8869a747e4fSDavid du Colombier Iobuf *p, *p1;
8879a747e4fSDavid du Colombier Dentry *d;
8889a747e4fSDavid du Colombier File *f;
8899a747e4fSDavid du Colombier Tlock *t;
8909a747e4fSDavid du Colombier long offset, addr, tim;
8919a747e4fSDavid du Colombier int count, nwrite, o, n;
8929a747e4fSDavid du Colombier
8939a747e4fSDavid du Colombier if(CHAT(cp)) {
8949a747e4fSDavid du Colombier print("c_write %d\n", cp->chan);
8959a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
8969a747e4fSDavid du Colombier print(" offset = %ld\n", in->offset);
8979a747e4fSDavid du Colombier print(" count = %ld\n", in->count);
8989a747e4fSDavid du Colombier }
8999a747e4fSDavid du Colombier
9009a747e4fSDavid du Colombier offset = in->offset;
9019a747e4fSDavid du Colombier count = in->count;
9029a747e4fSDavid du Colombier nwrite = 0;
9039a747e4fSDavid du Colombier p = 0;
9049a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
9059a747e4fSDavid du Colombier if(!f) {
9069a747e4fSDavid du Colombier ou->err = Efid;
9079a747e4fSDavid du Colombier goto out;
9089a747e4fSDavid du Colombier }
9099a747e4fSDavid du Colombier if(!(f->open & FWRITE)) {
9109a747e4fSDavid du Colombier ou->err = Eopen;
9119a747e4fSDavid du Colombier goto out;
9129a747e4fSDavid du Colombier }
9135d459b5aSDavid du Colombier if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
9149a747e4fSDavid du Colombier ou->err = Eronly;
9159a747e4fSDavid du Colombier goto out;
9169a747e4fSDavid du Colombier }
9179a747e4fSDavid du Colombier if(count < 0 || count > MAXDAT) {
9189a747e4fSDavid du Colombier ou->err = Ecount;
9199a747e4fSDavid du Colombier goto out;
9209a747e4fSDavid du Colombier }
9219a747e4fSDavid du Colombier if(offset < 0) {
9229a747e4fSDavid du Colombier ou->err = Eoffset;
9239a747e4fSDavid du Colombier goto out;
9249a747e4fSDavid du Colombier }
9259a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread|Bmod);
9269a747e4fSDavid du Colombier d = getdir(p, f->slot);
9279a747e4fSDavid du Colombier if(!d || !(d->mode & DALLOC)) {
9289a747e4fSDavid du Colombier ou->err = Ealloc;
9299a747e4fSDavid du Colombier goto out;
9309a747e4fSDavid du Colombier }
9319a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
9329a747e4fSDavid du Colombier goto out;
9339a747e4fSDavid du Colombier if(t = f->tlock) {
9349a747e4fSDavid du Colombier tim = time(0);
9359a747e4fSDavid du Colombier if(t->time < tim || t->file != f) {
9369a747e4fSDavid du Colombier ou->err = Ebroken;
9379a747e4fSDavid du Colombier goto out;
9389a747e4fSDavid du Colombier }
9399a747e4fSDavid du Colombier /* renew the lock */
9409a747e4fSDavid du Colombier t->time = tim + TLOCK;
9419a747e4fSDavid du Colombier }
9429a747e4fSDavid du Colombier accessdir(p, d, FWRITE);
9439a747e4fSDavid du Colombier if(d->mode & DAPND)
9449a747e4fSDavid du Colombier offset = d->size;
9459a747e4fSDavid du Colombier if(offset+count > d->size)
9469a747e4fSDavid du Colombier d->size = offset+count;
9479a747e4fSDavid du Colombier while(count > 0) {
9489a747e4fSDavid du Colombier addr = offset / BUFSIZE;
9499a747e4fSDavid du Colombier o = offset % BUFSIZE;
9509a747e4fSDavid du Colombier n = BUFSIZE - o;
9519a747e4fSDavid du Colombier if(n > count)
9529a747e4fSDavid du Colombier n = count;
9539a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, Tfile);
9549a747e4fSDavid du Colombier if(p1 == 0) {
9559a747e4fSDavid du Colombier ou->err = Efull;
9569a747e4fSDavid du Colombier goto out;
9579a747e4fSDavid du Colombier }
9589a747e4fSDavid du Colombier if(checktag(p1, Tfile, d->qid.path)) {
9599a747e4fSDavid du Colombier putbuf(p1);
9609a747e4fSDavid du Colombier ou->err = Ephase;
9619a747e4fSDavid du Colombier goto out;
9629a747e4fSDavid du Colombier }
9639a747e4fSDavid du Colombier memmove(p1->iobuf+o, in->data+nwrite, n);
9649a747e4fSDavid du Colombier p1->flags |= Bmod;
9659a747e4fSDavid du Colombier putbuf(p1);
9669a747e4fSDavid du Colombier count -= n;
9679a747e4fSDavid du Colombier nwrite += n;
9689a747e4fSDavid du Colombier offset += n;
9699a747e4fSDavid du Colombier }
9709a747e4fSDavid du Colombier if(CHAT(cp))
9719a747e4fSDavid du Colombier print(" nwrite = %d\n", nwrite);
9729a747e4fSDavid du Colombier
9739a747e4fSDavid du Colombier out:
9749a747e4fSDavid du Colombier if(p)
9759a747e4fSDavid du Colombier putbuf(p);
9769a747e4fSDavid du Colombier if(f)
9779a747e4fSDavid du Colombier qunlock(f);
9789a747e4fSDavid du Colombier ou->fid = in->fid;
9799a747e4fSDavid du Colombier ou->count = nwrite;
9809a747e4fSDavid du Colombier }
9819a747e4fSDavid du Colombier
9829a747e4fSDavid du Colombier int
doremove(File * f,int iscon)9839a747e4fSDavid du Colombier doremove(File *f, int iscon)
9849a747e4fSDavid du Colombier {
9859a747e4fSDavid du Colombier Iobuf *p, *p1;
9869a747e4fSDavid du Colombier Dentry *d, *d1;
9879a747e4fSDavid du Colombier long addr;
9889a747e4fSDavid du Colombier int slot, err;
9899a747e4fSDavid du Colombier
9909a747e4fSDavid du Colombier p = 0;
9919a747e4fSDavid du Colombier p1 = 0;
9925d459b5aSDavid du Colombier if(isro(f->fs->dev) || (f->cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
9939a747e4fSDavid du Colombier err = Eronly;
9949a747e4fSDavid du Colombier goto out;
9959a747e4fSDavid du Colombier }
9969a747e4fSDavid du Colombier /*
9979a747e4fSDavid du Colombier * check on parent directory of file to be deleted
9989a747e4fSDavid du Colombier */
9999a747e4fSDavid du Colombier if(f->wpath == 0 || f->wpath->addr == f->addr) {
10009a747e4fSDavid du Colombier err = Ephase;
10019a747e4fSDavid du Colombier goto out;
10029a747e4fSDavid du Colombier }
10039a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);
10049a747e4fSDavid du Colombier d1 = getdir(p1, f->wpath->slot);
10059a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
10069a747e4fSDavid du Colombier err = Ephase;
10079a747e4fSDavid du Colombier goto out;
10089a747e4fSDavid du Colombier }
10099a747e4fSDavid du Colombier if(!iscon && iaccess(f, d1, DWRITE)) {
10109a747e4fSDavid du Colombier err = Eaccess;
10119a747e4fSDavid du Colombier goto out;
10129a747e4fSDavid du Colombier }
10139a747e4fSDavid du Colombier accessdir(p1, d1, FWRITE);
10149a747e4fSDavid du Colombier putbuf(p1);
10159a747e4fSDavid du Colombier p1 = 0;
10169a747e4fSDavid du Colombier
10179a747e4fSDavid du Colombier /*
10189a747e4fSDavid du Colombier * check on file to be deleted
10199a747e4fSDavid du Colombier */
10209a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
10219a747e4fSDavid du Colombier d = getdir(p, f->slot);
10229a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
10239a747e4fSDavid du Colombier err = Ealloc;
10249a747e4fSDavid du Colombier goto out;
10259a747e4fSDavid du Colombier }
10269a747e4fSDavid du Colombier if(err = mkqidcmp(&f->qid, d))
10279a747e4fSDavid du Colombier goto out;
10289a747e4fSDavid du Colombier
10299a747e4fSDavid du Colombier /*
10309a747e4fSDavid du Colombier * if deleting a directory, make sure it is empty
10319a747e4fSDavid du Colombier */
10329a747e4fSDavid du Colombier if((d->mode & DDIR))
10339a747e4fSDavid du Colombier for(addr=0;; addr++) {
10349a747e4fSDavid du Colombier p1 = dnodebuf(p, d, addr, 0);
10359a747e4fSDavid du Colombier if(!p1)
10369a747e4fSDavid du Colombier break;
10379a747e4fSDavid du Colombier if(checktag(p1, Tdir, d->qid.path)) {
10389a747e4fSDavid du Colombier err = Ephase;
10399a747e4fSDavid du Colombier goto out;
10409a747e4fSDavid du Colombier }
10419a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) {
10429a747e4fSDavid du Colombier d1 = getdir(p1, slot);
10439a747e4fSDavid du Colombier if(!(d1->mode & DALLOC))
10449a747e4fSDavid du Colombier continue;
10459a747e4fSDavid du Colombier err = Eempty;
10469a747e4fSDavid du Colombier goto out;
10479a747e4fSDavid du Colombier }
10489a747e4fSDavid du Colombier putbuf(p1);
10499a747e4fSDavid du Colombier }
10509a747e4fSDavid du Colombier
10519a747e4fSDavid du Colombier /*
10529a747e4fSDavid du Colombier * do it
10539a747e4fSDavid du Colombier */
10549a747e4fSDavid du Colombier dtrunc(p, d);
10559a747e4fSDavid du Colombier memset(d, 0, sizeof(Dentry));
10569a747e4fSDavid du Colombier settag(p, Tdir, QPNONE);
10579a747e4fSDavid du Colombier
10589a747e4fSDavid du Colombier out:
10599a747e4fSDavid du Colombier if(p1)
10609a747e4fSDavid du Colombier putbuf(p1);
10619a747e4fSDavid du Colombier if(p)
10629a747e4fSDavid du Colombier putbuf(p);
10639a747e4fSDavid du Colombier return err;
10649a747e4fSDavid du Colombier }
10659a747e4fSDavid du Colombier
10669a747e4fSDavid du Colombier void
f_remove(Chan * cp,Oldfcall * in,Oldfcall * ou)10679a747e4fSDavid du Colombier f_remove(Chan *cp, Oldfcall *in, Oldfcall *ou)
10689a747e4fSDavid du Colombier {
10699a747e4fSDavid du Colombier File *f;
10709a747e4fSDavid du Colombier
10719a747e4fSDavid du Colombier if(CHAT(cp)) {
10729a747e4fSDavid du Colombier print("c_remove %d\n", cp->chan);
10739a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
10749a747e4fSDavid du Colombier }
10759a747e4fSDavid du Colombier
10769a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
10779a747e4fSDavid du Colombier if(!f) {
10789a747e4fSDavid du Colombier ou->err = Efid;
10799a747e4fSDavid du Colombier goto out;
10809a747e4fSDavid du Colombier }
10819a747e4fSDavid du Colombier ou->err = doremove(f, cp==cons.chan);
10829a747e4fSDavid du Colombier
10839a747e4fSDavid du Colombier out:
10849a747e4fSDavid du Colombier ou->fid = in->fid;
10859a747e4fSDavid du Colombier if(f)
10869a747e4fSDavid du Colombier qunlock(f);
10879a747e4fSDavid du Colombier }
10889a747e4fSDavid du Colombier
10899a747e4fSDavid du Colombier void
f_stat(Chan * cp,Oldfcall * in,Oldfcall * ou)10909a747e4fSDavid du Colombier f_stat(Chan *cp, Oldfcall *in, Oldfcall *ou)
10919a747e4fSDavid du Colombier {
10929a747e4fSDavid du Colombier Iobuf *p;
10939a747e4fSDavid du Colombier Dentry *d;
10949a747e4fSDavid du Colombier File *f;
10959a747e4fSDavid du Colombier
10969a747e4fSDavid du Colombier if(CHAT(cp)) {
10979a747e4fSDavid du Colombier print("c_stat %d\n", cp->chan);
10989a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
10999a747e4fSDavid du Colombier }
11009a747e4fSDavid du Colombier
11019a747e4fSDavid du Colombier p = 0;
11029a747e4fSDavid du Colombier memset(ou->stat, 0, sizeof(ou->stat));
11039a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
11049a747e4fSDavid du Colombier if(!f) {
11059a747e4fSDavid du Colombier ou->err = Efid;
11069a747e4fSDavid du Colombier goto out;
11079a747e4fSDavid du Colombier }
11089a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
11099a747e4fSDavid du Colombier d = getdir(p, f->slot);
11109a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
11119a747e4fSDavid du Colombier ou->err = Ealloc;
11129a747e4fSDavid du Colombier goto out;
11139a747e4fSDavid du Colombier }
11149a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
11159a747e4fSDavid du Colombier goto out;
11169a747e4fSDavid du Colombier if(d->qid.path == QPROOT) /* stat of root gives time */
11179a747e4fSDavid du Colombier d->atime = time(0);
11189a747e4fSDavid du Colombier if(convD2M9p1(d, ou->stat) != DIRREC)
11199a747e4fSDavid du Colombier print("stat convD2M\n");
11209a747e4fSDavid du Colombier
11219a747e4fSDavid du Colombier out:
11229a747e4fSDavid du Colombier if(p)
11239a747e4fSDavid du Colombier putbuf(p);
11249a747e4fSDavid du Colombier if(f)
11259a747e4fSDavid du Colombier qunlock(f);
11269a747e4fSDavid du Colombier ou->fid = in->fid;
11279a747e4fSDavid du Colombier }
11289a747e4fSDavid du Colombier
11299a747e4fSDavid du Colombier void
f_wstat(Chan * cp,Oldfcall * in,Oldfcall * ou)11309a747e4fSDavid du Colombier f_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou)
11319a747e4fSDavid du Colombier {
11329a747e4fSDavid du Colombier Iobuf *p, *p1;
11339a747e4fSDavid du Colombier Dentry *d, *d1, xd;
11349a747e4fSDavid du Colombier File *f;
11359a747e4fSDavid du Colombier int slot;
11369a747e4fSDavid du Colombier long addr;
11379a747e4fSDavid du Colombier
11389a747e4fSDavid du Colombier if(CHAT(cp)) {
11399a747e4fSDavid du Colombier print("c_wstat %d\n", cp->chan);
11409a747e4fSDavid du Colombier print(" fid = %d\n", in->fid);
11419a747e4fSDavid du Colombier }
11429a747e4fSDavid du Colombier
11439a747e4fSDavid du Colombier p = 0;
11449a747e4fSDavid du Colombier p1 = 0;
11459a747e4fSDavid du Colombier d1 = 0;
11469a747e4fSDavid du Colombier f = filep(cp, in->fid, 0);
11479a747e4fSDavid du Colombier if(!f) {
11489a747e4fSDavid du Colombier ou->err = Efid;
11499a747e4fSDavid du Colombier goto out;
11509a747e4fSDavid du Colombier }
11515d459b5aSDavid du Colombier if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) {
11529a747e4fSDavid du Colombier ou->err = Eronly;
11539a747e4fSDavid du Colombier goto out;
11549a747e4fSDavid du Colombier }
11559a747e4fSDavid du Colombier
11569a747e4fSDavid du Colombier /*
11579a747e4fSDavid du Colombier * first get parent
11589a747e4fSDavid du Colombier */
11599a747e4fSDavid du Colombier if(f->wpath) {
11609a747e4fSDavid du Colombier p1 = getbuf(f->fs->dev, f->wpath->addr, Bread);
11619a747e4fSDavid du Colombier d1 = getdir(p1, f->wpath->slot);
11629a747e4fSDavid du Colombier if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) {
11639a747e4fSDavid du Colombier ou->err = Ephase;
11649a747e4fSDavid du Colombier goto out;
11659a747e4fSDavid du Colombier }
11669a747e4fSDavid du Colombier }
11679a747e4fSDavid du Colombier
11689a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
11699a747e4fSDavid du Colombier d = getdir(p, f->slot);
11709a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
11719a747e4fSDavid du Colombier ou->err = Ealloc;
11729a747e4fSDavid du Colombier goto out;
11739a747e4fSDavid du Colombier }
11749a747e4fSDavid du Colombier if(ou->err = mkqidcmp(&f->qid, d))
11759a747e4fSDavid du Colombier goto out;
11769a747e4fSDavid du Colombier
11779a747e4fSDavid du Colombier convM2D9p1(in->stat, &xd);
11789a747e4fSDavid du Colombier if(CHAT(cp)) {
11799a747e4fSDavid du Colombier print(" d.name = %s\n", xd.name);
11809a747e4fSDavid du Colombier print(" d.uid = %d\n", xd.uid);
11819a747e4fSDavid du Colombier print(" d.gid = %d\n", xd.gid);
11829a747e4fSDavid du Colombier print(" d.mode = %.4x\n", xd.mode);
11839a747e4fSDavid du Colombier }
11849a747e4fSDavid du Colombier
11859a747e4fSDavid du Colombier /*
11869a747e4fSDavid du Colombier * if chown,
11879a747e4fSDavid du Colombier * must be god
11889a747e4fSDavid du Colombier */
11899a747e4fSDavid du Colombier while(xd.uid != d->uid) {
11909a747e4fSDavid du Colombier if(wstatallow) /* set to allow chown during boot */
11919a747e4fSDavid du Colombier break;
11929a747e4fSDavid du Colombier ou->err = Enotu;
11939a747e4fSDavid du Colombier goto out;
11949a747e4fSDavid du Colombier }
11959a747e4fSDavid du Colombier
11969a747e4fSDavid du Colombier /*
11979a747e4fSDavid du Colombier * if chgroup,
11989a747e4fSDavid du Colombier * must be either
11999a747e4fSDavid du Colombier * a) owner and in new group
12009a747e4fSDavid du Colombier * b) leader of both groups
12019a747e4fSDavid du Colombier */
12029a747e4fSDavid du Colombier while(xd.gid != d->gid) {
12039a747e4fSDavid du Colombier if(wstatallow || writeallow) /* set to allow chgrp during boot */
12049a747e4fSDavid du Colombier break;
12059a747e4fSDavid du Colombier if(d->uid == f->uid && ingroup(f->uid, xd.gid))
12069a747e4fSDavid du Colombier break;
12079a747e4fSDavid du Colombier if(leadgroup(f->uid, xd.gid))
12089a747e4fSDavid du Colombier if(leadgroup(f->uid, d->gid))
12099a747e4fSDavid du Colombier break;
12109a747e4fSDavid du Colombier ou->err = Enotg;
12119a747e4fSDavid du Colombier goto out;
12129a747e4fSDavid du Colombier }
12139a747e4fSDavid du Colombier
12149a747e4fSDavid du Colombier /*
12159a747e4fSDavid du Colombier * if rename,
12169a747e4fSDavid du Colombier * must have write permission in parent
12179a747e4fSDavid du Colombier */
12189a747e4fSDavid du Colombier if(xd.name[0] == 0)
12199a747e4fSDavid du Colombier strncpy(xd.name, d->name, sizeof(xd.name));
12209a747e4fSDavid du Colombier while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) {
12219a747e4fSDavid du Colombier if(checkname(xd.name)) {
12229a747e4fSDavid du Colombier ou->err = Ename;
12239a747e4fSDavid du Colombier goto out;
12249a747e4fSDavid du Colombier }
12259a747e4fSDavid du Colombier
12269a747e4fSDavid du Colombier if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) {
12279a747e4fSDavid du Colombier ou->err = Ename;
12289a747e4fSDavid du Colombier goto out;
12299a747e4fSDavid du Colombier }
12309a747e4fSDavid du Colombier
12319a747e4fSDavid du Colombier /*
12329a747e4fSDavid du Colombier * drop entry to prevent lock, then
12339a747e4fSDavid du Colombier * check that destination name is unique,
12349a747e4fSDavid du Colombier */
12359a747e4fSDavid du Colombier putbuf(p);
12369a747e4fSDavid du Colombier for(addr=0;; addr++) {
12379a747e4fSDavid du Colombier p = dnodebuf(p1, d1, addr, 0);
12389a747e4fSDavid du Colombier if(!p)
12399a747e4fSDavid du Colombier break;
12409a747e4fSDavid du Colombier if(checktag(p, Tdir, d1->qid.path)) {
12419a747e4fSDavid du Colombier putbuf(p);
12429a747e4fSDavid du Colombier continue;
12439a747e4fSDavid du Colombier }
12449a747e4fSDavid du Colombier for(slot=0; slot<DIRPERBUF; slot++) {
12459a747e4fSDavid du Colombier d = getdir(p, slot);
12469a747e4fSDavid du Colombier if(!(d->mode & DALLOC))
12479a747e4fSDavid du Colombier continue;
12489a747e4fSDavid du Colombier if(!strncmp(xd.name, d->name, sizeof(xd.name))) {
12499a747e4fSDavid du Colombier ou->err = Eexist;
12509a747e4fSDavid du Colombier goto out;
12519a747e4fSDavid du Colombier }
12529a747e4fSDavid du Colombier }
12539a747e4fSDavid du Colombier putbuf(p);
12549a747e4fSDavid du Colombier }
12559a747e4fSDavid du Colombier
12569a747e4fSDavid du Colombier /*
12579a747e4fSDavid du Colombier * reacquire entry
12589a747e4fSDavid du Colombier */
12599a747e4fSDavid du Colombier p = getbuf(f->fs->dev, f->addr, Bread);
12609a747e4fSDavid du Colombier d = getdir(p, f->slot);
12619a747e4fSDavid du Colombier if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) {
12629a747e4fSDavid du Colombier ou->err = Ephase;
12639a747e4fSDavid du Colombier goto out;
12649a747e4fSDavid du Colombier }
12659a747e4fSDavid du Colombier
12669a747e4fSDavid du Colombier if(wstatallow || writeallow) /* set to allow rename during boot */
12679a747e4fSDavid du Colombier break;
12689a747e4fSDavid du Colombier if(!d1 || iaccess(f, d1, DWRITE)) {
12699a747e4fSDavid du Colombier ou->err = Eaccess;
12709a747e4fSDavid du Colombier goto out;
12719a747e4fSDavid du Colombier }
12729a747e4fSDavid du Colombier break;
12739a747e4fSDavid du Colombier }
12749a747e4fSDavid du Colombier
12759a747e4fSDavid du Colombier /*
12769a747e4fSDavid du Colombier * if mode/time, either
12779a747e4fSDavid du Colombier * a) owner
12789a747e4fSDavid du Colombier * b) leader of either group
12799a747e4fSDavid du Colombier */
12809a747e4fSDavid du Colombier while(d->mtime != xd.mtime ||
12819a747e4fSDavid du Colombier ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) {
12829a747e4fSDavid du Colombier if(wstatallow) /* set to allow chmod during boot */
12839a747e4fSDavid du Colombier break;
12849a747e4fSDavid du Colombier if(d->uid == f->uid)
12859a747e4fSDavid du Colombier break;
12869a747e4fSDavid du Colombier if(leadgroup(f->uid, xd.gid))
12879a747e4fSDavid du Colombier break;
12889a747e4fSDavid du Colombier if(leadgroup(f->uid, d->gid))
12899a747e4fSDavid du Colombier break;
12909a747e4fSDavid du Colombier ou->err = Enotu;
12919a747e4fSDavid du Colombier goto out;
12929a747e4fSDavid du Colombier }
12939a747e4fSDavid du Colombier d->mtime = xd.mtime;
12949a747e4fSDavid du Colombier d->uid = xd.uid;
12959a747e4fSDavid du Colombier d->gid = xd.gid;
12969a747e4fSDavid du Colombier d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR));
12979a747e4fSDavid du Colombier
12989a747e4fSDavid du Colombier strncpy(d->name, xd.name, sizeof(d->name));
12999a747e4fSDavid du Colombier if(wstatallow) {
13009a747e4fSDavid du Colombier p->flags |= Bmod;
13019a747e4fSDavid du Colombier if(xd.atime)
13029a747e4fSDavid du Colombier d->atime = xd.atime;
13039a747e4fSDavid du Colombier if(xd.mtime)
13049a747e4fSDavid du Colombier d->mtime = xd.mtime;
13059a747e4fSDavid du Colombier } else
1306*229d2d34SDavid du Colombier accessdir(p, d, FWSTAT);
13079a747e4fSDavid du Colombier
13089a747e4fSDavid du Colombier out:
13099a747e4fSDavid du Colombier if(p)
13109a747e4fSDavid du Colombier putbuf(p);
13119a747e4fSDavid du Colombier if(p1)
13129a747e4fSDavid du Colombier putbuf(p1);
13139a747e4fSDavid du Colombier if(f)
13149a747e4fSDavid du Colombier qunlock(f);
13159a747e4fSDavid du Colombier ou->fid = in->fid;
13169a747e4fSDavid du Colombier }
13179a747e4fSDavid du Colombier
13189a747e4fSDavid du Colombier void
13199a747e4fSDavid du Colombier (*call9p1[MAXSYSCALL])(Chan*, Oldfcall*, Oldfcall*) =
13209a747e4fSDavid du Colombier {
13219a747e4fSDavid du Colombier [Tnop9p1] f_nop,
13229a747e4fSDavid du Colombier [Tosession9p1] f_session,
13239a747e4fSDavid du Colombier [Tsession9p1] f_session,
13249a747e4fSDavid du Colombier [Tflush9p1] f_flush,
13259a747e4fSDavid du Colombier [Toattach9p1] f_attach,
13269a747e4fSDavid du Colombier [Tattach9p1] f_attach,
13279a747e4fSDavid du Colombier [Tclone9p1] f_clone,
13289a747e4fSDavid du Colombier [Twalk9p1] f_walk,
13299a747e4fSDavid du Colombier [Topen9p1] f_open,
13309a747e4fSDavid du Colombier [Tcreate9p1] f_create,
13319a747e4fSDavid du Colombier [Tread9p1] f_read,
13329a747e4fSDavid du Colombier [Twrite9p1] f_write,
13339a747e4fSDavid du Colombier [Tclunk9p1] f_clunk,
13349a747e4fSDavid du Colombier [Tremove9p1] f_remove,
13359a747e4fSDavid du Colombier [Tstat9p1] f_stat,
13369a747e4fSDavid du Colombier [Twstat9p1] f_wstat,
13379a747e4fSDavid du Colombier [Tclwalk9p1] f_clwalk,
13389a747e4fSDavid du Colombier };
13399a747e4fSDavid du Colombier
13409a747e4fSDavid du Colombier static void
send(Chan * c,uchar * buf,int n)13419a747e4fSDavid du Colombier send(Chan *c, uchar *buf, int n)
13429a747e4fSDavid du Colombier {
13439a747e4fSDavid du Colombier int fd, m;
13449a747e4fSDavid du Colombier
13459a747e4fSDavid du Colombier fd = c->chan;
13469a747e4fSDavid du Colombier m = write(fd, buf, n);
13479a747e4fSDavid du Colombier if(m == n)
13489a747e4fSDavid du Colombier return;
13499a747e4fSDavid du Colombier panic("write failed");
13509a747e4fSDavid du Colombier }
13519a747e4fSDavid du Colombier
13529a747e4fSDavid du Colombier void
error9p1(Chan * c,uchar * buf)13539a747e4fSDavid du Colombier error9p1(Chan *c, uchar *buf)
13549a747e4fSDavid du Colombier {
13559a747e4fSDavid du Colombier buf[0] = Rnop9p1;
13569a747e4fSDavid du Colombier buf[1] = ~0;
13579a747e4fSDavid du Colombier buf[2] = ~0;
13589a747e4fSDavid du Colombier
13599a747e4fSDavid du Colombier send(c, buf, 3);
13609a747e4fSDavid du Colombier }
13619a747e4fSDavid du Colombier
13629a747e4fSDavid du Colombier void
serve9p1(Chan * chan,uchar * ib,int nib)13639a747e4fSDavid du Colombier serve9p1(Chan *chan, uchar *ib, int nib)
13649a747e4fSDavid du Colombier {
13659a747e4fSDavid du Colombier int n, t;
13669a747e4fSDavid du Colombier uchar inbuf[MAXMSG+MAXDAT], outbuf[MAXMSG+MAXDAT];
13679a747e4fSDavid du Colombier Oldfcall fi, fo;
13689a747e4fSDavid du Colombier
13699a747e4fSDavid du Colombier for(;;){
13709a747e4fSDavid du Colombier if(nib){
13719a747e4fSDavid du Colombier memmove(inbuf, ib, nib);
13729a747e4fSDavid du Colombier n = nib;
13739a747e4fSDavid du Colombier nib = 0;
13749a747e4fSDavid du Colombier }else
13759a747e4fSDavid du Colombier n = read(chan->chan, inbuf, sizeof inbuf);
13769a747e4fSDavid du Colombier if(chat)
13779a747e4fSDavid du Colombier print("read msg %d\n", n);
13789a747e4fSDavid du Colombier if(n == 0 && (chan == cons.srvchan || chan == cons.chan))
13799a747e4fSDavid du Colombier continue;
13809a747e4fSDavid du Colombier if(n <= 0)
13819a747e4fSDavid du Colombier return;
13829a747e4fSDavid du Colombier if(convM2S9p1(inbuf, &fi, n) != n){
13839a747e4fSDavid du Colombier error9p1(chan, outbuf);
13849a747e4fSDavid du Colombier continue;
13859a747e4fSDavid du Colombier }
13869a747e4fSDavid du Colombier
13879a747e4fSDavid du Colombier t = fi.type;
13889a747e4fSDavid du Colombier if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) {
13899a747e4fSDavid du Colombier print("9p1: bad message type\n");
13909a747e4fSDavid du Colombier error9p1(chan, outbuf);
13919a747e4fSDavid du Colombier continue;
13929a747e4fSDavid du Colombier }
13939a747e4fSDavid du Colombier
13949a747e4fSDavid du Colombier if(CHAT(chan))
13959a747e4fSDavid du Colombier print("9p1: fi %O\n", &fi);
13969a747e4fSDavid du Colombier
13979a747e4fSDavid du Colombier /*
13989a747e4fSDavid du Colombier * set up reply message
13999a747e4fSDavid du Colombier */
14009a747e4fSDavid du Colombier fo.err = 0;
14019a747e4fSDavid du Colombier if(t == Tread9p1)
14029a747e4fSDavid du Colombier fo.data = (char*)outbuf + 8;
14039a747e4fSDavid du Colombier
14049a747e4fSDavid du Colombier /*
14059a747e4fSDavid du Colombier * call the file system
14069a747e4fSDavid du Colombier */
14079a747e4fSDavid du Colombier cons.work.count++;
14089a747e4fSDavid du Colombier cons.rate.count += n;
14099a747e4fSDavid du Colombier
14109a747e4fSDavid du Colombier /*
14119a747e4fSDavid du Colombier * call the file system
14129a747e4fSDavid du Colombier */
14139a747e4fSDavid du Colombier rlock(&mainlock);
14149a747e4fSDavid du Colombier rlock(&chan->reflock);
14159a747e4fSDavid du Colombier
14169a747e4fSDavid du Colombier (*call9p1[t])(chan, &fi, &fo);
14179a747e4fSDavid du Colombier
14189a747e4fSDavid du Colombier runlock(&chan->reflock);
14199a747e4fSDavid du Colombier runlock(&mainlock);
14209a747e4fSDavid du Colombier
14219a747e4fSDavid du Colombier fo.type = t+1;
14229a747e4fSDavid du Colombier fo.tag = fi.tag;
14239a747e4fSDavid du Colombier
14249a747e4fSDavid du Colombier if(chat)
14259a747e4fSDavid du Colombier print("9p1: fo %O\n", &fo);
14269a747e4fSDavid du Colombier
14279a747e4fSDavid du Colombier if(fo.err) {
14289a747e4fSDavid du Colombier strcpy(fo.ename, errstring[fo.err]);
14299a747e4fSDavid du Colombier if(CHAT(cp))
14309a747e4fSDavid du Colombier print(" error: %s\n", fo.ename);
14319a747e4fSDavid du Colombier fo.type = Terror9p1+1;
14329a747e4fSDavid du Colombier }
14339a747e4fSDavid du Colombier
14349a747e4fSDavid du Colombier n = convS2M9p1(&fo, outbuf);
14359a747e4fSDavid du Colombier if(n == 0) {
14369a747e4fSDavid du Colombier print("9p1: bad S2M conversion\n");
14379a747e4fSDavid du Colombier error9p1(chan, outbuf);
14389a747e4fSDavid du Colombier continue;
14399a747e4fSDavid du Colombier }
14409a747e4fSDavid du Colombier
14419a747e4fSDavid du Colombier cons.rate.count += n;
14429a747e4fSDavid du Colombier send(chan, outbuf, n);
14439a747e4fSDavid du Colombier }
14449a747e4fSDavid du Colombier }
1445