PageRenderTime 20ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/TSRM/tsrm_win32.c

http://php52-backports.googlecode.com/
C | 417 lines | 319 code | 77 blank | 21 comment | 70 complexity | db80a4216c7fcb13414b4e7e40877a52 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2010 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Daniel Beulshausen <daniel@php4win.de> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id: tsrm_win32.c 293036 2010-01-03 09:23:27Z sebastian $ */
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <io.h>
  22. #include <process.h>
  23. #include <time.h>
  24. #define TSRM_INCLUDE_FULL_WINDOWS_HEADERS
  25. #include "TSRM.h"
  26. #ifdef TSRM_WIN32
  27. #include "tsrm_win32.h"
  28. #ifdef ZTS
  29. static ts_rsrc_id win32_globals_id;
  30. #else
  31. static tsrm_win32_globals win32_globals;
  32. #endif
  33. static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
  34. {
  35. globals->process = NULL;
  36. globals->shm = NULL;
  37. globals->process_size = 0;
  38. globals->shm_size = 0;
  39. globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
  40. }
  41. static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
  42. {
  43. shm_pair *ptr;
  44. if (globals->process) {
  45. free(globals->process);
  46. }
  47. if (globals->shm) {
  48. for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
  49. UnmapViewOfFile(ptr->addr);
  50. CloseHandle(ptr->segment);
  51. UnmapViewOfFile(ptr->descriptor);
  52. CloseHandle(ptr->info);
  53. }
  54. free(globals->shm);
  55. }
  56. free(globals->comspec);
  57. }
  58. TSRM_API void tsrm_win32_startup(void)
  59. {
  60. #ifdef ZTS
  61. ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
  62. #else
  63. tsrm_win32_ctor(&win32_globals TSRMLS_CC);
  64. #endif
  65. }
  66. TSRM_API void tsrm_win32_shutdown(void)
  67. {
  68. #ifndef ZTS
  69. tsrm_win32_dtor(&win32_globals TSRMLS_CC);
  70. #endif
  71. }
  72. TSRM_API int tsrm_win32_access(const char *pathname, int mode)
  73. {
  74. if (mode == 1 /*X_OK*/) {
  75. #if 1
  76. /* This code is not supported by Windows 98,
  77. * but we don't support it anymore */
  78. DWORD type;
  79. return GetBinaryType(pathname, &type)?0:-1;
  80. #else
  81. SHFILEINFO sfi;
  82. return access(pathname, 0) == 0 &&
  83. SHGetFileInfo(pathname, 0, &sfi, sizeof(SHFILEINFO), SHGFI_EXETYPE) != 0 ? 0 : -1;
  84. #endif
  85. } else {
  86. return access(pathname, mode);
  87. }
  88. }
  89. static process_pair *process_get(FILE *stream TSRMLS_DC)
  90. {
  91. process_pair *ptr;
  92. process_pair *newptr;
  93. for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
  94. if (ptr->stream == stream) {
  95. break;
  96. }
  97. }
  98. if (ptr < (TWG(process) + TWG(process_size))) {
  99. return ptr;
  100. }
  101. newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
  102. if (newptr == NULL) {
  103. return NULL;
  104. }
  105. TWG(process) = newptr;
  106. ptr = newptr + TWG(process_size);
  107. TWG(process_size)++;
  108. return ptr;
  109. }
  110. static shm_pair *shm_get(int key, void *addr)
  111. {
  112. shm_pair *ptr;
  113. shm_pair *newptr;
  114. TSRMLS_FETCH();
  115. for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
  116. if (!ptr->descriptor) {
  117. continue;
  118. }
  119. if (!addr && ptr->descriptor->shm_perm.key == key) {
  120. break;
  121. } else if (ptr->addr == addr) {
  122. break;
  123. }
  124. }
  125. if (ptr < (TWG(shm) + TWG(shm_size))) {
  126. return ptr;
  127. }
  128. newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
  129. if (newptr == NULL) {
  130. return NULL;
  131. }
  132. TWG(shm) = newptr;
  133. ptr = newptr + TWG(shm_size);
  134. TWG(shm_size)++;
  135. return ptr;
  136. }
  137. static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
  138. HANDLE copy, self = GetCurrentProcess();
  139. if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
  140. return NULL;
  141. }
  142. return copy;
  143. }
  144. TSRM_API FILE *popen(const char *command, const char *type)
  145. {
  146. return popen_ex(command, type, NULL, NULL);
  147. }
  148. TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
  149. {
  150. FILE *stream = NULL;
  151. int fno, type_len = strlen(type), read, mode;
  152. STARTUPINFO startup;
  153. PROCESS_INFORMATION process;
  154. SECURITY_ATTRIBUTES security;
  155. HANDLE in, out;
  156. process_pair *proc;
  157. char *cmd;
  158. int i;
  159. char *ptype = (char *)type;
  160. TSRMLS_FETCH();
  161. if (!type) {
  162. return NULL;
  163. }
  164. /*The following two checks can be removed once we drop XP support */
  165. type_len = strlen(type);
  166. if (type_len <1 || type_len > 2) {
  167. return NULL;
  168. }
  169. for (i=0; i < type_len; i++) {
  170. if (!(*ptype == 'r' || *ptype == 'w' || *ptype == 'b' || *ptype == 't')) {
  171. return NULL;
  172. }
  173. ptype++;
  174. }
  175. security.nLength = sizeof(SECURITY_ATTRIBUTES);
  176. security.bInheritHandle = TRUE;
  177. security.lpSecurityDescriptor = NULL;
  178. if (!type_len || !CreatePipe(&in, &out, &security, 2048L)) {
  179. return NULL;
  180. }
  181. memset(&startup, 0, sizeof(STARTUPINFO));
  182. memset(&process, 0, sizeof(PROCESS_INFORMATION));
  183. startup.cb = sizeof(STARTUPINFO);
  184. startup.dwFlags = STARTF_USESTDHANDLES;
  185. startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  186. read = (type[0] == 'r') ? TRUE : FALSE;
  187. mode = ((type_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
  188. if (read) {
  189. in = dupHandle(in, FALSE);
  190. startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
  191. startup.hStdOutput = out;
  192. } else {
  193. out = dupHandle(out, FALSE);
  194. startup.hStdInput = in;
  195. startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  196. }
  197. cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c "));
  198. sprintf(cmd, "%s /c %s", TWG(comspec), command);
  199. if (!CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, env, cwd, &startup, &process)) {
  200. free(cmd);
  201. return NULL;
  202. }
  203. free(cmd);
  204. CloseHandle(process.hThread);
  205. proc = process_get(NULL TSRMLS_CC);
  206. if (read) {
  207. fno = _open_osfhandle((tsrm_intptr_t)in, _O_RDONLY | mode);
  208. CloseHandle(out);
  209. } else {
  210. fno = _open_osfhandle((tsrm_intptr_t)out, _O_WRONLY | mode);
  211. CloseHandle(in);
  212. }
  213. stream = _fdopen(fno, type);
  214. proc->prochnd = process.hProcess;
  215. proc->stream = stream;
  216. return stream;
  217. }
  218. TSRM_API int pclose(FILE *stream)
  219. {
  220. DWORD termstat = 0;
  221. process_pair *process;
  222. TSRMLS_FETCH();
  223. if ((process = process_get(stream TSRMLS_CC)) == NULL) {
  224. return 0;
  225. }
  226. fflush(process->stream);
  227. fclose(process->stream);
  228. WaitForSingleObject(process->prochnd, INFINITE);
  229. GetExitCodeProcess(process->prochnd, &termstat);
  230. process->stream = NULL;
  231. CloseHandle(process->prochnd);
  232. return termstat;
  233. }
  234. TSRM_API int shmget(int key, int size, int flags)
  235. {
  236. shm_pair *shm;
  237. char shm_segment[26], shm_info[29];
  238. HANDLE shm_handle, info_handle;
  239. BOOL created = FALSE;
  240. if (size < 0) {
  241. return -1;
  242. }
  243. sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
  244. sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key);
  245. shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
  246. info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
  247. if ((!shm_handle && !info_handle)) {
  248. if (flags & IPC_CREAT) {
  249. shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
  250. info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
  251. created = TRUE;
  252. }
  253. if ((!shm_handle || !info_handle)) {
  254. return -1;
  255. }
  256. } else {
  257. if (flags & IPC_EXCL) {
  258. return -1;
  259. }
  260. }
  261. shm = shm_get(key, NULL);
  262. shm->segment = shm_handle;
  263. shm->info = info_handle;
  264. shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
  265. if (created) {
  266. shm->descriptor->shm_perm.key = key;
  267. shm->descriptor->shm_segsz = size;
  268. shm->descriptor->shm_ctime = time(NULL);
  269. shm->descriptor->shm_cpid = getpid();
  270. shm->descriptor->shm_perm.mode = flags;
  271. shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0;
  272. shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0;
  273. shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0;
  274. shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0;
  275. shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
  276. }
  277. if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
  278. CloseHandle(shm->segment);
  279. UnmapViewOfFile(shm->descriptor);
  280. CloseHandle(shm->info);
  281. return -1;
  282. }
  283. return key;
  284. }
  285. TSRM_API void *shmat(int key, const void *shmaddr, int flags)
  286. {
  287. shm_pair *shm = shm_get(key, NULL);
  288. if (!shm->segment) {
  289. return (void*)-1;
  290. }
  291. shm->descriptor->shm_atime = time(NULL);
  292. shm->descriptor->shm_lpid = getpid();
  293. shm->descriptor->shm_nattch++;
  294. shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
  295. return shm->addr;
  296. }
  297. TSRM_API int shmdt(const void *shmaddr)
  298. {
  299. shm_pair *shm = shm_get(0, (void*)shmaddr);
  300. if (!shm->segment) {
  301. return -1;
  302. }
  303. shm->descriptor->shm_dtime = time(NULL);
  304. shm->descriptor->shm_lpid = getpid();
  305. shm->descriptor->shm_nattch--;
  306. return UnmapViewOfFile(shm->addr) ? 0 : -1;
  307. }
  308. TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
  309. shm_pair *shm = shm_get(key, NULL);
  310. if (!shm->segment) {
  311. return -1;
  312. }
  313. switch (cmd) {
  314. case IPC_STAT:
  315. memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
  316. return 0;
  317. case IPC_SET:
  318. shm->descriptor->shm_ctime = time(NULL);
  319. shm->descriptor->shm_perm.uid = buf->shm_perm.uid;
  320. shm->descriptor->shm_perm.gid = buf->shm_perm.gid;
  321. shm->descriptor->shm_perm.mode = buf->shm_perm.mode;
  322. return 0;
  323. case IPC_RMID:
  324. if (shm->descriptor->shm_nattch < 1) {
  325. shm->descriptor->shm_perm.key = -1;
  326. }
  327. return 0;
  328. default:
  329. return -1;
  330. }
  331. }
  332. TSRM_API char *realpath(char *orig_path, char *buffer)
  333. {
  334. int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
  335. if(!ret || ret > _MAX_PATH) {
  336. return NULL;
  337. }
  338. return buffer;
  339. }
  340. #endif