diff options
Diffstat (limited to 'TSRM')
-rw-r--r-- | TSRM/tsrm_win32.c | 183 | ||||
-rw-r--r-- | TSRM/tsrm_win32.h | 70 |
2 files changed, 238 insertions, 15 deletions
diff --git a/TSRM/tsrm_win32.c b/TSRM/tsrm_win32.c index 5dfc2d60f8..daf7d606b1 100644 --- a/TSRM/tsrm_win32.c +++ b/TSRM/tsrm_win32.c @@ -23,6 +23,7 @@ #include <fcntl.h> #include <io.h> #include <process.h> +#include <time.h> #include "TSRM.h" @@ -39,15 +40,30 @@ static tsrm_win32_globals win32_globals; static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC) { globals->process = NULL; + globals->shm = NULL; globals->process_size = 0; + globals->shm_size = 0; globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com"); } static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC) { - if (globals->process != NULL) { + shm_pair *ptr; + + if (globals->process) { free(globals->process); } + + if (globals->shm) { + for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) { + UnmapViewOfFile(ptr->addr); + CloseHandle(ptr->segment); + UnmapViewOfFile(ptr->descriptor); + CloseHandle(ptr->info); + } + free(globals->shm); + } + free(globals->comspec); } @@ -67,10 +83,10 @@ TSRM_API void tsrm_win32_shutdown(void) #endif } -static ProcessPair* process_get(FILE *stream TSRMLS_DC) +static process_pair *process_get(FILE *stream TSRMLS_DC) { - ProcessPair* ptr; - ProcessPair* newptr; + process_pair *ptr; + process_pair *newptr; for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) { if (ptr->stream == stream) { @@ -82,7 +98,7 @@ static ProcessPair* process_get(FILE *stream TSRMLS_DC) return ptr; } - newptr = (ProcessPair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(ProcessPair)); + newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair)); if (newptr == NULL) { return NULL; } @@ -93,6 +109,38 @@ static ProcessPair* process_get(FILE *stream TSRMLS_DC) return ptr; } +static shm_pair *shm_get(int key, void *addr) +{ + shm_pair *ptr; + shm_pair *newptr; + TSRMLS_FETCH(); + + for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) { + if (!ptr->descriptor) { + continue; + } + if (!addr && ptr->descriptor->shm_perm.key == key) { + break; + } else if (ptr->addr == addr) { + break; + } + } + + if (ptr < (TWG(shm) + TWG(shm_size))) { + return ptr; + } + + newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair)); + if (newptr == NULL) { + return NULL; + } + + TWG(shm) = newptr; + ptr = newptr + TWG(shm_size); + TWG(shm_size)++; + return ptr; +} + static HANDLE dupHandle(HANDLE fh, BOOL inherit) { HANDLE copy, self = GetCurrentProcess(); if (!DuplicateHandle(self, fh, self, ©, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) { @@ -110,7 +158,7 @@ TSRM_API FILE *popen(const char *command, const char *type) SECURITY_ATTRIBUTES security; HANDLE in, out; char *cmd; - ProcessPair *proc; + process_pair *proc; TSRMLS_FETCH(); security.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -169,7 +217,7 @@ TSRM_API FILE *popen(const char *command, const char *type) TSRM_API int pclose(FILE *stream) { DWORD termstat = 0; - ProcessPair* process; + process_pair *process; TSRMLS_FETCH(); if ((process = process_get(stream TSRMLS_CC)) == NULL) { @@ -187,4 +235,125 @@ TSRM_API int pclose(FILE *stream) return termstat; } +TSRM_API int shmget(int key, int size, int flags) +{ + shm_pair *shm; + char shm_segment[26], shm_info[29]; + HANDLE shm_handle, info_handle; + BOOL created = FALSE; + + if (size < 0) { + return -1; + } + + sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key); + sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key); + + shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment); + info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info); + + if ((!shm_handle && !info_handle)) { + if (flags & IPC_EXCL) { + return -1; + } + if (flags & IPC_CREAT) { + shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment); + info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info); + created = TRUE; + } + if ((!shm_handle || !info_handle)) { + return -1; + } + } + + shm = shm_get(key, NULL); + shm->segment = shm_handle; + shm->info = info_handle; + shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL); + + if (created) { + shm->descriptor->shm_perm.key = key; + shm->descriptor->shm_segsz = size; + shm->descriptor->shm_ctime = time(NULL); + shm->descriptor->shm_cpid = getpid(); + shm->descriptor->shm_perm.mode = flags; + + shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0; + shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0; + shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0; + shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0; + shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0; + } + + if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) { + CloseHandle(shm->segment); + UnmapViewOfFile(shm->descriptor); + CloseHandle(shm->info); + return -1; + } + + return key; +} + +TSRM_API void *shmat(int key, const void *shmaddr, int flags) +{ + shm_pair *shm = shm_get(key, NULL); + + if (!shm->segment) { + return (void*)-1; + } + + shm->descriptor->shm_atime = time(NULL); + shm->descriptor->shm_lpid = getpid(); + shm->descriptor->shm_nattch++; + + shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL); + + return shm->addr; +} + +TSRM_API int shmdt(const void *shmaddr) +{ + shm_pair *shm = shm_get(0, (void*)shmaddr); + + if (!shm->segment) { + return -1; + } + + shm->descriptor->shm_dtime = time(NULL); + shm->descriptor->shm_lpid = getpid(); + shm->descriptor->shm_nattch--; + + return UnmapViewOfFile(shm->addr) ? 0 : -1; +} + +TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) { + shm_pair *shm = shm_get(key, NULL); + + if (!shm->segment) { + return -1; + } + + switch (cmd) { + case IPC_STAT: + memcpy(buf, shm->descriptor, sizeof(shm->descriptor)); + return 0; + + case IPC_SET: + shm->descriptor->shm_ctime = time(NULL); + shm->descriptor->shm_perm.uid = buf->shm_perm.uid; + shm->descriptor->shm_perm.gid = buf->shm_perm.gid; + shm->descriptor->shm_perm.mode = buf->shm_perm.mode; + return 0; + + case IPC_RMID: + if (shm->descriptor->shm_nattch < 1) { + shm->descriptor->shm_perm.key = -1; + } + return 0; + + default: + return -1; + } +} #endif
\ No newline at end of file diff --git a/TSRM/tsrm_win32.h b/TSRM/tsrm_win32.h index cb09786682..08e7c7a509 100644 --- a/TSRM/tsrm_win32.h +++ b/TSRM/tsrm_win32.h @@ -26,15 +26,45 @@ #ifdef TSRM_WIN32 #include <windows.h> +struct ipc_perm { + int key; + unsigned short uid; + unsigned short gid; + unsigned short cuid; + unsigned short cgid; + unsigned short mode; + unsigned short seq; +}; + +struct shmid_ds { + struct ipc_perm shm_perm; + int shm_segsz; + time_t shm_atime; + time_t shm_dtime; + time_t shm_ctime; + unsigned short shm_cpid; + unsigned short shm_lpid; + short shm_nattch; +}; + +typedef struct { + FILE *stream; + HANDLE prochnd; +} process_pair; + typedef struct { - FILE *stream; - HANDLE prochnd; -} ProcessPair; + void *addr; + HANDLE info; + HANDLE segment; + struct shmid_ds *descriptor; +} shm_pair; typedef struct { - ProcessPair *process; - int process_size; - char *comspec; + process_pair *process; + shm_pair *shm; + int process_size; + int shm_size; + char *comspec; } tsrm_win32_globals; #ifdef ZTS @@ -45,9 +75,33 @@ typedef struct { #endif +#define IPC_PRIVATE 0 +#define IPC_CREAT 00001000 +#define IPC_EXCL 00002000 +#define IPC_NOWAIT 00004000 + +#define IPC_RMID 0 +#define IPC_SET 1 +#define IPC_STAT 2 +#define IPC_INFO 3 + +#define SHM_R PAGE_READONLY +#define SHM_W PAGE_READWRITE + +#define SHM_RDONLY FILE_MAP_READ +#define SHM_RND FILE_MAP_WRITE +#define SHM_REMAP FILE_MAP_COPY + + TSRM_API void tsrm_win32_startup(void); TSRM_API void tsrm_win32_shutdown(void); -TSRM_API FILE* popen(const char *command, const char *type); -TSRM_API int pclose(FILE* stream); + +TSRM_API FILE *popen(const char *command, const char *type); +TSRM_API int pclose(FILE *stream); + +TSRM_API int shmget(int key, int size, int flags); +TSRM_API void *shmat(int key, const void *shmaddr, int flags); +TSRM_API int shmdt(const void *shmaddr); +TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf); #endif
\ No newline at end of file |