diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2003-11-19 18:49:41 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2003-11-19 18:49:41 +0000 |
commit | 282113ba894449ed17e85b296cf0760d5206ac8d (patch) | |
tree | 830bd7ad49e085ea8cde78fea68848fbbca09880 /winsup/cygserver/shm.cc | |
parent | 64cfc6f213541f0e9e8e57011af8a56aca8c8216 (diff) | |
download | cygnal-282113ba894449ed17e85b296cf0760d5206ac8d.tar.gz cygnal-282113ba894449ed17e85b296cf0760d5206ac8d.tar.bz2 cygnal-282113ba894449ed17e85b296cf0760d5206ac8d.zip |
Don't use safe_new but new throughout. Fix copyright dates
throughout.
* Makefile.in: Accomodate all new files and name changes.
Add a *.d dependency.
(sbindir): Add.
(etcdir): Drop in favor of more appropriate sysconfdir definition.
(sysconfdir): Add.
(CXXFLAGS): Add -MMD flag. Add SYSCONFDIR definition.
(.SUFFIXES): Add.
(install): Add action items.
(libclean): New target.
(fullclean): Ditto.
* bsd_helper.cc: New file.
* bsd_helper.h: Ditto.
* bsd_log.cc: Ditto.
* bsd_log.h: Ditto.
* bsd_mutex.cc: Ditto.
* bsd_mutex.h: Ditto.
* client.cc: Rearrange to build as less as possible if
__INSIDE_CYGWIN__.
(client_request::handle_request): Add Message Queue and Semaphore
handling.
* cygserver.cc: Rearrange to build as less as possible if
__INSIDE_CYGWIN__. Use new debug/log/panic logging functions.
(DEF_CONFIG_FILE): New definition for configuration file. Use
throughout.
(getfunc): Remove.
(__cygserver__printf): Remove.
(client_request_attach_tty::serve): Return error if impersonation
fails.
(print_usage): Pump up help message.
(print_version): Add output of default configuration file.
(main): Accommodate new options. Allow overwrite of threading options
from config file. Call several new initialization functions. Drop
printing dots. Don't define SIGHANDLE inline.
* cygserver.conf: New file.
* cygserver_process.h: Rename to process.h.
* cygserver_transport.h: Rename to transport.h.
* cygserver_transport_pipes.h: Rename to transport_pipes.h.
* cygserver_transport_sockets.h: Rename to transport_sockets.h.
* msg.cc: Rewrite.
* sem.cc: Rewrite.
* shm.cc: Rewrite.
* sysv_msg.cc: New file, derived from FreeBSD version 1.52.
* sysv_sem.cc: New file, derived from FreeBSD version 1.66.
* sysv_shm.cc: New file, derived from FreeBSD version 1.89.
* threaded_queue.cc: Rearrange to build as less as possible if
__INSIDE_CYGWIN__.
* transport.cc (transport_layer_base::impersonate_client): Define bool.
(transport_layer_base::revert_to_self): Ditto.
* transport.h (transport_layer_base::impersonate_client): Declare bool.
(transport_layer_base::revert_to_self): Ditto.
* transport_pipes.cc (transport_layer_pipes::transport_layer_pipes):
Don't call init_security.
(init_security): Remove.
(transport_layer_pipes::accept): Use global sec_all_nih.
(transport_layer_pipes::connect): Ditto.
(transport_layer_pipes::impersonate_client): Define bool.
(transport_layer_pipes::revert_to_self): Ditt.
* transport_pipes.h (transport_layer_pipes::impersonate_client): Declare
bool.
(transport_layer_pipes::revert_to_self): Ditto.
* woutsup.h: Include bsd compatibility headers.
(SIGHANDLE): Add definition.
(__cygserver__printf): Remove definition.
(__noop_printf): Ditto.
(debug_printf): Define using debug.
(syscall_printf): Define using log.
(system_printf): Ditto.
Drop all other _printf definitions.
Diffstat (limited to 'winsup/cygserver/shm.cc')
-rw-r--r-- | winsup/cygserver/shm.cc | 918 |
1 files changed, 70 insertions, 848 deletions
diff --git a/winsup/cygserver/shm.cc b/winsup/cygserver/shm.cc index 50d2b6e1d..f73fd012a 100644 --- a/winsup/cygserver/shm.cc +++ b/winsup/cygserver/shm.cc @@ -1,9 +1,6 @@ -/* cygserver_shm.cc: Single unix specification IPC interface for Cygwin. +/* shm.cc: Single unix specification IPC interface for Cygwin. - Copyright 2002 Red Hat, Inc. - - Written by Conrad Scott <conrad.scott@dsl.pipex.com>. - Based on code by Robert Collins <robert.collins@hotmail.com>. + Copyright 2003 Red Hat, Inc. This file is part of Cygwin. @@ -11,824 +8,33 @@ This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ +#ifdef __OUTSIDE_CYGWIN__ #include "woutsup.h" #include <errno.h> #include <pthread.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <time.h> -#include "cygserver_ipc.h" -#include "cygserver_shm.h" -#include "security.h" - #include "cygserver.h" -#include "cygserver_process.h" -#include "cygserver_transport.h" - -/*---------------------------------------------------------------------------* - * class server_shmmgr - * - * A singleton class. - *---------------------------------------------------------------------------*/ - -#define shmmgr (server_shmmgr::instance ()) - -class server_shmmgr -{ -private: - class attach_t - { - public: - class process *const _client; - unsigned int _refcnt; - - attach_t *_next; - - attach_t (class process *const client) - : _client (client), - _refcnt (0), - _next (NULL) - {} - }; - - class segment_t - { - private: - // Bits for the _flg field. - enum { IS_DELETED = 0x01 }; - - public: - const int _intid; - const int _shmid; - struct shmid_ds _ds; - - segment_t *_next; - - segment_t (const key_t key, const int intid, const HANDLE hFileMap); - ~segment_t (); - - bool is_deleted () const - { - return _flg & IS_DELETED; - } - - bool is_pending_delete () const - { - return !_ds.shm_nattch && is_deleted (); - } - - void mark_deleted () - { - assert (!is_deleted ()); - - _flg |= IS_DELETED; - } - - int attach (class process *, HANDLE & hFileMap); - int detach (class process *); - - private: - static long _sequence; - - int _flg; - const HANDLE _hFileMap; - attach_t *_attach_head; // A list sorted by winpid; - - attach_t *find (const class process *, attach_t **previous = NULL); - }; - - class cleanup_t : public cleanup_routine - { - public: - cleanup_t (const segment_t *const segptr) - : cleanup_routine (reinterpret_cast<void *> (segptr->_shmid)) - { - assert (key ()); - } - - int shmid () const { return reinterpret_cast<int> (key ()); } - - virtual void cleanup (class process *const client) - { - const int res = shmmgr.shmdt (shmid (), client); - - if (res != 0) - debug_printf ("process cleanup failed [shmid = %d]: %s", - shmid (), strerror (-res)); - } - }; - -public: - static server_shmmgr & instance (); - - int shmat (HANDLE & hFileMap, - int shmid, int shmflg, class process *); - int shmctl (int & out_shmid, struct shmid_ds & out_ds, - struct shminfo & out_shminfo, struct shm_info & out_shm_info, - const int shmid, int cmd, const struct shmid_ds &, - class process *); - int shmdt (int shmid, class process *); - int shmget (int & out_shmid, key_t, size_t, int shmflg, uid_t, gid_t, - class process *); - -private: - static server_shmmgr *_instance; - static pthread_once_t _instance_once; - - static void initialise_instance (); - - CRITICAL_SECTION _segments_lock; - segment_t *_segments_head; // A list sorted by int_id. - - int _shm_ids; // Number of shm segments (for ipcs(8)). - int _shm_tot; // Total bytes of shm segments (for ipcs(8)). - int _shm_atts; // Number of attached segments (for ipcs(8)). - int _intid_max; // Highest intid yet allocated (for ipcs(8)). - - server_shmmgr (); - ~server_shmmgr (); - - // Undefined (as this class is a singleton): - server_shmmgr (const server_shmmgr &); - server_shmmgr & operator= (const server_shmmgr &); - - segment_t *find_by_key (key_t); - segment_t *find (int intid, segment_t **previous = NULL); - - int new_segment (key_t, size_t, int shmflg, pid_t, uid_t, gid_t); - - segment_t *new_segment (key_t, size_t, HANDLE); - void delete_segment (segment_t *); -}; - -/* static */ long server_shmmgr::segment_t::_sequence = 0; - -/* static */ server_shmmgr *server_shmmgr::_instance = NULL; -/* static */ pthread_once_t server_shmmgr::_instance_once = PTHREAD_ONCE_INIT; - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::segment_t () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t::segment_t (const key_t key, - const int intid, - const HANDLE hFileMap) - : _intid (intid), - _shmid (ipc_int2ext (intid, IPC_SHMOP, _sequence)), - _next (NULL), - _flg (0), - _hFileMap (hFileMap), - _attach_head (NULL) -{ - assert (0 <= _intid && _intid < SHMMNI); - - memset (&_ds, '\0', sizeof (_ds)); - _ds.shm_perm.key = key; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::~segment_t () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t::~segment_t () -{ - assert (!_attach_head); - - if (!CloseHandle (_hFileMap)) - syscall_printf ("failed to close file map [handle = 0x%x]: %E", _hFileMap); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::attach () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::segment_t::attach (class process *const client, - HANDLE & hFileMap) -{ - assert (client); - - if (!DuplicateHandle (GetCurrentProcess (), - _hFileMap, - client->handle (), - &hFileMap, - 0, - FALSE, // bInheritHandle - DUPLICATE_SAME_ACCESS)) - { - syscall_printf (("failed to duplicate handle for client " - "[key = 0x%016llx, shmid = %d, handle = 0x%x]: %E"), - _ds.shm_perm.key, _shmid, _hFileMap); - - return -EACCES; // FIXME: Case analysis? - } - - _ds.shm_lpid = client->cygpid (); - _ds.shm_nattch += 1; - _ds.shm_atime = time (NULL); // FIXME: sub-second times. - - attach_t *previous = NULL; - attach_t *attptr = find (client, &previous); - - if (!attptr) - { - attptr = safe_new (attach_t, client); - - if (previous) - { - attptr->_next = previous->_next; - previous->_next = attptr; - } - else - { - attptr->_next = _attach_head; - _attach_head = attptr; - } - } - - attptr->_refcnt += 1; - - cleanup_t *const cleanup = safe_new (cleanup_t, this); - - // FIXME: ::add should only fail if the process object is already - // cleaning up; but it can't be doing that since this thread has it - // locked. - - const bool result = client->add (cleanup); - - assert (result); - - return 0; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::detach () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::segment_t::detach (class process *const client) -{ - attach_t *previous = NULL; - attach_t *const attptr = find (client, &previous); - - if (!attptr) - return -EINVAL; - - if (client->is_active ()) - { - const cleanup_t key (this); - - if (!client->remove (&key)) - syscall_printf (("failed to remove cleanup routine for %d(%lu) " - "[shmid = %d]"), - client->cygpid (), client->winpid (), - _shmid); - } - - attptr->_refcnt -= 1; - - if (!attptr->_refcnt) - { - assert (previous ? previous->_next == attptr : _attach_head == attptr); - - if (previous) - previous->_next = attptr->_next; - else - _attach_head = attptr->_next; - - safe_delete (attptr); - } - - assert (_ds.shm_nattch > 0); - - _ds.shm_lpid = client->cygpid (); - _ds.shm_nattch -= 1; - _ds.shm_dtime = time (NULL); // FIXME: sub-second times. - - return 0; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::segment_t::find () - *---------------------------------------------------------------------------*/ - -server_shmmgr::attach_t * -server_shmmgr::segment_t::find (const class process *const client, - attach_t **previous) -{ - if (previous) - *previous = NULL; - - // Nb. The _attach_head list is sorted by winpid. - - for (attach_t *attptr = _attach_head; attptr; attptr = attptr->_next) - if (attptr->_client == client) - return attptr; - else if (attptr->_client->winpid () > client->winpid ()) - return NULL; - else if (previous) - *previous = attptr; - - return NULL; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::instance () - *---------------------------------------------------------------------------*/ - -/* static */ server_shmmgr & -server_shmmgr::instance () -{ - pthread_once (&_instance_once, &initialise_instance); - - assert (_instance); - - return *_instance; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmat () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmat (HANDLE & hFileMap, - const int shmid, const int shmflg, - class process *const client) -{ - syscall_printf ("shmat (shmid = %d, shmflg = 0%o) for %d(%lu)", - shmid, shmflg, client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP)); - - if (!segptr) - result = -EINVAL; - else - result = segptr->attach (client, hFileMap); - - if (!result) - _shm_atts += 1; - - LeaveCriticalSection (&_segments_lock); - - if (result < 0) - syscall_printf (("-1 [%d] = shmat (shmid = %d, shmflg = 0%o) " - "for %d(%lu)"), - -result, shmid, shmflg, - client->cygpid (), client->winpid ()); - else - syscall_printf (("0x%x = shmat (shmid = %d, shmflg = 0%o) " - "for %d(%lu)"), - hFileMap, shmid, shmflg, - client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmctl () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmctl (int & out_shmid, - struct shmid_ds & out_ds, - struct shminfo & out_shminfo, - struct shm_info & out_shm_info, - const int shmid, const int cmd, - const struct shmid_ds & ds, - class process *const client) -{ - syscall_printf ("shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)", - shmid, cmd, client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - switch (cmd) - { - case IPC_STAT: - case SHM_STAT: // Uses intids rather than shmids. - case IPC_SET: - case IPC_RMID: - { - int intid; - - if (cmd == SHM_STAT) - intid = shmid; - else - intid = ipc_ext2int (shmid, IPC_SHMOP); - - segment_t *const segptr = find (intid); - - if (!segptr) - result = -EINVAL; - else - switch (cmd) - { - case IPC_STAT: - out_ds = segptr->_ds; - break; - - case IPC_SET: - segptr->_ds.shm_perm.uid = ds.shm_perm.uid; - segptr->_ds.shm_perm.gid = ds.shm_perm.gid; - segptr->_ds.shm_perm.mode = ds.shm_perm.mode & 0777; - segptr->_ds.shm_lpid = client->cygpid (); - segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times. - break; - - case IPC_RMID: - if (segptr->is_deleted ()) - result = -EIDRM; - else - { - segptr->mark_deleted (); - if (segptr->is_pending_delete ()) - delete_segment (segptr); - } - break; - - case SHM_STAT: // ipcs(8) i'face. - out_ds = segptr->_ds; - out_shmid = segptr->_shmid; - break; - } - } - break; - - case IPC_INFO: - out_shminfo.shmmax = SHMMAX; - out_shminfo.shmmin = SHMMIN; - out_shminfo.shmmni = SHMMNI; - out_shminfo.shmseg = SHMSEG; - out_shminfo.shmall = SHMALL; - break; +#include "process.h" +#include "transport.h" - case SHM_INFO: // ipcs(8) i'face. - out_shmid = _intid_max; - out_shm_info.shm_ids = _shm_ids; - out_shm_info.shm_tot = _shm_tot; - out_shm_info.shm_atts = _shm_atts; - break; - - default: - result = -EINVAL; - break; - } - - LeaveCriticalSection (&_segments_lock); - - if (result < 0) - syscall_printf (("-1 [%d] = " - "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"), - -result, - shmid, cmd, client->cygpid (), client->winpid ()); - else - syscall_printf (("%d = " - "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"), - ((cmd == SHM_STAT || cmd == SHM_INFO) - ? out_shmid - : result), - shmid, cmd, client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmdt () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmdt (const int shmid, class process *const client) -{ - syscall_printf ("shmdt (shmid = %d) for %d(%lu)", - shmid, client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP)); - - if (!segptr) - result = -EINVAL; - else - result = segptr->detach (client); - - if (!result) - _shm_atts -= 1; - - if (!result && segptr->is_pending_delete ()) - delete_segment (segptr); - - LeaveCriticalSection (&_segments_lock); - - if (result < 0) - syscall_printf ("-1 [%d] = shmdt (shmid = %d) for %d(%lu)", - -result, shmid, client->cygpid (), client->winpid ()); - else - syscall_printf ("%d = shmdt (shmid = %d) for %d(%lu)", - result, shmid, client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::shmget () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::shmget (int & out_shmid, - const key_t key, const size_t size, const int shmflg, - const uid_t uid, const gid_t gid, - class process *const client) -{ - syscall_printf (("shmget (key = 0x%016llx, size = %u, shmflg = 0%o) " - "for %d(%lu)"), - key, size, shmflg, - client->cygpid (), client->winpid ()); - - int result = 0; - EnterCriticalSection (&_segments_lock); - - if (key == IPC_PRIVATE) - result = new_segment (key, size, shmflg, - client->cygpid (), uid, gid); - else - { - segment_t *const segptr = find_by_key (key); - - if (!segptr) - if (shmflg & IPC_CREAT) - result = new_segment (key, size, shmflg, - client->cygpid (), uid, gid); - else - result = -ENOENT; - else if (segptr->is_deleted ()) - result = -EIDRM; - else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) - result = -EEXIST; - else if ((shmflg & ~(segptr->_ds.shm_perm.mode)) & 0777) - result = -EACCES; - else if (size && segptr->_ds.shm_segsz < size) - result = -EINVAL; - else - result = segptr->_shmid; - } - - LeaveCriticalSection (&_segments_lock); - - if (result >= 0) - { - out_shmid = result; - result = 0; - } - - if (result < 0) - syscall_printf (("-1 [%d] = " - "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) " - "for %d(%lu)"), - -result, - key, size, shmflg, - client->cygpid (), client->winpid ()); - else - syscall_printf (("%d = " - "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) " - "for %d(%lu)"), - out_shmid, - key, size, shmflg, - client->cygpid (), client->winpid ()); - - return result; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::initialise_instance () - *---------------------------------------------------------------------------*/ - -/* static */ void -server_shmmgr::initialise_instance () -{ - assert (!_instance); - - _instance = safe_new0 (server_shmmgr); - - assert (_instance); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::server_shmmgr () - *---------------------------------------------------------------------------*/ - -server_shmmgr::server_shmmgr () - : _segments_head (NULL), - _shm_ids (0), - _shm_tot (0), - _shm_atts (0), - _intid_max (0) -{ - InitializeCriticalSection (&_segments_lock); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::~server_shmmgr () - *---------------------------------------------------------------------------*/ - -server_shmmgr::~server_shmmgr () -{ - DeleteCriticalSection (&_segments_lock); -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::find_by_key () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t * -server_shmmgr::find_by_key (const key_t key) -{ - for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next) - if (segptr->_ds.shm_perm.key == key) - return segptr; - - return NULL; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::find () - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t * -server_shmmgr::find (const int intid, segment_t **previous) -{ - if (previous) - *previous = NULL; - - for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next) - if (segptr->_intid == intid) - return segptr; - else if (segptr->_intid > intid) // The list is sorted by intid. - return NULL; - else if (previous) - *previous = segptr; - - return NULL; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::new_segment () - *---------------------------------------------------------------------------*/ - -int -server_shmmgr::new_segment (const key_t key, - const size_t size, - const int shmflg, - const pid_t cygpid, - const uid_t uid, - const gid_t gid) -{ - if (size < SHMMIN || size > SHMMAX) - return -EINVAL; - - const HANDLE hFileMap = CreateFileMapping (INVALID_HANDLE_VALUE, - NULL, PAGE_READWRITE, - 0, size, - NULL); - - if (!hFileMap) - { - syscall_printf ("failed to create file mapping [size = %lu]: %E", size); - return -ENOMEM; // FIXME - } - - segment_t *const segptr = new_segment (key, size, hFileMap); - - if (!segptr) - { - (void) CloseHandle (hFileMap); - return -ENOSPC; - } - - segptr->_ds.shm_perm.cuid = segptr->_ds.shm_perm.uid = uid; - segptr->_ds.shm_perm.cgid = segptr->_ds.shm_perm.gid = gid; - segptr->_ds.shm_perm.mode = shmflg & 0777; - segptr->_ds.shm_segsz = size; - segptr->_ds.shm_cpid = cygpid; - segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times. - - return segptr->_shmid; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::new_segment () - * - * Allocate a new segment for the given key and file map with the - * lowest available intid and insert into the segment map. - *---------------------------------------------------------------------------*/ - -server_shmmgr::segment_t * -server_shmmgr::new_segment (const key_t key, const size_t size, - const HANDLE hFileMap) -{ - // FIXME: Overflow risk. - if (_shm_tot + size > SHMALL) - return NULL; - - int intid = 0; // Next expected intid value. - segment_t *previous = NULL; // Insert pointer. - - // Find first unallocated intid. - for (segment_t *segptr = _segments_head; - segptr && segptr->_intid == intid; - segptr = segptr->_next, intid++) - { - previous = segptr; - } - - /* By the time this condition is reached (given the default value of - * SHMMNI), the linear searches should all replaced by something - * just a *little* cleverer . . . - */ - if (intid >= SHMMNI) - return NULL; - - segment_t *const segptr = safe_new (segment_t, key, intid, hFileMap); - - assert (segptr); - - if (previous) - { - segptr->_next = previous->_next; - previous->_next = segptr; - } - else - { - segptr->_next = _segments_head; - _segments_head = segptr; - } - - _shm_ids += 1; - _shm_tot += size; - if (intid > _intid_max) - _intid_max = intid; - - return segptr; -} - -/*---------------------------------------------------------------------------* - * server_shmmgr::delete_segment () - *---------------------------------------------------------------------------*/ - -void -server_shmmgr::delete_segment (segment_t *const segptr) -{ - assert (segptr); - assert (segptr->is_pending_delete ()); - - segment_t *previous = NULL; - - const segment_t *const tmp = find (segptr->_intid, &previous); - - assert (tmp == segptr); - assert (previous ? previous->_next == segptr : _segments_head == segptr); - - if (previous) - previous->_next = segptr->_next; - else - _segments_head = segptr->_next; - - assert (_shm_ids > 0); - _shm_ids -= 1; - _shm_tot -= segptr->_ds.shm_segsz; - - safe_delete (segptr); -} - -/*---------------------------------------------------------------------------* - * client_request_shm::client_request_shm () - *---------------------------------------------------------------------------*/ +#include "cygserver_ipc.h" +#include "cygserver_shm.h" client_request_shm::client_request_shm () : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters)) -{ - // verbose: syscall_printf ("created"); +{ } -/*---------------------------------------------------------------------------* - * client_request_shm::serve () - *---------------------------------------------------------------------------*/ - void client_request_shm::serve (transport_layer_base *const conn, - process_cache *const cache) + process_cache *const cache) { - assert (conn); - - assert (!error_code ()); - if (msglen () != sizeof (_parameters.in)) { syscall_printf ("bad request body length: expecting %lu bytes, got %lu", @@ -837,60 +43,76 @@ client_request_shm::serve (transport_layer_base *const conn, msglen (0); return; } - - // FIXME: Get a return code out of this and don't continue on error. - conn->impersonate_client (); - - class process *const client = cache->process (_parameters.in.cygpid, - _parameters.in.winpid); - + if (support_sharedmem == TUN_FALSE) + { + syscall_printf ("Shared memory support not started"); + error_code (ENOSYS); + if (_parameters.in.shmop == SHMOP_shmat) + _parameters.out.ptr = (vm_offset_t)0; + else + _parameters.out.ret = -1; + msglen (sizeof (_parameters.out)); + return; + } + process *const client = cache->process (_parameters.in.ipcblk.cygpid, + _parameters.in.ipcblk.winpid); if (!client) { error_code (EAGAIN); msglen (0); return; } - - int result = -EINVAL; - - switch (_parameters.in.shmop) + if (!conn->impersonate_client ()) { - case SHMOP_shmget: - result = shmmgr.shmget (_parameters.out.shmid, - _parameters.in.key, _parameters.in.size, - _parameters.in.shmflg, - _parameters.in.uid, _parameters.in.gid, - client); - break; - - case SHMOP_shmat: - result = shmmgr.shmat (_parameters.out.hFileMap, - _parameters.in.shmid, _parameters.in.shmflg, - client); - break; - - case SHMOP_shmdt: - result = shmmgr.shmdt (_parameters.in.shmid, client); - break; - - case SHMOP_shmctl: - result = shmmgr.shmctl (_parameters.out.shmid, - _parameters.out.ds, _parameters.out.shminfo, - _parameters.out.shm_info, - _parameters.in.shmid, _parameters.in.cmd, - _parameters.in.ds, - client); - break; + client->release (); + error_code (EACCES); + msglen (0); + return; } - - client->release (); - conn->revert_to_self (); - - if (result < 0) + if (!adjust_identity_info (&_parameters.in.ipcblk)) { - error_code (-result); + client->release (); + conn->revert_to_self (); + error_code (EACCES); msglen (0); + return; } + /* Early revert_to_self since IPC code runs in kernel mode. */ + conn->revert_to_self (); + thread td = { client, &_parameters.in.ipcblk, {0, 0} }; + int res; + shmop_t shmop = _parameters.in.shmop; /* Get's overwritten otherwise. */ + switch (shmop) + { + case SHMOP_shmat: + ipc_p_vmspace (td.ipcblk); + res = shmat (&td, &_parameters.in.atargs); + break; + case SHMOP_shmctl: + res = shmctl (&td, &_parameters.in.ctlargs); + break; + case SHMOP_shmdt: + ipc_p_vmspace (td.ipcblk); + res = shmdt (&td, &_parameters.in.dtargs); + break; + case SHMOP_shmget: + res = shmget (&td, &_parameters.in.getargs); + break; + case SHMOP_shmfork: + res = cygwin_shmfork_myhook (&td, &_parameters.in.forkargs); + break; + } + /* Allocated by the call to adjust_identity_info(). */ + if (_parameters.in.ipcblk.gidlist) + free (_parameters.in.ipcblk.gidlist); + client->release (); + error_code (res); + if (shmop == SHMOP_shmat) + _parameters.out.ptr = td.td_retval[0]; else - msglen (sizeof (_parameters.out)); + _parameters.out.ret = td.td_retval[0]; + if (shmop == SHMOP_shmget) + _parameters.out.obj = td.td_retval[1]; + msglen (sizeof (_parameters.out)); } +#endif /* __OUTSIDE_CYGWIN__ */ |