9 char Ebadoff[] = "bad file offset or count";
10 char Eexist[] = "file already exists";
11 char Enomem[] = "no memory";
12 char Eperm[] = "permission denied";
13 char Enotowner[] = "not owner";
14 char Elocked[] = "file locked";
23 #define MAXFSIZE ((0x7fffffffll/sizeof(Ram*))*ESIZE)
25 typedef struct Ram Ram;
48 rammoved(void*, void *to)
50 Ram **link, **elink, *x = to;
57 for(elink = link + (x->size / sizeof(Ram*)); link < elink; link++)
58 if((x = *link) != nil)
69 .maxsize= 800*1024*1024,
80 accessfile(File *f, int a)
99 off = r->ifcall.offset;
100 count = r->ifcall.count;
102 if(count == 0 || off >= f->length || f->aux == nil){
118 p = (char*)r->ofcall.data;
124 if(i < (x->size / sizeof(Ram*)))
128 if(x != nil && o < x->size){
132 memmove(p, (char*)&x[1] + o, n);
143 accessfile(f, AREAD);
145 r->ofcall.count = p - (char*)r->ofcall.data;
159 off = r->ifcall.offset;
160 count = r->ifcall.count;
162 if(f->mode & DMAPPEND)
177 n = ((top + ESIZE-1)/ESIZE) * sizeof(Ram*);
179 if(x == nil || x->size < n){
180 x = poolrealloc(&rampool, x, sizeof(Ram) + n);
185 link = (Ram**)&f->aux;
187 memset(x, 0, sizeof(Ram));
191 } else if(x != *link)
193 memset((char*)&x[1] + x->size, 0, n - x->size);
197 p = (char*)r->ifcall.data;
206 x = ((Ram*)f->aux)->ent[i];
207 if(x == nil || x->size < o+n){
208 x = poolrealloc(&rampool, x, sizeof(Ram) + o+n);
213 link = &((Ram*)f->aux)->ent[i];
215 memset(x, 0, sizeof(Ram));
219 memset((char*)&x[1] + x->size, 0, o - x->size);
225 memmove((char*)&x[1] + o, p, n);
233 accessfile(f, AWRITE);
235 r->ofcall.count = p - (char*)r->ifcall.data;
240 truncfile(File *f, vlong l)
247 n = x->size / sizeof(Ram*);
251 if(o != 0 && x->ent[i] != nil){
252 x->ent[i]->size = o * sizeof(Ram*);
256 if(x->ent[i] != nil){
257 poolfree(&rampool, x->ent[i]);
264 poolfree(&rampool, (Ram*)f->aux);
281 * To change length, must have write permission on file.
283 if(r->d.length != ~0 && r->d.length != f->length){
284 if(r->d.length > MAXFSIZE){
288 if(!hasperm(f, u, AWRITE) || (f->mode & DMDIR) != 0)
293 * To change name, must have write permission in parent.
295 if(r->d.name[0] != '\0' && strcmp(r->d.name, f->name) != 0){
296 if((w = f->parent) == nil)
299 if(!hasperm(w, u, AWRITE)){
303 if((w = walkfile(w, r->d.name)) != nil){
311 * To change mode, must be owner or group leader.
312 * Because of lack of users file, leader=>group itself.
314 if(r->d.mode != ~0 && f->mode != r->d.mode){
315 if(strcmp(u, f->uid) != 0)
316 if(strcmp(u, f->gid) != 0){
317 respond(r, Enotowner);
323 * To change group, must be owner and member of new group,
324 * or leader of current group and leader of new group.
325 * Second case cannot happen, but we check anyway.
327 while(r->d.gid[0] != '\0' && strcmp(f->gid, r->d.gid) != 0){
328 if(strcmp(u, f->uid) == 0)
330 if(strcmp(u, f->gid) == 0)
331 if(strcmp(u, r->d.gid) == 0)
333 respond(r, Enotowner);
339 f->qid.type = f->mode >> 24;
341 if(r->d.name[0] != '\0'){
343 f->name = estrdup9p(r->d.name);
345 if(r->d.length != ~0 && r->d.length != f->length)
346 truncfile(f, r->d.length);
348 accessfile(f, AWRITE);
349 if(r->d.mtime != ~0){
350 f->mtime = r->d.mtime;
369 p = (p & ~0777) | ((p & f->mode) & 0777);
371 p = (p & ~0666) | ((p & f->mode) & 0666);
372 if((f = createfile(f, r->ifcall.name, r->fid->uid, p, nil)) == nil){
376 f->atime = f->mtime = time(0);
379 r->ofcall.qid = f->qid;
389 if((f->mode & DMEXCL) != 0){
390 if(f->ref > 2 && (long)((ulong)time(0)-(ulong)f->atime) < 300){
395 if((f->mode & DMAPPEND) == 0 && (r->ifcall.mode & OTRUNC) != 0){
397 accessfile(f, AWRITE);
403 fsdestroyfid(Fid *fid)
408 if(fid->omode != -1 && (fid->omode & ORCLOSE) != 0 && f != nil && f->parent != nil)
413 fsdestroyfile(File *f)
425 snprint(buf, sizeof buf, "/proc/%d/ctl", getpid());
426 if((ctl = open(buf, OWRITE)) < 0)
427 sysfatal("can't protect memory: %r");
428 fprint(ctl, "noswap\n");
429 fprint(ctl, "private\n");
440 .destroyfid= fsdestroyfid,
448 fprint(2, "usage: %s [-Dipsubac] [-m mountpoint] [-S srvname]\n", argv0);
453 main(int argc, char **argv)
460 fs.tree = alloctree(nil, nil, DMDIR|0777, fsdestroyfile);
461 q = fs.tree->root->qid;
473 srvname = EARGF(usage());
477 mtpt = EARGF(usage());
488 rampool.maxsize = (uintptr)~0;
491 mountflags |= MBEFORE;
494 mountflags |= MCREATE;
497 mountflags |= MAFTER;
512 if(srvname == nil && mtpt == nil)
513 sysfatal("must specify -S, or -m option");
516 mountflags = MREPL | MCREATE;
517 postmountsrv(&fs, srvname, mtpt, mountflags);