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:
parent
c6de6b66e9
commit
99855d60d6
33
qa/kern/wdir.rc
Normal file
33
qa/kern/wdir.rc
Normal 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
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 == '\'')
|
||||
|
38
sys/src/lib/c/9sys/chdir.c
Normal file
38
sys/src/lib/c/9sys/chdir.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user