📄 nfs.c
字号:
return 0; } if(readplus == 0){ rerrstr(e, sizeof e); if(strstr(e, "procedure unavailable") || strstr(e, "not supported")) readplus = -1; } if(readplus == 0) fprint(2, "readdirplus: %r\n"); } if(readplus == 1) return -1; memset(&tx, 0, sizeof tx); nfs3Call(a, &tx.call, Nfs3CallTReadDir); tx.handle = *h; tx.count = count; tx.cookie = cookie; memset(&rx, 0, sizeof rx); nfs3Call(a, &rx.call, Nfs3CallRReadDir); if(sunClientRpc(nfscli, tag, &tx.call, &rx.call, pfreeme) < 0) return -1; if(rx.status != Nfs3Ok){ free(*pfreeme); *pfreeme = 0; nfs3Errstr(rx.status); return -1; } /* readplus failed but read succeeded */ readplus = -1; *unpack = nfs3EntryUnpack; *pcount = rx.count; *pp = rx.data; return 0;}/* * name <-> int translation */typedef struct Map Map;typedef struct User User;typedef struct Group Group;Map *map;Map emptymap;struct User{ char *name; uint uid; uint gid; uint g[16]; uint ng; uchar *auth; int nauth;};struct Group{ char *name; /* same pos as in User struct */ uint gid; /* same pos as in User struct */};struct Map{ int nuser; int ngroup; User *user; User **ubyname; User **ubyid; Group *group; Group **gbyname; Group **gbyid;};User*finduser(User **u, int nu, char *s){ int lo, hi, mid, n; hi = nu; lo = 0; while(hi > lo){ mid = (lo+hi)/2; n = strcmp(u[mid]->name, s); if(n == 0) return u[mid]; if(n < 0) lo = mid+1; else hi = mid; } return nil;}intstrtoid(User **u, int nu, char *s, u32int *id){ u32int x; char *p; User *uu; x = strtoul(s, &p, 10); if(*s != 0 && *p == 0){ *id = x; return 0; } uu = finduser(u, nu, s); if(uu == nil) return -1; *id = uu->uid; return 0;}char*idtostr(User **u, int nu, u32int id){ char buf[32]; int lo, hi, mid; hi = nu; lo = 0; while(hi > lo){ mid = (lo+hi)/2; if(u[mid]->uid == id) return estrdup9p(u[mid]->name); if(u[mid]->uid < id) lo = mid+1; else hi = mid; } snprint(buf, sizeof buf, "%ud", id); return estrdup9p(buf);} char*uidtostr(u32int uid){ return idtostr(map->ubyid, map->nuser, uid);}char*gidtostr(u32int gid){ return idtostr((User**)map->gbyid, map->ngroup, gid);}intstrtouid(char *s, u32int *id){ return strtoid(map->ubyname, map->nuser, s, id);}intstrtogid(char *s, u32int *id){ return strtoid((User**)map->gbyid, map->ngroup, s, id);}intidcmp(const void *va, const void *vb){ User **a, **b; a = (User**)va; b = (User**)vb; return (*a)->uid - (*b)->uid;}intnamecmp(const void *va, const void *vb){ User **a, **b; a = (User**)va; b = (User**)vb; return strcmp((*a)->name, (*b)->name);}voidclosemap(Map *m){ int i; for(i=0; i<m->nuser; i++){ free(m->user[i].name); free(m->user[i].auth); } for(i=0; i<m->ngroup; i++) free(m->group[i].name); free(m->user); free(m->group); free(m->ubyid); free(m->ubyname); free(m->gbyid); free(m->gbyname); free(m);}Map*readmap(char *passwd, char *group){ char *s, *f[10], *p, *nextp, *name; uchar *q, *eq; int i, n, nf, line, uid, gid; Biobuf *b; Map *m; User *u; Group *g; SunAuthUnix au; m = emalloc(sizeof(Map)); if((b = Bopen(passwd, OREAD)) == nil){ free(m); return nil; } line = 0; for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){ line++; if(s[0] == '#') continue; nf = getfields(s, f, nelem(f), 0, ":"); if(nf < 4) continue; name = f[0]; uid = strtol(f[2], &p, 10); if(f[2][0] == 0 || *p != 0){ fprint(2, "%s:%d: non-numeric id in third field\n", passwd, line); continue; } gid = strtol(f[3], &p, 10); if(f[3][0] == 0 || *p != 0){ fprint(2, "%s:%d: non-numeric id in fourth field\n", passwd, line); continue; } if(m->nuser%32 == 0) m->user = erealloc(m->user, (m->nuser+32)*sizeof(m->user[0])); u = &m->user[m->nuser++]; u->name = estrdup9p(name); u->uid = uid; u->gid = gid; u->ng = 0; u->auth = 0; u->nauth = 0; } Bterm(b); m->ubyname = emalloc(m->nuser*sizeof(User*)); m->ubyid = emalloc(m->nuser*sizeof(User*)); for(i=0; i<m->nuser; i++){ m->ubyname[i] = &m->user[i]; m->ubyid[i] = &m->user[i]; } qsort(m->ubyname, m->nuser, sizeof(m->ubyname[0]), namecmp); qsort(m->ubyid, m->nuser, sizeof(m->ubyid[0]), idcmp); if((b = Bopen(group, OREAD)) == nil){ closemap(m); return nil; } line = 0; for(; (s = Brdstr(b, '\n', 1)) != nil; free(s)){ line++; if(s[0] == '#') continue; nf = getfields(s, f, nelem(f), 0, ":"); if(nf < 4) continue; name = f[0]; gid = strtol(f[2], &p, 10); if(f[2][0] == 0 || *p != 0){ fprint(2, "%s:%d: non-numeric id in third field\n", group, line); continue; } if(m->ngroup%32 == 0) m->group = erealloc(m->group, (m->ngroup+32)*sizeof(m->group[0])); g = &m->group[m->ngroup++]; g->name = estrdup9p(name); g->gid = gid; for(p=f[3]; *p; p=nextp){ if((nextp = strchr(p, ',')) != nil) *nextp++ = 0; else nextp = p+strlen(p); u = finduser(m->ubyname, m->nuser, p); if(u == nil){ if(verbose) fprint(2, "%s:%d: unknown user %s\n", group, line, p); continue; } if(u->ng >= nelem(u->g)){ fprint(2, "%s:%d: user %s is in too many groups; ignoring %s\n", group, line, p, name); continue; } u->g[u->ng++] = gid; } } Bterm(b); m->gbyname = emalloc(m->ngroup*sizeof(Group*)); m->gbyid = emalloc(m->ngroup*sizeof(Group*)); for(i=0; i<m->ngroup; i++){ m->gbyname[i] = &m->group[i]; m->gbyid[i] = &m->group[i]; } qsort(m->gbyname, m->ngroup, sizeof(m->gbyname[0]), namecmp); qsort(m->gbyid, m->ngroup, sizeof(m->gbyid[0]), idcmp); for(i=0; i<m->nuser; i++){ au.stamp = 0; au.sysname = sys; au.uid = m->user[i].uid; au.gid = m->user[i].gid; memmove(au.g, m->user[i].g, sizeof au.g); au.ng = m->user[i].ng; n = sunAuthUnixSize(&au); q = emalloc(n); eq = q+n; m->user[i].auth = q; m->user[i].nauth = n; if(sunAuthUnixPack(q, eq, &q, &au) < 0 || q != eq){ fprint(2, "sunAuthUnixPack failed for %s\n", m->user[i].name); free(m->user[i].auth); m->user[i].auth = 0; m->user[i].nauth = 0; } } return m;}Auth*mkauth(char *user){ Auth *a; uchar *p; int n; SunAuthUnix au; User *u; u = finduser(map->ubyname, map->nuser, user); if(u == nil || u->nauth == 0){ /* nobody */ au.stamp = 0; au.uid = -1; au.gid = -1; au.ng = 0; au.sysname = sys; n = sunAuthUnixSize(&au); a = emalloc(sizeof(Auth)+n); a->data = (uchar*)&a[1]; a->ndata = n; if(sunAuthUnixPack(a->data, a->data+a->ndata, &p, &au) < 0 || p != a->data+a->ndata){ free(a); return nil; } a->ref = 1;if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data); return a; } a = emalloc(sizeof(Auth)+u->nauth); a->data = (uchar*)&a[1]; a->ndata = u->nauth; memmove(a->data, u->auth, a->ndata); a->ref = 1;if(verbose)print("creds for %s: %.*H\n", user, a->ndata, a->data); return a;}voidfreeauth(Auth *a){ if(--a->ref > 0) return; free(a);}/* * 9P server */voidresponderrstr(Req *r){ char e[ERRMAX]; rerrstr(e, sizeof e); respond(r, e);}voidfsdestroyfid(Fid *fid){ FidAux *aux; aux = fid->aux; if(aux == nil) return; freeauth(aux->auth); free(aux->name); free(aux);}voidattrToQid(Nfs3Attr *attr, Qid *qid){ qid->path = attr->fileid; qid->vers = attr->mtime.sec; qid->type = 0; if(attr->type == Nfs3FileDir) qid->type |= QTDIR;}voidattrToDir(Nfs3Attr *attr, Dir *d){ d->mode = attr->mode & 0777; if(attr->type == Nfs3FileDir) d->mode |= DMDIR; d->uid = uidtostr(attr->uid); d->gid = gidtostr(attr->gid); d->length = attr->size; attrToQid(attr, &d->qid); d->mtime = attr->mtime.sec; d->atime = attr->atime.sec; d->muid = nil;}voidfsattach(Req *r){ char *path; Auth *auth; FidAux *aux; Nfs3Attr attr; Nfs3Handle h; path = r->ifcall.aname; if(path==nil || path[0]==0) path = defaultpath; auth = mkauth(r->ifcall.uname); if(mountMnt(auth, r->tag, path, &h) < 0 || nfsGetattr(auth, r->tag, &h, &attr) < 0){ freeauth(auth); responderrstr(r); return; } aux = emalloc(sizeof(FidAux)); aux->auth = auth; aux->handle = h; aux->cookie = 0; aux->name = nil; memset(&aux->parent, 0, sizeof aux->parent); r->fid->aux = aux; attrToQid(&attr, &r->fid->qid); r->ofcall.qid = r->fid->qid; respond(r, nil);}voidfsopen(Req *r){ FidAux *aux; Nfs3Attr attr; Nfs3SetAttr sa; u1int have; ulong a, b; aux = r->fid->aux; a = 0; switch(r->ifcall.mode&OMASK){ case OREAD: a = 0x0001; break; case OWRITE: a = 0x0004; break; case ORDWR: a = 0x0001|0x0004; break; case OEXEC: a = 0x20; break; } if(r->ifcall.mode&OTRUNC) a |= 0x0004; if(nfsAccess(aux->auth, r->tag, &aux->handle, a, &b, &have, &attr) < 0 || (!have && nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0)){ Error: responderrstr(r); return; } if(a != b){ respond(r, "permission denied"); return; } if(r->ifcall.mode&OTRUNC){ memset(&sa, 0, sizeof sa); sa.setSize = 1; if(nfsSetattr(aux->auth, r->tag, &aux->handle, &sa) < 0) goto Error; } attrToQid(&attr, &r->fid->qid); r->ofcall.qid = r->fid->qid; respond(r, nil);}voidfscreate(Req *r){ FidAux *aux; u1int have; Nfs3Attr attr; Nfs3Handle h; ulong mode; uint gid; int (*mk)(Auth*, ulong, Nfs3Handle*, char*, Nfs3Handle*, ulong, uint, u1int*, Nfs3Attr*); aux = r->fid->aux; /* * Plan 9 has no umask, so let's use the * parent directory bits like Plan 9 does. * What the heck, let's inherit the group too. * (Unix will let us set the group to anything * since we're the owner!) */ if(nfsGetattr(aux->auth, r->tag, &aux->handle, &attr) < 0){ responderrstr(r); return; } mode = r->ifcall.perm&0777; if(r->ifcall.perm&DMDIR) mode &= (attr.mode&0666) | ~0666; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -