summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/man/2/dup13
-rw-r--r--sys/src/9/port/auth.c5
-rw-r--r--sys/src/9/port/chan.c7
-rw-r--r--sys/src/9/port/devdup.c2
-rw-r--r--sys/src/9/port/devshr.c2
-rw-r--r--sys/src/9/port/devsrv.c4
-rw-r--r--sys/src/9/port/lib.h2
-rw-r--r--sys/src/9/port/pgrp.c14
-rw-r--r--sys/src/9/port/portdat.h3
-rw-r--r--sys/src/9/port/portfns.h2
-rw-r--r--sys/src/9/port/sysfile.c50
11 files changed, 74 insertions, 30 deletions
diff --git a/sys/man/2/dup b/sys/man/2/dup
index cd3414106..1eca0a713 100644
--- a/sys/man/2/dup
+++ b/sys/man/2/dup
@@ -32,6 +32,19 @@ requires that
.I newfd
be no greater than 20 more than the highest file descriptor ever used by
the program.
+.PP
+.I Dup
+does not copy the per file descriptor
+.B OCEXEC
+flag,
+meaning that
+.I newfd
+will not be closed on
+.IR exec(2)
+syscall,
+when
+.I oldfd
+had been previously opend with it.
.SH SOURCE
.B /sys/src/libc/9syscall
.SH SEE ALSO
diff --git a/sys/src/9/port/auth.c b/sys/src/9/port/auth.c
index 2cc54c657..b6b19bd63 100644
--- a/sys/src/9/port/auth.c
+++ b/sys/src/9/port/auth.c
@@ -97,13 +97,12 @@ sysfauth(va_list list)
nexterror();
}
- fd = newfd(ac);
+ /* always mark it close on exec */
+ fd = newfd(ac, OCEXEC);
if(fd < 0)
error(Enofd);
poperror(); /* ac */
- /* always mark it close on exec */
- ac->flag |= CCEXEC;
return (uintptr)fd;
}
diff --git a/sys/src/9/port/chan.c b/sys/src/9/port/chan.c
index 58a47cc83..e60561d1a 100644
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -1468,9 +1468,6 @@ namec(char *aname, int amode, int omode, ulong perm)
saveregisters();
c = devtab[c->type]->open(c, omode&~OCEXEC);
-
- if(omode & OCEXEC)
- c->flag |= CCEXEC;
if(omode & ORCLOSE)
c->flag |= CRCLOSE;
break;
@@ -1571,11 +1568,9 @@ namec(char *aname, int amode, int omode, ulong perm)
incref(cnew->path);
cnew = devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm);
- poperror();
- if(omode & OCEXEC)
- cnew->flag |= CCEXEC;
if(omode & ORCLOSE)
cnew->flag |= CRCLOSE;
+ poperror();
putmhead(m);
cclose(c);
c = cnew;
diff --git a/sys/src/9/port/devdup.c b/sys/src/9/port/devdup.c
index 2ba718729..79c7d90ff 100644
--- a/sys/src/9/port/devdup.c
+++ b/sys/src/9/port/devdup.c
@@ -63,6 +63,8 @@ dupopen(Chan *c, int omode)
Chan *f;
int fd, twicefd;
+ if(omode & ORCLOSE)
+ error(Eperm);
if(c->qid.type & QTDIR){
if(omode != 0)
error(Eisdir);
diff --git a/sys/src/9/port/devshr.c b/sys/src/9/port/devshr.c
index 96e319221..225ba6c93 100644
--- a/sys/src/9/port/devshr.c
+++ b/sys/src/9/port/devshr.c
@@ -396,6 +396,8 @@ shropen(Chan *c, int omode)
case Qcmpt:
if(omode&OTRUNC)
error(Eexist);
+ if(omode&ORCLOSE)
+ error(Eperm);
shr = sch->shr;
mpt = sch->mpt;
devpermcheck(mpt->owner, mpt->perm, mode);
diff --git a/sys/src/9/port/devsrv.c b/sys/src/9/port/devsrv.c
index 193fa6c8b..8128569a1 100644
--- a/sys/src/9/port/devsrv.c
+++ b/sys/src/9/port/devsrv.c
@@ -135,6 +135,8 @@ srvopen(Chan *c, int omode)
if(omode&OTRUNC)
error(Eexist);
+ if(omode&ORCLOSE)
+ error(Eperm);
if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR)
error(Eperm);
devpermcheck(sp->owner, sp->perm, omode);
@@ -338,8 +340,6 @@ srvwrite(Chan *c, void *va, long n, vlong)
cclose(c1);
nexterror();
}
- if(c1->flag & (CCEXEC|CRCLOSE))
- error("posted fd has remove-on-close or close-on-exec");
if(c1->qid.type & QTAUTH)
error("cannot post auth file in srv");
sp = srvlookup(nil, c->qid.path);
diff --git a/sys/src/9/port/lib.h b/sys/src/9/port/lib.h
index 1f7bf7d1d..06b423d9d 100644
--- a/sys/src/9/port/lib.h
+++ b/sys/src/9/port/lib.h
@@ -176,7 +176,7 @@ extern void qsort(void*, long, long, int (*)(void*, void*));
#define ORDWR 2 /* read and write */
#define OEXEC 3 /* execute, == read but check execute permission */
#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
-#define OCEXEC 32 /* or'ed in, close on exec */
+#define OCEXEC 32 /* or'ed in (per file descriptor), close on exec */
#define ORCLOSE 64 /* or'ed in, remove on close */
#define OEXCL 0x1000 /* or'ed in, exclusive create */
diff --git a/sys/src/9/port/pgrp.c b/sys/src/9/port/pgrp.c
index 5576acc57..408370d35 100644
--- a/sys/src/9/port/pgrp.c
+++ b/sys/src/9/port/pgrp.c
@@ -140,7 +140,8 @@ dupfgrp(Fgrp *f)
new = smalloc(sizeof(Fgrp));
if(f == nil){
- new->fd = smalloc(DELTAFD*sizeof(Chan*));
+ new->flag = smalloc(DELTAFD*sizeof(new->flag[0]));
+ new->fd = smalloc(DELTAFD*sizeof(new->fd[0]));
new->nfd = DELTAFD;
new->ref = 1;
return new;
@@ -152,12 +153,19 @@ dupfgrp(Fgrp *f)
i = new->nfd%DELTAFD;
if(i != 0)
new->nfd += DELTAFD - i;
- new->fd = malloc(new->nfd*sizeof(Chan*));
+ new->fd = malloc(new->nfd*sizeof(new->fd[0]));
if(new->fd == nil){
unlock(f);
free(new);
error("no memory for fgrp");
}
+ new->flag = malloc(new->nfd*sizeof(new->flag[0]));
+ if(new->flag == nil){
+ unlock(f);
+ free(new->fd);
+ free(new);
+ error("no memory for fgrp");
+ }
new->ref = 1;
new->maxfd = f->maxfd;
@@ -165,6 +173,7 @@ dupfgrp(Fgrp *f)
if((c = f->fd[i]) != nil){
incref(c);
new->fd[i] = c;
+ new->flag[i] = f->flag[i];
}
}
unlock(f);
@@ -194,6 +203,7 @@ closefgrp(Fgrp *f)
up->closingfgrp = nil;
free(f->fd);
+ free(f->flag);
free(f);
}
diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h
index 7c9aa7193..a5cdafa6a 100644
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -125,7 +125,7 @@ enum
COPEN = 0x0001, /* for i/o */
CMSG = 0x0002, /* the message channel for a mount */
/*rsc CCREATE = 0x0004, /* permits creation if c->mnt */
- CCEXEC = 0x0008, /* close on exec */
+ CCEXEC = 0x0008, /* close on exec (per file descriptor) */
CFREE = 0x0010, /* not in use */
CRCLOSE = 0x0020, /* remove on close */
CCACHE = 0x0080, /* client cache */
@@ -509,6 +509,7 @@ struct Fgrp
Ref;
Lock;
Chan **fd;
+ uchar *flag; /* per file-descriptor flags (CCEXEC) */
int nfd; /* number allocated */
int maxfd; /* highest fd in use */
int exceed; /* debugging */
diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h
index 04550987f..00c7e8b96 100644
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -201,7 +201,7 @@ Chan* namec(char*, int, int, ulong);
void nameerror(char*, char*);
int needpages(void*);
Chan* newchan(void);
-int newfd(Chan*);
+int newfd(Chan*, int);
Mhead* newmhead(Chan*);
Mount* newmount(Chan*, int, char*);
Page* newpage(int, Segment **, uintptr);
diff --git a/sys/src/9/port/sysfile.c b/sys/src/9/port/sysfile.c
index ed8e5c7ad..a503b2cca 100644
--- a/sys/src/9/port/sysfile.c
+++ b/sys/src/9/port/sysfile.c
@@ -25,33 +25,45 @@ int
growfd(Fgrp *f, int fd) /* fd is always >= 0 */
{
Chan **newfd, **oldfd;
+ uchar *newflag, *oldflag;
+ int nfd;
- if(fd < f->nfd)
+ nfd = f->nfd;
+ if(fd < nfd)
return 0;
- if(fd >= f->nfd+DELTAFD)
+ if(fd >= nfd+DELTAFD)
return -1; /* out of range */
/*
* Unbounded allocation is unwise; besides, there are only 16 bits
* of fid in 9P
*/
- if(f->nfd >= 5000){
+ if(nfd >= 5000){
Exhausted:
print("no free file descriptors\n");
return -1;
}
- newfd = malloc((f->nfd+DELTAFD)*sizeof(Chan*));
+ oldfd = f->fd;
+ oldflag = f->flag;
+ newfd = malloc((nfd+DELTAFD)*sizeof(newfd[0]));
if(newfd == nil)
goto Exhausted;
- oldfd = f->fd;
- memmove(newfd, oldfd, f->nfd*sizeof(Chan*));
+ memmove(newfd, oldfd, nfd*sizeof(newfd[0]));
+ newflag = malloc((nfd+DELTAFD)*sizeof(newflag[0]));
+ if(newflag == nil){
+ free(newfd);
+ goto Exhausted;
+ }
+ memmove(newflag, oldflag, nfd*sizeof(newflag[0]));
f->fd = newfd;
- free(oldfd);
- f->nfd += DELTAFD;
+ f->flag = newflag;
+ f->nfd = nfd+DELTAFD;
if(fd > f->maxfd){
if(fd/100 > f->maxfd/100)
f->exceed = (fd/100)*100;
f->maxfd = fd;
}
+ free(oldfd);
+ free(oldflag);
return 1;
}
@@ -72,9 +84,9 @@ findfreefd(Fgrp *f, int start)
}
int
-newfd(Chan *c)
+newfd(Chan *c, int mode)
{
- int fd;
+ int fd, flag;
Fgrp *f;
f = up->fgrp;
@@ -87,6 +99,13 @@ newfd(Chan *c)
if(fd > f->maxfd)
f->maxfd = fd;
f->fd[fd] = c;
+
+ /* per file-descriptor flags */
+ flag = 0;
+ if(mode & OCEXEC)
+ flag |= CCEXEC;
+ f->flag[fd] = flag;
+
unlockfgrp(f);
return fd;
}
@@ -112,6 +131,8 @@ newfd2(int fd[2], Chan *c[2])
f->maxfd = fd[1];
f->fd[fd[0]] = c[0];
f->fd[fd[1]] = c[1];
+ f->flag[fd[0]] = 0;
+ f->flag[fd[1]] = 0;
unlockfgrp(f);
return 0;
}
@@ -247,6 +268,7 @@ sysdup(va_list list)
oc = f->fd[fd];
f->fd[fd] = c;
+ f->flag[fd] = 0;
unlockfgrp(f);
if(oc != nil)
cclose(oc);
@@ -255,7 +277,7 @@ sysdup(va_list list)
cclose(c);
nexterror();
}
- fd = newfd(c);
+ fd = newfd(c, 0);
if(fd < 0)
error(Enofd);
poperror();
@@ -280,7 +302,7 @@ sysopen(va_list list)
cclose(c);
nexterror();
}
- fd = newfd(c);
+ fd = newfd(c, mode);
if(fd < 0)
error(Enofd);
poperror();
@@ -295,7 +317,7 @@ fdclose(int fd, int flag)
lock(f);
c = fd <= f->maxfd ? f->fd[fd] : nil;
- if(c == nil || (flag != 0 && (c->flag&flag) == 0)){
+ if(c == nil || (flag != 0 && ((f->flag[fd]|c->flag)&flag) == 0)){
unlock(f);
return;
}
@@ -1166,7 +1188,7 @@ syscreate(va_list list)
cclose(c);
nexterror();
}
- fd = newfd(c);
+ fd = newfd(c, mode);
if(fd < 0)
error(Enofd);
poperror();