📄 sysfile.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "../port/error.h"/* * The sys*() routines needn't poperror() as they return directly to syscall(). */intgrowfd(Fgrp *f, int fd) /* fd is always >= 0 */{ Chan **newfd, **oldfd; if(fd < f->nfd) return 0; if(fd >= f->nfd+DELTAFD) return -1; /* out of range */ if(fd % 100 == 0) pprint("warning: process exceeds %d file descriptors\n", fd); /* * Unbounded allocation is unwise; besides, there are only 16 bits * of fid in 9P */ if(f->nfd >= 5000){ Exhausted: exhausted("file descriptors"); return -1; } newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*)); if(newfd == 0) goto Exhausted; oldfd = f->fd; memmove(newfd, oldfd, f->nfd*sizeof(Chan*)); f->fd = newfd; free(oldfd); f->nfd += DELTAFD; if(fd > f->maxfd) f->maxfd = fd; return 1;}intnewfd(Chan *c){ int fd; Fgrp *f; f = up->fgrp; lock(f); for(fd=0; fd<f->nfd; fd++) if(f->fd[fd] == 0) break; if(fd >= f->nfd && growfd(f, fd) < 0){ unlock(f); return -1; } if(fd > f->maxfd) f->maxfd = fd; f->fd[fd] = c; unlock(f); return fd;}Chan*fdtochan(int fd, int mode, int chkmnt, int iref){ Chan *c; Fgrp *f; c = 0; f = up->fgrp; lock(f); if(fd<0 || f->nfd<=fd || (c = f->fd[fd])==0) { unlock(f); error(Ebadfd); } if(iref) incref(c); unlock(f); if(chkmnt && (c->flag&CMSG)) { if(iref) cclose(c); error(Ebadusefd); } if(mode<0 || c->mode==ORDWR) return c; if((mode&OTRUNC) && c->mode==OREAD) { if(iref) cclose(c); error(Ebadusefd); } if((mode&~OTRUNC) != c->mode) { if(iref) cclose(c); error(Ebadusefd); } return c;}intopenmode(ulong o){ o &= ~(OTRUNC|OCEXEC|ORCLOSE); if(o > OEXEC) error(Ebadarg); if(o == OEXEC) return OREAD; return o;}longsysfd2path(ulong *arg){ Chan *c; validaddr(arg[1], arg[2], 1); c = fdtochan(arg[0], -1, 0, 1); if(c->name == nil) snprint((char*)arg[1], arg[2], "<null>"); else snprint((char*)arg[1], arg[2], "%s", c->name->s); cclose(c); return 0;}longsyspipe(ulong *arg){ int fd[2]; Chan *c[2]; Dev *d; Fgrp *f = up->fgrp; validaddr(arg[0], 2*BY2WD, 1); evenaddr(arg[0]); d = devtab[devno('|', 0)]; c[0] = namec("#|", Atodir, 0, 0); c[1] = 0; fd[0] = -1; fd[1] = -1; if(waserror()){ cclose(c[0]); if(c[1]) cclose(c[1]); if(fd[0] >= 0) f->fd[fd[0]]=0; if(fd[1] >= 0) f->fd[fd[1]]=0; nexterror(); } c[1] = cclone(c[0], 0); if(walk(&c[0], "data", 1) < 0) error(Egreg); if(walk(&c[1], "data1", 1) < 0) error(Egreg); c[0] = d->open(c[0], ORDWR); c[1] = d->open(c[1], ORDWR); fd[0] = newfd(c[0]); fd[1] = newfd(c[1]); if(fd[0] < 0 || fd[1] < 0) error(Enofd); ((long*)arg[0])[0] = fd[0]; ((long*)arg[0])[1] = fd[1]; poperror(); return 0;}longsysdup(ulong *arg){ int fd; Chan *c, *oc; Fgrp *f = up->fgrp; /* * Close after dup'ing, so date > #d/1 works */ c = fdtochan(arg[0], -1, 0, 1); fd = arg[1]; if(fd != -1){ lock(f); if(fd<0 || growfd(f, fd)<0) { unlock(f); cclose(c); error(Ebadfd); } if(fd > f->maxfd) f->maxfd = fd; oc = f->fd[fd]; f->fd[fd] = c; unlock(f); if(oc) cclose(oc); }else{ if(waserror()) { cclose(c); nexterror(); } fd = newfd(c); if(fd < 0) error(Enofd); poperror(); } return fd;}longsysopen(ulong *arg){ int fd; Chan *c = 0; openmode(arg[1]); /* error check only */ if(waserror()){ if(c) cclose(c); nexterror(); } validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aopen, arg[1], 0); fd = newfd(c); if(fd < 0) error(Enofd); poperror(); return fd;}voidfdclose(int fd, int flag){ int i; Chan *c; Fgrp *f = up->fgrp; lock(f); c = f->fd[fd]; if(c == 0){ /* can happen for users with shared fd tables */ unlock(f); return; } if(flag){ if(c==0 || !(c->flag&flag)){ unlock(f); return; } } f->fd[fd] = 0; if(fd == f->maxfd) for(i=fd; --i>=0 && f->fd[i]==0; ) f->maxfd = i; unlock(f); cclose(c);}longsysclose(ulong *arg){ fdtochan(arg[0], -1, 0, 0); fdclose(arg[0], 0); return 0;}longunionread(Chan *c, void *va, long n){ int i; long nr; Chan *nc; Mhead *m; Mount *mount; m = c->mh; rlock(&m->lock); mount = m->mount; for(i = 0; mount != nil && i < c->uri; i++) mount = mount->next; while(mount != nil) { if(waserror()) { runlock(&m->lock); nexterror(); } if(mount->to == nil) goto next; nc = cclone(mount->to, 0); poperror(); /* Error causes component of union to be skipped */ if(waserror()) { cclose(nc); goto next; } nc = devtab[nc->type]->open(nc, OREAD); nc->offset = c->offset; nr = devtab[nc->type]->read(nc, va, n, nc->offset); /* devdirread e.g. changes it */ c->offset = nc->offset; poperror(); cclose(nc); if(nr > 0) { runlock(&m->lock); return nr; } /* Advance to next element */ next: c->uri++; mount = mount->next; if(mount == nil) break; c->offset = 0; } runlock(&m->lock); return 0;}longsysread9p(ulong *arg){ int dir; long n; Chan *c; validaddr(arg[1], arg[2], 1); c = fdtochan(arg[0], OREAD, 1, 1); if(waserror()) { cclose(c); nexterror(); } n = arg[2]; dir = c->qid.path&CHDIR; if(dir) { n -= n%DIRLEN; if(c->offset%DIRLEN || n==0) error(Etoosmall); } if(dir && c->mh) n = unionread(c, (void*)arg[1], n); else if(devtab[c->type]->dc != L'M') n = devtab[c->type]->read(c, (void*)arg[1], n, c->offset); else n = mntread9p(c, (void*)arg[1], n, c->offset); lock(c); c->offset += n; unlock(c); poperror(); cclose(c); return n;}longsysread(ulong *arg){ int dir; long n; Chan *c; n = arg[2]; validaddr(arg[1], n, 1); c = fdtochan(arg[0], OREAD, 1, 1); if(waserror()) { cclose(c); nexterror(); } dir = c->qid.path&CHDIR; if(dir) { n -= n%DIRLEN; if(c->offset%DIRLEN || n==0) error(Etoosmall); } if(dir && c->mh) n = unionread(c, (void*)arg[1], n); else n = devtab[c->type]->read(c, (void*)arg[1], n, c->offset); lock(c); c->offset += n; unlock(c); poperror(); cclose(c); return n;}longsyswrite9p(ulong *arg){ Chan *c; long n; validaddr(arg[1], arg[2], 0); c = fdtochan(arg[0], OWRITE, 1, 1); if(waserror()) { cclose(c); nexterror(); } if(c->qid.path & CHDIR) error(Eisdir); if(devtab[c->type]->dc != L'M') n = devtab[c->type]->write(c, (void*)arg[1], arg[2], c->offset); else n = mntwrite9p(c, (void*)arg[1], arg[2], c->offset); lock(c); c->offset += n; unlock(c); poperror(); cclose(c); return n;}longsyswrite(ulong *arg){ Chan *c; long m, n; uvlong oo; validaddr(arg[1], arg[2], 0); n = arg[2]; c = fdtochan(arg[0], OWRITE, 1, 1); if(waserror()) { cclose(c); lock(c); c->offset -= n; unlock(c); nexterror(); } if(c->qid.path & CHDIR) error(Eisdir); lock(c); oo = c->offset; c->offset += n; unlock(c); m = devtab[c->type]->write(c, (void*)arg[1], n, oo); if(m < n){ lock(c); c->offset -= n - m; unlock(c); } poperror(); cclose(c); return m;}static voidsseek(ulong *arg){ Chan *c; char buf[DIRLEN]; Dir dir; vlong off; union { vlong v; ulong u[2]; } o; c = fdtochan(arg[1], -1, 1, 1); if(waserror()){ cclose(c); nexterror(); } if(c->qid.path & CHDIR) error(Eisdir); if(devtab[c->type]->dc == '|') error(Eisstream); off = 0; o.u[0] = arg[2]; o.u[1] = arg[3]; switch(arg[4]){ case 0: off = o.v; c->offset = off; break; case 1: lock(c); /* lock for read/write update */ off = o.v + c->offset; c->offset = off; unlock(c); break; case 2: devtab[c->type]->stat(c, buf); convM2D(buf, &dir); off = dir.length + o.v; c->offset = off; break; } *(vlong*)arg[0] = off; c->uri = 0; cclose(c); poperror();}longsysseek(ulong *arg){ validaddr(arg[0], BY2V, 1); sseek(arg); return 0;}longsysoseek(ulong *arg){ union { vlong v; ulong u[2]; } o; ulong a[5]; o.v = arg[1]; a[0] = (ulong)&o.v; a[1] = arg[0]; a[2] = o.u[0]; a[3] = o.u[1]; a[4] = arg[2]; sseek(a); return o.v;}longsysfstat(ulong *arg){ Chan *c; validaddr(arg[1], DIRLEN, 1); evenaddr(arg[1]); c = fdtochan(arg[0], -1, 0, 1); if(waserror()) { cclose(c); nexterror(); } devtab[c->type]->stat(c, (char*)arg[1]); poperror(); cclose(c); return 0;}longsysstat(ulong *arg){ Chan *c; validaddr(arg[1], DIRLEN, 1); evenaddr(arg[1]); validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aaccess, 0, 0); if(waserror()){ cclose(c); nexterror(); } devtab[c->type]->stat(c, (char*)arg[1]); poperror(); cclose(c); return 0;}longsyschdir(ulong *arg){ Chan *c; validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Atodir, 0, 0); cclose(up->dot); up->dot = c; return 0;}longbindmount(ulong *arg, int ismount){ ulong flag; int fd, ret; Chan *c0, *c1, *bc; struct{ Chan *chan; char *spec; int flags; }bogus; flag = arg[2]; fd = arg[0]; if(flag>MMASK || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); bogus.flags = flag & MCACHE; if(ismount){ if(up->pgrp->noattach) error(Enoattach); bc = fdtochan(fd, ORDWR, 0, 1); if(waserror()) { cclose(bc); nexterror(); } bogus.chan = bc; validaddr(arg[3], 1, 0); if(vmemchr((char*)arg[3], '\0', NAMELEN) == 0) error(Ebadarg); bogus.spec = (char*)arg[3]; if(waserror()) error(Ebadspec); nameok(bogus.spec, 1); poperror(); ret = devno('M', 0); c0 = devtab[ret]->attach((char*)&bogus); poperror(); cclose(bc); } else { bogus.spec = 0; validaddr(arg[0], 1, 0); c0 = namec((char*)arg[0], Aaccess, 0, 0); } if(waserror()){ cclose(c0); nexterror(); } validaddr(arg[1], 1, 0); c1 = namec((char*)arg[1], Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } ret = cmount(c0, c1, flag, bogus.spec); poperror(); cclose(c1); poperror(); cclose(c0); if(ismount) fdclose(fd, 0); return ret;}longsysbind(ulong *arg){ return bindmount(arg, 0);}longsysmount(ulong *arg){ return bindmount(arg, 1);}longsysunmount(ulong *arg){ Chan *cmount, *cmounted; cmounted = 0; validaddr(arg[1], 1, 0); cmount = namec((char *)arg[1], Amount, 0, 0); if(arg[0]) { if(waserror()) { cclose(cmount); nexterror(); } validaddr(arg[0], 1, 0); cmounted = namec((char*)arg[0], Aopen, OREAD, 0); poperror(); } if(waserror()) { cclose(cmount); if(cmounted) cclose(cmounted); nexterror(); } cunmount(cmount, cmounted); cclose(cmount); if(cmounted) cclose(cmounted); poperror(); return 0;}longsyscreate(ulong *arg){ int fd; Chan *c = 0; openmode(arg[1]); /* error check only */ if(waserror()) { if(c) cclose(c); nexterror(); } validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Acreate, arg[1], arg[2]); fd = newfd(c); if(fd < 0) error(Enofd); poperror(); return fd;}longsysremove(ulong *arg){ Chan *c; validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aaccess, 0, 0); if(waserror()){ c->type = 0; /* see below */ cclose(c); nexterror(); } devtab[c->type]->remove(c); /* * Remove clunks the fid, but we need to recover the Chan * so fake it up. rootclose() is known to be a nop. */ c->type = 0; poperror(); cclose(c); return 0;}longsyswstat(ulong *arg){ Chan *c; validaddr(arg[1], DIRLEN, 0); nameok((char*)arg[1], 0); validaddr(arg[0], 1, 0); c = namec((char*)arg[0], Aaccess, 0, 0); if(waserror()){ cclose(c); nexterror(); } devtab[c->type]->wstat(c, (char*)arg[1]); poperror(); cclose(c); return 0;}longsysfwstat(ulong *arg){ Chan *c; validaddr(arg[1], DIRLEN, 0); nameok((char*)arg[1], 0); c = fdtochan(arg[0], -1, 1, 1); if(waserror()) { cclose(c); nexterror(); } devtab[c->type]->wstat(c, (char*)arg[1]); poperror(); cclose(c); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -