📄 ramfs.c
字号:
name = thdr.name; if(strcmp(name, ".")==0 || strcmp(name, "..")==0) return Ename; for(r=ram; r<&ram[nram]; r++) if(r->busy && parent==r->parent) if(strcmp((char*)name, r->name)==0) return Einuse; for(r=ram; r->busy; r++) if(r == &ram[Nram-1]) return "no free ram resources"; r->busy = 1; r->qid.path = ++path; r->qid.vers = 0; if(prm & DMDIR) r->qid.type |= QTDIR; r->parent = parent; free(r->name); r->name = estrdup(name); r->user = f->user; r->group = f->ram->group; r->muid = f->ram->muid; if(prm & DMDIR) prm = (prm&~0777) | (f->ram->perm&prm&0777); else prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666); r->perm = prm; r->ndata = 0; if(r-ram >= nram) nram = r - ram + 1; r->atime = time(0); r->mtime = r->atime; f->ram->mtime = r->atime; f->ram = r; rhdr.qid = r->qid; rhdr.iounit = messagesize-IOHDRSZ; f->open = 1; if(thdr.mode & ORCLOSE) f->rclose = 1; r->open++; return 0;}char*rread(Fid *f){ Ram *r; uchar *buf; long off; int n, m, cnt; if(f->ram->busy == 0) return Enotexist; n = 0; rhdr.count = 0; off = thdr.offset; buf = rdata; cnt = thdr.count; if(cnt > messagesize) /* shouldn't happen, anyway */ cnt = messagesize; if(f->ram->qid.type & QTDIR){ for(r=ram+1; off > 0; r++){ if(r->busy && r->parent==f->ram-ram) off -= ramstat(r, statbuf, sizeof statbuf); if(r == &ram[nram-1]) return 0; } for(; r<&ram[nram] && n < cnt; r++){ if(!r->busy || r->parent!=f->ram-ram) continue; m = ramstat(r, buf+n, cnt-n); if(m == 0) break; n += m; } rhdr.data = (char*)rdata; rhdr.count = n; return 0; } r = f->ram; if(off >= r->ndata) return 0; r->atime = time(0); n = cnt; if(off+n > r->ndata) n = r->ndata - off; rhdr.data = r->data+off; rhdr.count = n; return 0;}char*rwrite(Fid *f){ Ram *r; ulong off; int cnt; r = f->ram; if(r->busy == 0) return Enotexist; off = thdr.offset; if(r->perm & DMAPPEND) off = r->ndata; cnt = thdr.count; if(r->qid.type & QTDIR) return Eisdir; if(off+cnt >= Maxsize) /* sanity check */ return "write too big"; if(off+cnt > r->ndata) r->data = erealloc(r->data, off+cnt); if(off > r->ndata) memset(r->data+r->ndata, 0, off-r->ndata); if(off+cnt > r->ndata) r->ndata = off+cnt; memmove(r->data+off, thdr.data, cnt); r->qid.vers++; r->mtime = time(0); rhdr.count = cnt; return 0;}static intemptydir(Ram *dr){ long didx = dr - ram; Ram *r; for(r=ram; r<&ram[nram]; r++) if(r->busy && didx==r->parent) return 0; return 1;}char *realremove(Ram *r){ if(r->qid.type & QTDIR && !emptydir(r)) return Enotempty; r->ndata = 0; if(r->data) free(r->data); r->data = 0; r->parent = 0; memset(&r->qid, 0, sizeof r->qid); free(r->name); r->name = nil; r->busy = 0; return nil;}char *rclunk(Fid *f){ char *e = nil; if(f->open) f->ram->open--; if(f->rclose) e = realremove(f->ram); f->busy = 0; f->open = 0; f->ram = 0; return e;}char *rremove(Fid *f){ Ram *r; if(f->open) f->ram->open--; f->busy = 0; f->open = 0; r = f->ram; f->ram = 0; if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite)) return Eperm; ram[r->parent].mtime = time(0); return realremove(r);}char *rstat(Fid *f){ if(f->ram->busy == 0) return Enotexist; rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf); rhdr.stat = statbuf; return 0;}char *rwstat(Fid *f){ Ram *r, *s; Dir dir; if(f->ram->busy == 0) return Enotexist; convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf); r = f->ram; /* * To change length, must have write permission on file. */ if(dir.length!=~0 && dir.length!=r->ndata){ if(!perm(f, r, Pwrite)) return Eperm; } /* * To change name, must have write permission in parent * and name must be unique. */ if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){ if(!perm(f, &ram[r->parent], Pwrite)) return Eperm; for(s=ram; s<&ram[nram]; s++) if(s->busy && s->parent==r->parent) if(strcmp(dir.name, s->name)==0) return Eexist; } /* * To change mode, must be owner or group leader. * Because of lack of users file, leader=>group itself. */ if(dir.mode!=~0 && r->perm!=dir.mode){ if(strcmp(f->user, r->user) != 0) if(strcmp(f->user, r->group) != 0) return Enotowner; } /* * To change group, must be owner and member of new group, * or leader of current group and leader of new group. * Second case cannot happen, but we check anyway. */ if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){ if(strcmp(f->user, r->user) == 0) // if(strcmp(f->user, dir.gid) == 0) goto ok; if(strcmp(f->user, r->group) == 0) if(strcmp(f->user, dir.gid) == 0) goto ok; return Enotowner; ok:; } /* all ok; do it */ if(dir.mode != ~0){ dir.mode &= ~DMDIR; /* cannot change dir bit */ dir.mode |= r->perm&DMDIR; r->perm = dir.mode; } if(dir.name[0] != '\0'){ free(r->name); r->name = estrdup(dir.name); } if(dir.gid[0] != '\0') r->group = estrdup(dir.gid); if(dir.length!=~0 && dir.length!=r->ndata){ r->data = erealloc(r->data, dir.length); if(r->ndata < dir.length) memset(r->data+r->ndata, 0, dir.length-r->ndata); r->ndata = dir.length; } ram[r->parent].mtime = time(0); return 0;}uintramstat(Ram *r, uchar *buf, uint nbuf){ int n; Dir dir; dir.name = r->name; dir.qid = r->qid; dir.mode = r->perm; dir.length = r->ndata; dir.uid = r->user; dir.gid = r->group; dir.muid = r->muid; dir.atime = r->atime; dir.mtime = r->mtime; n = convD2M(&dir, buf, nbuf); if(n > 2) return n; return 0;}Fid *newfid(int fid){ Fid *f, *ff; ff = 0; for(f = fids; f; f = f->next) if(f->fid == fid) return f; else if(!ff && !f->busy) ff = f; if(ff){ ff->fid = fid; return ff; } f = emalloc(sizeof *f); f->ram = nil; f->fid = fid; f->next = fids; fids = f; return f;}voidio(void){ char *err, buf[40]; int n, pid, ctl; Fid *fid; pid = getpid(); if(private){ snprint(buf, sizeof buf, "/proc/%d/ctl", pid); ctl = open(buf, OWRITE); if(ctl < 0){ fprint(2, "can't protect ramfs\n"); }else{ fprint(ctl, "noswap\n"); fprint(ctl, "private\n"); close(ctl); } } for(;;){ /* * reading from a pipe or a network device * will give an error after a few eof reads. * however, we cannot tell the difference * between a zero-length read and an interrupt * on the processes writing to us, * so we wait for the error. */ n = read9pmsg(mfd[0], mdata, messagesize); if(n < 0){ rerrstr(buf, sizeof buf); if(buf[0]=='\0' || strstr(buf, "hungup")) exits(""); error("mount read"); } if(n == 0) continue; if(convM2S(mdata, n, &thdr) == 0) continue; if(debug) fprint(2, "ramfs %d:<-%F\n", pid, &thdr); if(thdr.type<0 || thdr.type>=nelem(fcalls) || !fcalls[thdr.type]) err = "bad fcall type"; else if(((fid=newfid(thdr.fid))==nil || !fid->ram) && needfid[thdr.type]) err = "fid not in use"; else err = (*fcalls[thdr.type])(fid); if(err){ rhdr.type = Rerror; rhdr.ename = err; }else{ rhdr.type = thdr.type + 1; rhdr.fid = thdr.fid; } rhdr.tag = thdr.tag; if(debug) fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/ n = convS2M(&rhdr, mdata, messagesize); if(n == 0) error("convS2M error on write"); if(write(mfd[1], mdata, n) != n) error("mount write"); }}intperm(Fid *f, Ram *r, int p){ if((p*Pother) & r->perm) return 1; if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm)) return 1; if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm)) return 1; return 0;}voiderror(char *s){ fprint(2, "%s: %s: %r\n", argv0, s); exits(s);}void *emalloc(ulong n){ void *p; p = malloc(n); if(!p) error("out of memory"); memset(p, 0, n); return p;}void *erealloc(void *p, ulong n){ p = realloc(p, n); if(!p) error("out of memory"); return p;}char *estrdup(char *q){ char *p; int n; n = strlen(q)+1; p = malloc(n); if(!p) error("out of memory"); memmove(p, q, n); return p;}voidusage(void){ fprint(2, "usage: %s [-Dips] [-m mountpoint] [-S srvname]\n", argv0); exits("usage");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -