diff options
author | Roland McGrath <roland@gnu.org> | 1998-12-30 06:50:40 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1998-12-30 06:50:40 +0000 |
commit | 426351562d55a06e490fad6a87cd7d0106280ab6 (patch) | |
tree | 68b935f19834e5fd0b2addcb7e00bfa3a4f9e4dc /libdiskfs/file-exec.c | |
parent | 05361f6e96c9b7abaca44e16cf38e9f8bc0475e2 (diff) |
1998-12-27 Roland McGrath <roland@baalperazim.frob.com>
Use a struct hurd_port for the cached exec server port,
so it is properly reference-counted and locked.
* boot-start.c (diskfs_exec): Variable removed.
(diskfs_start_bootstrap): Make it a local here.
Install that port in _diskfs_exec_portcell.
(diskfs_S_fsys_init): Use _diskfs_exec_portcell instead
of diskfs_exec.
* init-init.c (_diskfs_exec_portcell): New variable.
(diskfs_init_diskfs): Initialize it.
* priv.h: Declare it.
* diskfs.h (diskfs_exec, diskfs_exec_ctl): Remove decls.
* file-exec.c (diskfs_S_file_exec): Use _diskfs_exec_portcell instead
of diskfs_exec.
Diffstat (limited to 'libdiskfs/file-exec.c')
-rw-r--r-- | libdiskfs/file-exec.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/libdiskfs/file-exec.c b/libdiskfs/file-exec.c index 2933a7d4..521f3528 100644 --- a/libdiskfs/file-exec.c +++ b/libdiskfs/file-exec.c @@ -54,16 +54,31 @@ diskfs_S_file_exec (struct protid *cred, int suid, sgid; struct protid *newpi; error_t err = 0; + mach_port_t execserver; int cached_exec; + struct hurd_userlink ulink; +#define RETURN(code) do { err = (code); goto out; } while (0) if (!cred) return EOPNOTSUPP; - cached_exec = (diskfs_exec != MACH_PORT_NULL); - if (diskfs_exec == MACH_PORT_NULL) - diskfs_exec = file_name_lookup (_SERVERS_EXEC, 0, 0); /* XXX unlocked */ - if (diskfs_exec == MACH_PORT_NULL) - return EOPNOTSUPP; + /* Get a light reference to the cached exec server port. */ + execserver = _hurd_port_get (&_diskfs_exec_portcell, &ulink); + cached_exec = (execserver != MACH_PORT_NULL); + if (execserver == MACH_PORT_NULL) + { + /* No cached port. Look up the canonical naming point. */ + execserver = file_name_lookup (_SERVERS_EXEC, 0, 0); + if (execserver == MACH_PORT_NULL) + return EOPNOTSUPP; /* No exec server, no exec. */ + else + { + /* Install the newly-gotten exec server port for other + threads to use, then get a light reference for this call. */ + _hurd_port_set (&_diskfs_exec_portcell, execserver); + execserver = _hurd_port_get (&_diskfs_exec_portcell, &ulink); + } + } np = cred->po->np; @@ -74,17 +89,17 @@ diskfs_S_file_exec (struct protid *cred, mutex_unlock (&np->lock); if (_diskfs_noexec) - return EACCES; + RETURN (EACCES); if ((cred->po->openstat & O_EXEC) == 0) - return EBADF; + RETURN (EBADF); if (!((mode & (S_IXUSR|S_IXGRP|S_IXOTH)) || ((mode & S_IUSEUNK) && (mode & (S_IEXEC << S_IUNKSHIFT))))) - return EACCES; + RETURN (EACCES); if ((mode & S_IFMT) == S_IFDIR) - return EACCES; + RETURN (EACCES); suid = mode & S_ISUID; sgid = mode & S_ISGID; @@ -124,7 +139,7 @@ diskfs_S_file_exec (struct protid *cred, { do { - err = exec_exec (diskfs_exec, + err = exec_exec (execserver, ports_get_right (newpi), MACH_MSG_TYPE_MAKE_SEND, task, flags, argv, argvlen, envp, envplen, @@ -140,10 +155,17 @@ diskfs_S_file_exec (struct protid *cred, /* We were using a previously looked-up exec server port. Try looking up a new one before giving an error. */ cached_exec = 0; - mach_port_deallocate (mach_task_self (), diskfs_exec); - diskfs_exec = file_name_lookup (_SERVERS_EXEC, 0, 0); - if (diskfs_exec == MACH_PORT_NULL) + _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver); + + execserver = file_name_lookup (_SERVERS_EXEC, 0, 0); + if (execserver == MACH_PORT_NULL) err = EOPNOTSUPP; + else + { + _hurd_port_set (&_diskfs_exec_portcell, execserver); + execserver = _hurd_port_get (&_diskfs_exec_portcell, + &ulink); + } } else err = EOPNOTSUPP; @@ -163,5 +185,8 @@ diskfs_S_file_exec (struct protid *cred, mach_port_deallocate (mach_task_self (), portarray[i]); } + out: + _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver); + return err; } |