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.
This commit is contained in:
Giacomo Tesio 2016-12-15 22:42:01 +01:00
parent c6de6b66e9
commit 99855d60d6
20 changed files with 357 additions and 308 deletions

33
qa/kern/wdir.rc Normal file
View File

@ -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

View File

@ -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");

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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 <giacomo@tesio.it>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <u.h>
@ -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");
}

View File

@ -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; i<nwindow; i++)
if(window[i]->notefd >= 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);

View File

@ -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;

View File

@ -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;

View File

@ -25,6 +25,12 @@
#include <trace.h>
#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);

View File

@ -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:

View File

@ -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; i++)
if(strcmp(tab[i].name, name) == 0)
break;
if(i==ntab)
return -1;
tab += i;
}else{
/* skip over the first element, that for . itself */
i++;
if(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

View File

@ -1,21 +1,3 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2015-2016 Giacomo Tesio <giacomo@tesio.it>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* This device has been ported from 9front.
*/
#include "u.h"

View File

@ -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<<pages->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);
}

View File

@ -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.

View File

@ -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 == '\'')

View File

@ -0,0 +1,38 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2016 Giacomo Tesio <giacomo@tesio.it>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <libc.h>
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;
}

View File

@ -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 <giacomo@tesio.it>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <libc.h>
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;
}

View File

@ -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",

View File

@ -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"