From 99855d60d6ee1a20b46895d8dde59d9ae6feb794 Mon Sep 17 00:00:00 2001 From: Giacomo Tesio Date: Thu, 15 Dec 2016 22:42:01 +0100 Subject: [PATCH] kernel: move chdir to libc using devself/devproc Added wdir to devself and devproc: - read '#0/wdir' to get the working directory of the calling process NOTE that a read(fd, nil, -1) will return the negated length of the working directory, just in case you want to allocate the memory required - read '/proc/n/wdir' to know the working directory of process n (read(fd, nil, -1) still returns the negated length) - write '#0/wdir' to change the working directory of the calling process NOTE: no offset is allowed and the provided string must be null terminated - write '/proc/n/wdir' to change the working directory of process n NOTE: no offset is allowed and the provided string must be null terminated; moreover if another process change the working directory change during the write, the current process will receive an error. In libc updated getwd() and chdir(). Also modified pwd to get advantage of the new file. To test, run /arch/amd64/qa/kern/wdir.rc or simply try % pwd /usr/glenda % echo -n /tmp > /proc/$pid/wdir % pwd /tmp % cat '#0/wdir' && echo /tmp The expected use cases for wdir in devproc are rio and acme. Also, note that we could theoretically remove the cd builtin from rc and simply implement it as a rc function. We don't do that to preserve rc portability to other OS. --- qa/kern/wdir.rc | 33 ++++++++ qa/lib/c/asmscall.c | 41 +--------- sys/include/libc.h | 3 +- sys/src/cmd/acme/aux/win/main.c | 18 ++--- sys/src/cmd/cpu.c | 2 +- sys/src/cmd/pwd.c | 43 +++++++--- sys/src/cmd/rio/rio.c | 10 +-- sys/src/cmd/tar.c | 2 +- sys/src/kern/port/devdup.c | 4 +- sys/src/kern/port/devproc.c | 50 ++++++++++-- sys/src/kern/port/devsegment.c | 2 +- sys/src/kern/port/devself.c | 114 +++++++++++++++++++++++++-- sys/src/kern/port/devshr.c | 18 ----- sys/src/kern/port/fault.c | 135 +------------------------------- sys/src/kern/port/sysfile.c | 30 +++---- sys/src/lib/auth/newns.c | 6 +- sys/src/lib/c/9sys/chdir.c | 38 +++++++++ sys/src/lib/c/9sys/getwd.c | 47 +++++++---- sys/src/lib/c/build.json | 1 + sys/src/sysconf.json | 68 +++++++--------- 20 files changed, 357 insertions(+), 308 deletions(-) create mode 100644 qa/kern/wdir.rc create mode 100644 sys/src/lib/c/9sys/chdir.c diff --git a/qa/kern/wdir.rc b/qa/kern/wdir.rc new file mode 100644 index 0000000..a3c4719 --- /dev/null +++ b/qa/kern/wdir.rc @@ -0,0 +1,33 @@ +#!/cmd/rc + +rm -fr /tmp/abcdefghijklmnopqrstuvwxyz/ + +dir=/tmp/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz/abcdefghijklmnopqrstuvwxyz + +mkdir -p $dir +cd $dir + +cwd=`{pwd} + +if ( ! ~ $dir $cwd ) { + echo FAIL: '''pwd''' returned $cwd instead of '$dir' + exit FAIL +} + +cwd=`{cat '#0/wdir'} +if ( ! ~ $dir $cwd ) { + echo FAIL: '''cat #0/wdir''' returned $cwd instead of '$dir' + exit FAIL +} + +ppath=/proc/$pid/wdir + +cwd=`{cat $ppath} +if ( ! ~ $dir $cwd ) { + echo FAIL: cat $ppath returned $cwd instead of '$dir' + exit FAIL +} + +rm -fr /tmp/abcdefghijklmnopqrstuvwxyz/ +echo PASS +exit PASS diff --git a/qa/lib/c/asmscall.c b/qa/lib/c/asmscall.c index 01e8d28..7ba2297 100644 --- a/qa/lib/c/asmscall.c +++ b/qa/lib/c/asmscall.c @@ -20,41 +20,6 @@ int verbose = 1; -#define asm_nsec() ({ \ - register long __ret asm ("rax"); \ - __asm__ __volatile__ ( \ - "syscall" \ - : "=r" (__ret) \ - : "0"(19) \ - : "cc", "rcx", "r11", "memory" \ - ); \ - __ret; }) - -#define asm_mount(/* int */ fd, /* int */ afd, /* char* */ old, /* int */ flag, /* char* */ aname, /* int */ mdev) ({ \ - register long r10 asm("r10") = flag; \ - register long r8 asm("r8") = (uintptr_t)aname; \ - register long r9 asm("r9") = mdev; \ - register int __ret asm ("eax"); \ - __asm__ __volatile__ ( \ - "syscall" \ - : "=r" (__ret) \ - : "0"(16), "D"(fd), "S"(afd), "d"(old), "r"(r10), "r"(r8), "r"(r9) \ - : "cc", "rcx", "r11", "memory" \ - ); \ - __ret; }) - -/* -long -asm_nsec(void) -{ - register int *p1 asm ("r0"); - register int *p2 asm ("r1"); - register int *result asm ("r0"); - asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2)); - return result ; -} -*/ - void main(void) { @@ -62,9 +27,9 @@ main(void) uint64_t start, end; char *msg; - start = asm_nsec(); + start = sys_nsec(); sleep(1); - end = asm_nsec(); + end = sys_nsec(); if (end <= start) ret = 1; @@ -80,7 +45,7 @@ main(void) int fd; fd = open("#|", ORDWR); - asm_mount(fd, -1, "/tmp", MREPL, "", 'M'); + sys_mount(fd, -1, "/tmp", MREPL, "", 'M'); print("PASS\n"); exits("PASS"); diff --git a/sys/include/libc.h b/sys/include/libc.h index b1d5283..81c72b8 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -370,6 +370,7 @@ extern int atoi(const char*); extern int32_t atol(const char*); extern int64_t atoll(const char*); extern double charstod(int(*)(void*), void*); +extern int chdir(const char *dirname); extern char* cleanname(char*); extern int decrypt(void*, void*, int); extern int encrypt(void*, void*, int); @@ -387,7 +388,7 @@ extern char* getenv(const char*); extern int getfields(char*, char**, int, int, const char*); extern int gettokens(char *, char **, int, const char *); extern char* getuser(void); -extern char* getwd(char*, int); +extern long getwd(char*, int); extern int iounit(int); extern int32_t labs(int32_t); extern double ldexp(double, int); diff --git a/sys/src/cmd/acme/aux/win/main.c b/sys/src/cmd/acme/aux/win/main.c index 21b1783..7530034 100644 --- a/sys/src/cmd/acme/aux/win/main.c +++ b/sys/src/cmd/acme/aux/win/main.c @@ -71,7 +71,7 @@ threadmain(int argc, char *argv[]) name = av[0]; } - if(getwd(buf, sizeof buf) == 0) + if(getwd(buf, sizeof buf) <= 0) dir = "/"; else dir = buf; @@ -301,7 +301,7 @@ fsloop(void* _) break; } } -} +} void sendit(char *s) @@ -358,7 +358,7 @@ execevent(Window *w, Event *e, int (*command)(Window*, char*)) n = winread(w, e->q0, e->q1, s); s[n] = '\0'; needfree = 1; - }else + }else if(na){ t = emalloc(strlen(s)+1+na+2); sprint(t, "%s %s", s, ea->b); @@ -448,7 +448,7 @@ mainctl(void *v) write(w->data, e->b, e->nb); pendingS += e->nr; break; - + case 'E': /* write to tag or body; body happens due to sendit */ delta = e->q1-e->q0; if(e->c2=='I'){ @@ -463,7 +463,7 @@ mainctl(void *v) fprint(2, "win msg: %C %C %d %d %d %d %q\n", e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b); break; - + case 'F': /* generated by our actions (specifically case 'S' above) */ delta = e->q1-e->q0; if(e->c2=='D'){ @@ -540,7 +540,7 @@ mainctl(void *v) break; } break; - + case 'M': /* mouse */ delta = e->q1-e->q0; switch(e->c2){ @@ -548,14 +548,14 @@ mainctl(void *v) case 'X': execevent(w, e, command); break; - + case 'l': /* reflect all searches back to acme */ case 'L': if(e->flag & 2) recvp(w->cevent); winwriteevent(w, e); break; - + case 'I': endpt += delta; if(e->q0 < hostpt) @@ -574,7 +574,7 @@ mainctl(void *v) case 'd': /* modify away; we don't care */ case 'i': break; - + default: goto Unknown; } diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c index 6c2bf45..bca24de 100644 --- a/sys/src/cmd/cpu.c +++ b/sys/src/cmd/cpu.c @@ -231,7 +231,7 @@ main(int argc, char **argv) /* Tell the remote side the command to execute and where our working directory is */ if(cflag) writestr(data, cmd, "command", 0); - if(getwd(dat, sizeof(dat)) == 0) + if(getwd(dat, sizeof(dat)) <= 0) writestr(data, "NO", "dir", 0); else writestr(data, dat, "dir", 0); diff --git a/sys/src/cmd/pwd.c b/sys/src/cmd/pwd.c index b862250..15f33b8 100644 --- a/sys/src/cmd/pwd.c +++ b/sys/src/cmd/pwd.c @@ -1,10 +1,19 @@ /* - * This file is part of the UCB release of Plan 9. It is subject to the license - * terms in the LICENSE file found in the top-level directory of this - * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No - * part of the UCB release of Plan 9, including this file, may be copied, - * modified, propagated, or distributed except according to the terms contained - * in the LICENSE file. + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . */ #include @@ -16,13 +25,23 @@ void main(int argc, char *argv[]) { - char pathname[512]; + long len; + char path[512]; + char *ppath = path; - //USED(argc, argv); - if(getwd(pathname, sizeof(pathname)) == 0) { - fprint(2, "pwd: %r\n"); - exits("getwd"); + len = getwd(ppath, sizeof(path)); + if(len == 0) + goto Error; + if(len < 0){ + len = ~len; + ppath = malloc(len*sizeof(char)); + if(getwd(ppath, len*sizeof(char)) <= 0) + goto Error; } - print("%s\n", pathname); + print("%s\n", ppath); exits(0); + +Error: + fprint(2, "pwd: %r\n"); + exits("getwd"); } diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c index c395694..b7313ed 100644 --- a/sys/src/cmd/rio/rio.c +++ b/sys/src/cmd/rio/rio.c @@ -157,7 +157,7 @@ threadmain(int argc, char *argv[]) usage(); }ARGEND - if(getwd(buf, sizeof buf) == nil) + if(getwd(buf, sizeof buf) <= 0) startdir = estrdup("."); else startdir = estrdup(buf); @@ -324,7 +324,7 @@ shutdown(void * _, char *msg) { int i; static Lock shutdownlk; - + killprocs(); for(i=0; oknotes[i]; i++) if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0){ @@ -344,7 +344,7 @@ killprocs(void) for(i=0; inotefd >= 0) - write(window[i]->notefd, "hangup", 6); + write(window[i]->notefd, "hangup", 6); } void @@ -418,7 +418,7 @@ int whichcorner(Rectangle r, Point p) { int i, j; - + i = portion(p.x, r.min.x, r.max.x); j = portion(p.y, r.min.y, r.max.y); return 3*j+i; @@ -995,7 +995,7 @@ bandsize(Window *w) drawborder(r, 1); or = r; startp = p; - + while(mouse->buttons==but){ p = onscreen(mouse->xy); r = whichrect(w->screenr, p, which); diff --git a/sys/src/cmd/tar.c b/sys/src/cmd/tar.c index b1614d0..bb41b62 100644 --- a/sys/src/cmd/tar.c +++ b/sys/src/cmd/tar.c @@ -1366,7 +1366,7 @@ main(int argc, char *argv[]) ret = extract(argv); break; case Replace: - if (getwd(origdir, sizeof origdir) == nil) + if (getwd(origdir, sizeof origdir) <= 0) strcpy(origdir, "/tmp"); ret = replace(argv); break; diff --git a/sys/src/kern/port/devdup.c b/sys/src/kern/port/devdup.c index 82f2720..566ed0c 100644 --- a/sys/src/kern/port/devdup.c +++ b/sys/src/kern/port/devdup.c @@ -64,9 +64,9 @@ dupopen(Chan *c, unsigned long omode) int fd, twicefd; if(c->qid.type & QTDIR){ - if(omode != 0) + if(omode != OREAD) error(Eisdir); - c->mode = 0; + c->mode = OREAD; c->flag |= COPEN; c->offset = 0; return c; diff --git a/sys/src/kern/port/devproc.c b/sys/src/kern/port/devproc.c index e6e64a9..53b86c7 100644 --- a/sys/src/kern/port/devproc.c +++ b/sys/src/kern/port/devproc.c @@ -25,6 +25,12 @@ #include #include "ureg.h" +extern long write_working_dir(Proc* p, void *va, long n, int64_t off); +extern long read_working_dir(Proc* p, void *va, long n, int64_t off); + +/* We can have up to 32 files in proc/n sice we dedicate 5 bits in Qid + * to it (see QSHIFT) + */ enum { Qdir, @@ -47,6 +53,7 @@ enum Qwait, Qprofile, Qsyscall, + Qwdir, }; enum @@ -76,23 +83,25 @@ enum{ }; #define STATSIZE (2*KNAMELEN+NUMSIZE+9*NUMSIZE + 1) -/* - * Status, fd, and ns are left fully readable (0444) because of their use in debugging, - * particularly on shared servers. - * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000 +/* In Plan 9 status, fd, and ns were left fully readable (0444) + * because of their use in debugging, particularly on shared servers. + * + * In Jehanne the process owner and the host owner can read + * status and fd, but not others (0440). + * TODO: allow per process stats and permissions. */ Dirtab procdir[] = { "args", {Qargs}, 0, 0660, "ctl", {Qctl}, 0, 0000, - "fd", {Qfd}, 0, 0444, + "fd", {Qfd}, 0, 0440, "fpregs", {Qfpregs}, 0, 0000, "kregs", {Qkregs}, sizeof(Ureg), 0400, "mem", {Qmem}, 0, 0000, "note", {Qnote}, 0, 0000, "noteid", {Qnoteid}, 0, 0664, "notepg", {Qnotepg}, 0, 0000, - "ns", {Qns}, 0, 0444, + "ns", {Qns}, 0, 0440, "proc", {Qproc}, 0, 0400, "regs", {Qregs}, sizeof(Ureg), 0000, "segment", {Qsegment}, 0, 0444, @@ -100,6 +109,7 @@ Dirtab procdir[] = "text", {Qtext}, 0, 0000, "wait", {Qwait}, 0, 0400, "syscall", {Qsyscall}, 0, 0400, + "wdir", {Qwdir}, 0, 0640, }; static @@ -124,7 +134,7 @@ Cmdtab proccmd[] = { /* * Qids are, in path: - * 4 bits of file type (qids above) + * 5 bits of file type (qids above) * 23 bits of process slot number + 1 * in vers, * 32 bits of pid, for consistency checking @@ -232,6 +242,14 @@ procgen(Chan *c, char *name, Dirtab *tab, int _1, int s, Dir *dp) len = p->nwait; /* incorrect size, but >0 means there's something to read */ break; } + switch(QID(tab->qid)){ + case Qwdir: + /* file length might be relevant to the caller to + * malloc enough space in the buffer + */ + len = 1 + strlen(p->dot->path->s); + break; + } mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE); devdir(c, qid, tab->name, len, p->user, perm, dp); @@ -424,6 +442,17 @@ procopen(Chan *c, unsigned long omode) c->pgrpid.vers = p->noteid; break; + case Qwdir: + if(p == up) /* self write is always allowed */ + break; + if(omode > ORDWR) + error(Eperm); + if(strcmp(up->user, p->user) != 0 /* process owner can read/write */ + || !iseve() /* host owner can read */ + || (omode&OWRITE) != 0) + error(Eperm); + break; + default: poperror(); qunlock(&p->debug); @@ -1058,6 +1087,10 @@ procread(Chan *c, void *va, long n, int64_t off) r = procfds(p, va, n, offset); psdecref(p); return r; + case Qwdir: + r = read_working_dir(p, va, n, off); + psdecref(p); + return r; } error(Egreg); return 0; /* not reached */ @@ -1213,6 +1246,9 @@ procwrite(Chan *c, void *va, long n, int64_t off) if(p->noteid != id) error(Ebadarg); break; + case Qwdir: + n = write_working_dir(p, va, n, off); + break; default: poperror(); qunlock(&p->debug); diff --git a/sys/src/kern/port/devsegment.c b/sys/src/kern/port/devsegment.c index 6ec55fc..1d53aef 100644 --- a/sys/src/kern/port/devsegment.c +++ b/sys/src/kern/port/devsegment.c @@ -215,7 +215,7 @@ segmentopen(Chan *c, int omode) switch(TYPE(c)){ case Qtopdir: case Qsegdir: - if(omode != 0) + if(omode != OREAD) error(Eisdir); break; case Qctl: diff --git a/sys/src/kern/port/devself.c b/sys/src/kern/port/devself.c index 275f6ce..522d2f9 100644 --- a/sys/src/kern/port/devself.c +++ b/sys/src/kern/port/devself.c @@ -37,6 +37,7 @@ typedef enum SelfNodes Qppid, Qsegments, Qpipes, + Qwdir, } SelfNodes; typedef enum SegmentsCmd @@ -65,9 +66,49 @@ static Dirtab selfdir[]={ "ppid", {Qppid}, 0, 0, "segments", {Qsegments}, 0, 0644, "pipes", {Qpipes}, 0, 0, + "wdir", {Qwdir}, 0, 0644, }; +static int +selfgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) +{ + long length; + if(tab == 0) + return -1; + if(i == DEVDOTDOT){ + if(QID(c->qid) != Qdir) + panic("selfwalk %llux", c->qid.path); + devdir(c, selfdir[0].qid, "#0", 0, up->user, selfdir[0].perm, dp); + return 1; + } + + if(name){ + for(i=1; i= ntab) + return -1; + tab += i; + } + if(tab->qid.path == Qwdir) { + /* file length might be relevant to the caller to + * malloc enough space in the buffer + */ + length = 1 + strlen(up->dot->path->s); + } else { + length = tab->length; + } + devdir(c, tab->qid, tab->name, length, up->user, tab->perm, dp); + return 1; +} + static Chan* selfattach(Chan *c, Chan *ac, char *spec, int flags) { @@ -77,23 +118,80 @@ selfattach(Chan *c, Chan *ac, char *spec, int flags) static Walkqid* selfwalk(Chan *c, Chan *nc, char **name, int nname) { - return devwalk(c, nc, name, nname, selfdir, nelem(selfdir), devgen); + return devwalk(c, nc, name, nname, selfdir, nelem(selfdir), selfgen); } static long selfstat(Chan *c, uint8_t *dp, long n) { - return devstat(c, dp, n, selfdir, nelem(selfdir), devgen); + return devstat(c, dp, n, selfdir, nelem(selfdir), selfgen); } static Chan* selfopen(Chan *c, unsigned long omode) { c->aux = nil; - c = devopen(c, omode, selfdir, nelem(selfdir), devgen); + c = devopen(c, omode, selfdir, nelem(selfdir), selfgen); return c; } +long +read_working_dir(Proc* p, void *va, long n, int64_t off) +{ + int i, j; + char *path; + Chan *dot; + + dot = up->dot; + path = dot->path->s; + i = 1 + strlen(path); + if(va == nil){ + /* the user is actually asking for the space */ + if(off != 0 && off != ~0) { + /* #0/wdir does not allow offset in read */ + error("offset reading wdir size"); + } + errorl("not enough space in buffer", ~i); + } + if(off > i) + return 0; + j = i - off; + if(n < j) + j = n; + memmove(va, path, j); + + return j; +} + + +long +write_working_dir(Proc* p, void *va, long n, int64_t off) +{ + Chan *c, *dot; + char *path, *epath; + + dot = p->dot; + path = va; + epath = vmemchr(path, 0, n); + + if(n <= 0) + error(Ebadarg); + if(off != 0 && off != ~0) + error("offset writing wdir"); + if(epath-path>=n) + error("no terminal zero writing wdir"); + + c = namec(path, Atodir, 0, 0); + if(CASV(&p->dot, dot, c)){ + cclose(dot); + } else { + cclose(c); + error("race writing wdir"); + } + + return 0; +} + static long selfread(Chan *c, void *va, long n, int64_t off) { @@ -104,6 +202,8 @@ selfread(Chan *c, void *va, long n, int64_t off) offset = off; switch(QID(c->qid)){ + case Qdir: + return devdirread(c, va, n, selfdir, nelem(selfdir), selfgen); case Qsegments: rlock(&up->seglock); j = 0; @@ -127,6 +227,8 @@ selfread(Chan *c, void *va, long n, int64_t off) exhausted("segments"); memmove(va, &statbuf[offset], n); return n; + case Qwdir: + return read_working_dir(up, va, n, off); default: error(Egreg); } @@ -271,10 +373,10 @@ selfwrite(Chan *c, void *va, long n, int64_t off) default: error(Egreg); case Qsegments: - n = procsegctl(up, va, n); - break; + return procsegctl(up, va, n); + case Qwdir: + return write_working_dir(up, va, n, off); } - return n; } static int diff --git a/sys/src/kern/port/devshr.c b/sys/src/kern/port/devshr.c index 28e3e6d..a5950bf 100644 --- a/sys/src/kern/port/devshr.c +++ b/sys/src/kern/port/devshr.c @@ -1,21 +1,3 @@ -/* - * This file is part of Jehanne. - * - * Copyright (C) 2015-2016 Giacomo Tesio - * - * Jehanne is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * Jehanne is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Jehanne. If not, see . - */ - /* This device has been ported from 9front. */ #include "u.h" diff --git a/sys/src/kern/port/fault.c b/sys/src/kern/port/fault.c index 842d162..37c764b 100644 --- a/sys/src/kern/port/fault.c +++ b/sys/src/kern/port/fault.c @@ -6,13 +6,6 @@ #include "fns.h" #include "../port/error.h" -//char *faulttypes[] = { - //[FT_WRITE] "write", - //[FT_READ] "read", - //[FT_EXEC] "exec" -//}; - - int fault(uintptr_t addr, uintptr_t pc, int ftype) { @@ -70,132 +63,6 @@ fault(uintptr_t addr, uintptr_t pc, int ftype) return -1; } -//int -//fixfault(Segment *s, uintptr_t addr, int ftype, int dommuput) -//{ - //int type; - //Pte **p, *etp; - //uintptr_t soff; - //uintmem mmuphys; - //Page **pg, *old, *new; - //Page *(*fn)(Segment*, uintptr_t); - //uintptr_t pgsize; - //Pages *pages; - - //pages = s->pages; /* TO DO: segwalk */ - //pgsize = 1<lg2pgsize; - //addr &= ~(pgsize-1); - //soff = addr-s->pages->base; - - //p = &pages->map[soff/pages->ptemapmem]; - //if(*p == nil) - //*p = ptealloc(); - - //etp = *p; - //pg = &etp->pages[(soff&(pages->ptemapmem-1))>>pages->lg2pgsize]; - - //if(pg < etp->first) - //etp->first = pg; - //if(pg > etp->last) - //etp->last = pg; - - //type = s->type&SG_TYPE; - //if(*pg == nil){ - //switch(type){ - //case SG_BSS: /* Zero fill on demand */ - //case SG_SHARED: - //case SG_STACK: - //new = newpage(1, s->pages->lg2pgsize, &s->lk); - //if(new == nil) - //return -1; - //*pg = new; - //break; - - //case SG_LOAD: - //case SG_TEXT: /* demand load */ - //case SG_DATA: - //if(!loadimagepage(s->image, s, pg, addr)) - //return -1; - //break; - - //case SG_PHYSICAL: - //fn = s->pseg->pgalloc; - //if(fn != nil) - //*pg = (*fn)(s, addr); - //else { - //new = smalloc(sizeof(Page)); - //new->pa = s->pseg->pa+(addr-s->pages->base); - //new->r.ref = 1; - //new->lg2size = s->pseg->lg2pgsize; - //if(new->lg2size == 0) - //new->lg2size = PGSHFT; /* TO DO */ - //*pg = new; - //} - //break; - //default: - //panic("fault on demand"); - //break; - //} - //} - //mmuphys = 0; - //switch(type) { - //default: - //panic("fault"); - //break; - - //case SG_TEXT: - //DBG("text pg %#p: %#p -> %#P %d\n", pg, addr, (*pg)->pa, (*pg)->r.ref); - //mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID; - //break; - - //case SG_BSS: - //case SG_SHARED: - //case SG_STACK: - //case SG_DATA: /* copy on write */ - //DBG("data pg %#p: %#p -> %#P %d\n", pg, addr, (*pg)->pa, (*pg)->r.ref); - ///* - //* It's only possible to copy on write if - //* we're the only user of the segment. - //*/ - //if(ftype != FT_WRITE && sys->copymode == 0 && s->r.ref == 1) { - //mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID; - //break; - //} - - //old = *pg; - //if(old->r.ref > 1){ - ///* shared (including image pages): make private writable copy */ - //new = newpage(0, s->pages->lg2pgsize, &s->lk); - //if(new != nil) - //copypage(old, new); - //*pg = new; - //putpage(old); - //if(new == nil) - //return -1; - //DBG("data' pg %#p: %#p -> %#P %d\n", *pg, addr, old->pa, old->r.ref); - //}else if(old->r.ref <= 0) - //panic("fault: page %#p %#P ref %d <= 0", old, old->pa, old->r.ref); - //mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID; - //break; - - //case SG_PHYSICAL: - //mmuphys = PPN((*pg)->pa) | PTEVALID; - //if((s->pseg->attr & SG_WRITE)) - //mmuphys |= PTEWRITE; - //if((s->pseg->attr & SG_CACHED) == 0) - //mmuphys |= PTEUNCACHED; - //break; - //} - //runlock(&s->lk); - - //if(dommuput) - //mmuput(addr, mmuphys, *pg); - //if(ftype == FT_EXEC) - //peekAtExecFaults(addr); - - //return 0; -//} - /* * Called only in a system call */ @@ -225,7 +92,7 @@ void* validaddr(void* addr, long len, int write) { if(!okaddr(PTR2UINT(addr), len, write)){ - pprint("trap: invalid address %#p/%lud in sys call pc=%#P\n", addr, len, userpc(nil)); + pprint("trap: invalid address %#p/%ld in sys call pc=%#P\n", addr, len, userpc(nil)); postnote(up, 1, "sys: bad address in syscall", NDebug); error(Ebadarg); } diff --git a/sys/src/kern/port/sysfile.c b/sys/src/kern/port/sysfile.c index cc22a91..ea38c53 100644 --- a/sys/src/kern/port/sysfile.c +++ b/sys/src/kern/port/sysfile.c @@ -597,14 +597,24 @@ mountfix(Chan *c, uint8_t *op, int32_t n, int32_t maxn) } long -syspread(int fd, void *p, int32_t n, int64_t off) +syspread(int fd, void *p, long n, int64_t off) { int32_t nn; long nnn; int sequential; Chan *c; - p = validaddr(p, n, 1); + if(n >= 0) + p = validaddr(p, n, 1); + else if(p != nil) { + /* in Jehanne, a negative length can be meaningful to + * the target device/server, but with a negative length + * to read the buffer must be nil + */ + pprint("trap: invalid address %#p/%ld in sys call pc=%#P\n", p, n, userpc(nil)); + postnote(up, 1, "sys: bad address in syscall", NDebug); + error(Ebadarg); + } c = fdtochan(fd, OREAD, 1, 1); @@ -679,7 +689,7 @@ syspread(int fd, void *p, int32_t n, int64_t off) } long -syspwrite(int fd, void *p, int32_t n, int64_t off) +syspwrite(int fd, void *p, long n, int64_t off) { long r; int sequential; @@ -858,20 +868,6 @@ sysfstat(int fd, uint8_t* p, int n) return r; } -int -syschdir(char *aname) -{ - Chan *c; - - aname = validaddr(aname, 1, 0); - - c = namec(aname, Atodir, 0, 0); - cclose(up->dot); - up->dot = c; - - return 0; -} - /* white list of devices we allow mounting on. * At some point we can have build generate this if we ever * really start using it. diff --git a/sys/src/lib/auth/newns.c b/sys/src/lib/auth/newns.c index 8d7ac32..ea37b3b 100644 --- a/sys/src/lib/auth/newns.c +++ b/sys/src/lib/auth/newns.c @@ -77,7 +77,7 @@ buildns(int newns, char *user, char *file) /* make sure we managed to cd into the new name space */ if(newns && !cdroot){ path = malloc(1024); - if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0) + if(path == nil || getwd(path, 1024) <= 0 || chdir(path) < 0) chdir("/"); if(path != nil) free(path); @@ -222,7 +222,7 @@ unquote(char *s) { char *r, *w; int inquote; - + inquote = 0; for(r=w=s; *r; r++){ if(*r != '\''){ @@ -267,7 +267,7 @@ nextdollar(char *arg) { char *p; int inquote; - + inquote = 0; for(p=arg; *p; p++){ if(*p == '\'') diff --git a/sys/src/lib/c/9sys/chdir.c b/sys/src/lib/c/9sys/chdir.c new file mode 100644 index 0000000..8c7009c --- /dev/null +++ b/sys/src/lib/c/9sys/chdir.c @@ -0,0 +1,38 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ + +#include +#include + +int +chdir(const char *dirname) +{ + char buf[32]; + int tmp, fd; + + tmp = getpid(); + snprint(buf, sizeof(buf), "/proc/%d/wdir", tmp); + fd = open(buf, OWRITE); + if(fd < 0) + fd = open("#0/wdir", OWRITE); + if(fd < 0) + return fd; + tmp = write(fd, dirname, 1+strlen(dirname)); + close(fd); + return tmp; +} diff --git a/sys/src/lib/c/9sys/getwd.c b/sys/src/lib/c/9sys/getwd.c index 4834c1e..2b4e04b 100644 --- a/sys/src/lib/c/9sys/getwd.c +++ b/sys/src/lib/c/9sys/getwd.c @@ -1,26 +1,45 @@ /* - * This file is part of the UCB release of Plan 9. It is subject to the license - * terms in the LICENSE file found in the top-level directory of this - * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No - * part of the UCB release of Plan 9, including this file, may be copied, - * modified, propagated, or distributed except according to the terms contained - * in the LICENSE file. + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . */ #include #include -char* +/* Fills buf with the current workking directory. + * + * Returns + * - 0 on error + * - the negated length of the working directory path if nbuf is too small + * - the (positive) length of the working directory on success + */ +long getwd(char *buf, int nbuf) { - int n, fd; + long n; + int fd; - fd = open(".", OREAD); + fd = open("#0/wdir", OREAD); if(fd < 0) - return nil; - n = fd2path(fd, buf, nbuf); + return 0; + n = read(fd, nil, -1); + if(n == ~0) /* an error occurred */ + return 0; + if(nbuf >= ~n) + n = read(fd, buf, nbuf); close(fd); - if(n < 0) - return nil; - return buf; + return n; } diff --git a/sys/src/lib/c/build.json b/sys/src/lib/c/build.json index 097b7a5..6de15f9 100644 --- a/sys/src/lib/c/build.json +++ b/sys/src/lib/c/build.json @@ -38,6 +38,7 @@ "9sys/access.c", "9sys/announce.c", "9sys/awakened.c", + "9sys/chdir.c", "9sys/convD2M.c", "9sys/convM2D.c", "9sys/cputime.c", diff --git a/sys/src/sysconf.json b/sys/src/sysconf.json index 853cc64..ab80fe9 100644 --- a/sys/src/sysconf.json +++ b/sys/src/sysconf.json @@ -65,19 +65,9 @@ }, { "Args": [ - "const char*" + "int" ], "Id": 4, - "Name": "chdir", - "Ret": [ - "int" - ] - }, - { - "Args": [ - "int" - ], - "Id": 5, "Name": "close", "Ret": [ "long" @@ -89,7 +79,7 @@ "uint32_t", "uint32_t" ], - "Id": 6, + "Id": 5, "Name": "create", "Ret": [ "long" @@ -100,7 +90,7 @@ "int32_t", "int32_t" ], - "Id": 7, + "Id": 6, "Name": "dup", "Ret": [ "int32_t" @@ -111,7 +101,7 @@ "char*", "int" ], - "Id": 8, + "Id": 7, "Name": "errstr", "Ret": [ "int" @@ -122,7 +112,7 @@ "const char*", "const char**" ], - "Id": 9, + "Id": 8, "Name": "exec", "Ret": [ "uintptr_t" @@ -132,7 +122,7 @@ "Args": [ "const char*" ], - "Id": 10, + "Id": 9, "Name": "_exits", "Ret": [ "int" @@ -143,7 +133,7 @@ "int", "const char*" ], - "Id": 11, + "Id": 10, "Name": "fauth", "Ret": [ "int" @@ -155,7 +145,7 @@ "const char*", "uint32_t" ], - "Id": 12, + "Id": 11, "Name": "fd2path", "Ret": [ "int32_t" @@ -167,7 +157,7 @@ "uint8_t*", "int" ], - "Id": 13, + "Id": 12, "Name": "fstat", "Ret": [ "long" @@ -180,7 +170,7 @@ "const char*", "int" ], - "Id": 14, + "Id": 13, "Name": "fversion", "Ret": [ "int" @@ -192,7 +182,7 @@ "const uint8_t*", "uint32_t" ], - "Id": 15, + "Id": 14, "Name": "fwstat", "Ret": [ "long" @@ -207,7 +197,7 @@ "const char*", "int" ], - "Id": 16, + "Id": 15, "Name": "mount", "Ret": [ "int" @@ -217,7 +207,7 @@ "Args": [ "int" ], - "Id": 17, + "Id": 16, "Name": "noted", "Ret": [ "int" @@ -227,14 +217,14 @@ "Args": [ "const void*" ], - "Id": 18, + "Id": 17, "Name": "notify", "Ret": [ "int" ] }, { - "Id": 19, + "Id": 18, "Name": "nsec", "Ret": [ "long" @@ -245,7 +235,7 @@ "const char*", "uint32_t" ], - "Id": 20, + "Id": 19, "Name": "open", "Ret": [ "long" @@ -255,10 +245,10 @@ "Args": [ "int", "void*", - "int", + "long", "long" ], - "Id": 21, + "Id": 20, "Name": "pread", "Ret": [ "long" @@ -268,10 +258,10 @@ "Args": [ "int", "const void*", - "int", + "long", "long" ], - "Id": 22, + "Id": 21, "Name": "pwrite", "Ret": [ "long" @@ -281,7 +271,7 @@ "Args": [ "const char*" ], - "Id": 23, + "Id": 22, "Name": "remove", "Ret": [ "long" @@ -292,7 +282,7 @@ "const void*", "void*" ], - "Id": 24, + "Id": 23, "Name": "rendezvous", "Ret": [ "void*" @@ -302,7 +292,7 @@ "Args": [ "uint32_t" ], - "Id": 25, + "Id": 24, "Name": "rfork", "Ret": [ "int" @@ -314,7 +304,7 @@ "long", "int" ], - "Id": 26, + "Id": 25, "Name": "seek", "Ret": [ "long" @@ -325,7 +315,7 @@ "int*", "int" ], - "Id": 27, + "Id": 26, "Name": "semacquire", "Ret": [ "int" @@ -336,7 +326,7 @@ "int*", "int" ], - "Id": 28, + "Id": 27, "Name": "semrelease", "Ret": [ "int" @@ -347,7 +337,7 @@ "int*", "uint64_t" ], - "Id": 29, + "Id": 28, "Name": "tsemacquire", "Ret": [ "int" @@ -358,7 +348,7 @@ "const char*", "const char*" ], - "Id": 30, + "Id": 29, "Name": "unmount", "Ret": [ "int" @@ -368,7 +358,7 @@ "Args": [ "unsigned long" ], - "Id": 31, + "Id": 30, "Name": "alarm", "Ret": [ "long"