Spfcall * sp_open(Spreq *req, Spfcall *tc) { Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (fid->omode != (u16)~0) { sp_werror(Ebadusefid, EIO); goto done; } if (fid->type&Qtdir && tc->mode != Oread) { sp_werror(Eperm, EISDIR); goto done; } rc = (*conn->srv->open)(fid, tc->mode); fid->omode = tc->mode; done: // sp_fid_decref(fid); return rc; }
Spfcall * sp_create(Spreq *req, Spfcall *tc) { Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (fid->omode != (u16)~0) { sp_werror(Ebadusefid, EIO); goto done; } if (!fid->type&Qtdir) { sp_werror(Enotdir, ENOTDIR); goto done; } if (tc->perm&Dmdir && tc->mode!=Oread) { sp_werror(Eperm, EPERM); goto done; } if (tc->perm&(Dmnamedpipe|Dmsymlink|Dmlink|Dmdevice|Dmsocket) && !fid->conn->dotu) { sp_werror(Eperm, ENOTSUP); goto done; } rc = (*conn->srv->create)(fid, &tc->name, tc->perm, tc->mode, &tc->extension); if (rc && rc->type == Rcreate) { fid->omode = tc->mode; fid->type = rc->qid.type; } done: // sp_fid_decref(fid); return rc; }
Spfcall * sp_write(Spreq *req, Spfcall *tc) { int n; Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (fid->type&Qtauth) { if (conn->srv->auth) { n = conn->srv->auth->write(fid, tc->offset, tc->count, tc->data); if (n >= 0) rc = sp_create_rwrite(n); goto done; } else { sp_werror(Ebadusefid, EIO); goto done; } } if (fid->omode==(u16)~0 || fid->type&Qtdir || (fid->omode&3)==Oread) { sp_werror(Ebadusefid, EIO); goto done; } if (tc->count+IOHDRSZ > conn->msize) { sp_werror(Etoolarge, EIO); goto done; } rc = (*conn->srv->write)(fid, tc->offset, tc->count, tc->data, req); done: return rc; }
Spfcall * sp_clunk(Spreq *req, Spfcall *tc) { int n; Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (fid->type&Qtauth) { if (conn->srv->auth) { n = conn->srv->auth->clunk(fid); if (n) rc = sp_create_rclunk(); } else sp_werror(Ebadusefid, EIO); goto done; } if (fid->omode!=(u16)~0 && fid->omode==Orclose) { rc = (*conn->srv->remove)(fid); if (rc->type == Rerror) goto done; free(rc); rc = sp_create_rclunk(); } else rc = (*conn->srv->clunk)(fid); if (rc && rc->type == Rclunk) sp_fid_decref(fid); done: return rc; }
Spfcall * sp_stat(Spreq *req, Spfcall *tc) { Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; rc = (*conn->srv->stat)(fid); done: // sp_fid_decref(fid); return rc; }
Spfcall * sp_wstat(Spreq *req, Spfcall *tc) { Spconn *conn; Spfid *fid; Spfcall *rc; Spstat *stat; rc = NULL; conn = req->conn; stat = &tc->stat; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (stat->type != (u16)~0 || stat->dev != (u32)~0 || stat->qid.version != (u32)~0 || stat->qid.path != (u64)~0 ) { sp_werror(Eperm, EPERM); goto done; } if ((fid->type&Qtdir && !stat->mode&Dmdir) || (!fid->type&Qtdir&&stat->mode&Dmdir)) { sp_werror(Edirchange, EPERM); goto done; } rc = (*conn->srv->wstat)(fid, &tc->stat); done: // sp_fid_decref(fid); return rc; }
Spfcall * sp_remove(Spreq *req, Spfcall *tc) { Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; rc = (*conn->srv->remove)(fid); if (rc && rc->type == Rremove) sp_fid_decref(fid); done: return rc; }
Spfcall * sp_auth(Spreq *req, Spfcall *tc) { int n; char *uname, *aname; Spconn *conn; Spsrv *srv; Spfid *afid; Spfcall *rc; Spuser *user; Spqid aqid; rc = NULL; aname = NULL; conn = req->conn; srv = conn->srv; afid = sp_fid_find(conn, tc->afid); if (afid) { sp_werror(Einuse, EIO); goto done; } afid = sp_fid_create(conn, tc->afid, NULL); if (!afid) goto done; else sp_fid_incref(afid); if (tc->uname.len && tc->n_uname==~0) { uname = sp_strdup(&tc->uname); if (!uname) goto done; user = (*srv->upool->uname2user)(srv->upool, uname); free(uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } tc->n_uname = user->uid; } else { user = (*srv->upool->uid2user)(srv->upool, tc->n_uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } } if (tc->aname.len) { aname = sp_strdup(&tc->aname); if (!aname) goto done; } else aname = NULL; afid->user = user; afid->type = Qtauth; if (srv->auth && srv->auth->startauth) n = (*srv->auth->startauth)(afid, aname, &aqid); else n = 0; if (n) { assert((aqid.type & Qtauth) != 0); rc = sp_create_rauth(&aqid); } else sp_werror(Enoauth, EIO); done: free(aname); if (!rc) sp_fid_decref(afid); return rc; }
Spfcall * sp_read(Spreq *req, Spfcall *tc) { int n; Spconn *conn; Spfid *fid; Spfcall *rc; rc = NULL; conn = req->conn; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (tc->count+IOHDRSZ > conn->msize) { sp_werror(Etoolarge, EIO); goto done; } if (fid->type&Qtauth) { if (conn->srv->auth) { rc = sp_alloc_rread(tc->count); if (!rc) goto done; n = conn->srv->auth->read(fid, tc->offset, tc->count, rc->data); if (n >= 0) sp_set_rread_count(rc, n); else { free(rc); rc = NULL; } } else sp_werror(Ebadusefid, EIO); goto done; } if (fid->omode==(u16)~0 || (fid->omode&3)==Owrite) { sp_werror(Ebadusefid, EIO); goto done; } if (fid->type&Qtdir && tc->offset != fid->diroffset) { sp_werror(Ebadoffset, EIO); goto done; } rc = (*conn->srv->read)(fid, tc->offset, tc->count, req); /* if (rc && rc->id==Rread && fid->type&Qtdir) { fid->diroffset = tc->offset + rc->count; } */ done: return rc; }
Spfcall * sp_walk(Spreq *req, Spfcall *tc) { int i; Spconn *conn; Spfid *fid, *newfid; Spfcall *rc; Spqid wqids[MAXWELEM]; rc = NULL; conn = req->conn; newfid = NULL; fid = sp_fid_find(conn, tc->fid); if (!fid) { sp_werror(Eunknownfid, EIO); goto done; } else sp_fid_incref(fid); req->fid = fid; if (!fid->type&Qtdir) { sp_werror(Enotdir, ENOTDIR); goto done; } if (fid->omode != (u16) ~0) { sp_werror(Ebadusefid, EIO); goto done; } if (tc->nwname > MAXWELEM) { sp_werror(Etoomanywnames, EIO); goto done; } if (tc->fid != tc->newfid) { newfid = sp_fid_find(conn, tc->newfid); if (newfid) { sp_werror(Einuse, EIO); goto done; } newfid = sp_fid_create(conn, tc->newfid, NULL); if (!newfid) goto done; if (!(*conn->srv->clone)(fid, newfid)) goto done; sp_user_incref(fid->user); newfid->user = fid->user; newfid->type = fid->type; } else newfid = fid; sp_fid_incref(newfid); for(i = 0; i < tc->nwname;) { if (!(*conn->srv->walk)(newfid, &tc->wnames[i], &wqids[i])) break; newfid->type = wqids[i].type; i++; if (i<(tc->nwname) && !newfid->type&Qtdir) break; } if (i==0 && tc->nwname!=0) goto done; sp_werror(NULL, 0); if (tc->fid != tc->newfid) sp_fid_incref(newfid); rc = sp_create_rwalk(i, wqids); done: sp_fid_decref(newfid); return rc; }
Spfcall * sp_attach(Spreq *req, Spfcall *tc) { char *uname, *aname; Spconn *conn; Spsrv *srv; Spfid *fid, *afid; Spfcall *rc; Spuser *user; rc = NULL; aname = NULL; conn = req->conn; srv = conn->srv; afid = NULL; fid = sp_fid_find(conn, tc->fid); if (fid) { sp_werror(Einuse, EIO); goto done; } fid = sp_fid_create(conn, tc->fid, NULL); if (!fid) goto done; else sp_fid_incref(fid); req->fid = fid; afid = sp_fid_find(conn, tc->afid); if (!afid) { if (tc->afid!=NOFID) { sp_werror(Eunknownfid, EIO); goto done; } if (!afid->type&Qtauth) { sp_werror(Ebadusefid, EIO); goto done; } } else sp_fid_incref(afid); if (tc->uname.len && tc->n_uname==~0) { uname = sp_strdup(&tc->uname); if (!uname) goto done; user = srv->upool->uname2user(srv->upool, uname); free(uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } tc->n_uname = user->uid; } else { user = srv->upool->uid2user(srv->upool, tc->n_uname); if (!user) { sp_werror(Eunknownuser, EIO); goto done; } } fid->user = user; if (tc->aname.len) { aname = sp_strdup(&tc->aname); if (!aname) goto done; } else aname = NULL; if (conn->srv->auth && conn->srv->auth->checkauth && !(*conn->srv->auth->checkauth)(fid, afid, aname)) goto done; rc = (*conn->srv->attach)(fid, afid, &tc->uname, &tc->aname, tc->n_uname); done: free(aname); sp_fid_decref(afid); return rc; }
static int npfs_create_special(Spfid *fid, char *path, u32 perm, Spstr *extension) { int nfid, err; int nmode, major, minor; char ctype; mode_t umode; Spfid *ofid; Fid *f, *of; char *ext; f = fid->aux; if (!perm&Dmnamedpipe && !extension->len) { sp_werror(Enoextension, EIO); return -1; } umode = np2umode(perm, extension, fid->conn->dotu); ext = sp_strdup(extension); if (perm & Dmsymlink) { if (symlink(ext, path) < 0) { err = errno; fprintf(stderr, "symlink %s %s %d\n", ext, path, err); create_rerror(err); goto error; } } else if (perm & Dmlink) { if (sscanf(ext, "%d", &nfid) == 0) { sp_werror(Eformat, EIO); goto error; } ofid = sp_fid_find(fid->conn, nfid); if (!ofid) { sp_werror(Eunknownfid, EIO); goto error; } of = ofid->aux; if (link(of->path, path) < 0) { create_rerror(errno); goto error; } } else if (perm & Dmdevice) { if (sscanf(ext, "%c %u %u", &ctype, &major, &minor) != 3) { sp_werror(Eformat, EIO); goto error; } nmode = 0; switch (ctype) { case 'c': nmode = S_IFCHR; break; case 'b': nmode = S_IFBLK; break; default: sp_werror(Eformat, EIO); goto error; } nmode |= perm & 0777; if (mknod(path, nmode, makedev(major, minor)) < 0) { create_rerror(errno); goto error; } } else if (perm & Dmnamedpipe) { if (mknod(path, S_IFIFO | (umode&0777), 0) < 0) { create_rerror(errno); goto error; } } f->omode = 0; if (!perm&Dmsymlink && chmod(path, umode)<0) { create_rerror(errno); goto error; } free(ext); return 0; error: free(ext); return -1; }