PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/release/src/router/php/ext/shmop/shmop.c

https://gitlab.com/envieidoc/advancedtomato2
C | 377 lines | 247 code | 64 blank | 66 comment | 36 complexity | dc94b75d21dd7eb88068564378d7c550 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2014 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: Slava Poliakov <hackie@prohost.org> |
  16. | Ilia Alshanetsky <ilia@prohost.org> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include "php.h"
  24. #include "php_ini.h"
  25. #include "php_shmop.h"
  26. # ifndef PHP_WIN32
  27. # include <sys/ipc.h>
  28. # include <sys/shm.h>
  29. #else
  30. #include "tsrm_win32.h"
  31. #endif
  32. #if HAVE_SHMOP
  33. #include "ext/standard/info.h"
  34. #ifdef ZTS
  35. int shmop_globals_id;
  36. #else
  37. php_shmop_globals shmop_globals;
  38. #endif
  39. int shm_type;
  40. /* {{{ arginfo */
  41. ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_open, 0, 0, 4)
  42. ZEND_ARG_INFO(0, key)
  43. ZEND_ARG_INFO(0, flags)
  44. ZEND_ARG_INFO(0, mode)
  45. ZEND_ARG_INFO(0, size)
  46. ZEND_END_ARG_INFO()
  47. ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_read, 0, 0, 3)
  48. ZEND_ARG_INFO(0, shmid)
  49. ZEND_ARG_INFO(0, start)
  50. ZEND_ARG_INFO(0, count)
  51. ZEND_END_ARG_INFO()
  52. ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_close, 0, 0, 1)
  53. ZEND_ARG_INFO(0, shmid)
  54. ZEND_END_ARG_INFO()
  55. ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_size, 0, 0, 1)
  56. ZEND_ARG_INFO(0, shmid)
  57. ZEND_END_ARG_INFO()
  58. ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_write, 0, 0, 3)
  59. ZEND_ARG_INFO(0, shmid)
  60. ZEND_ARG_INFO(0, data)
  61. ZEND_ARG_INFO(0, offset)
  62. ZEND_END_ARG_INFO()
  63. ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_delete, 0, 0, 1)
  64. ZEND_ARG_INFO(0, shmid)
  65. ZEND_END_ARG_INFO()
  66. /* }}} */
  67. /* {{{ shmop_functions[]
  68. */
  69. const zend_function_entry shmop_functions[] = {
  70. PHP_FE(shmop_open, arginfo_shmop_open)
  71. PHP_FE(shmop_read, arginfo_shmop_read)
  72. PHP_FE(shmop_close, arginfo_shmop_close)
  73. PHP_FE(shmop_size, arginfo_shmop_size)
  74. PHP_FE(shmop_write, arginfo_shmop_write)
  75. PHP_FE(shmop_delete, arginfo_shmop_delete)
  76. PHP_FE_END
  77. };
  78. /* }}} */
  79. /* {{{ shmop_module_entry
  80. */
  81. zend_module_entry shmop_module_entry = {
  82. STANDARD_MODULE_HEADER,
  83. "shmop",
  84. shmop_functions,
  85. PHP_MINIT(shmop),
  86. NULL,
  87. NULL,
  88. NULL,
  89. PHP_MINFO(shmop),
  90. NO_VERSION_YET,
  91. STANDARD_MODULE_PROPERTIES
  92. };
  93. /* }}} */
  94. #ifdef COMPILE_DL_SHMOP
  95. ZEND_GET_MODULE(shmop)
  96. #endif
  97. #define PHP_SHMOP_GET_RES \
  98. shmop = zend_list_find(shmid, &type); \
  99. if (!shmop) { \
  100. php_error_docref(NULL TSRMLS_CC, E_WARNING, "no shared memory segment with an id of [%lu]", shmid); \
  101. RETURN_FALSE; \
  102. } else if (type != shm_type) { \
  103. php_error_docref(NULL TSRMLS_CC, E_WARNING, "not a shmop resource"); \
  104. RETURN_FALSE; \
  105. } \
  106. /* {{{ rsclean
  107. */
  108. static void rsclean(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  109. {
  110. struct php_shmop *shmop = (struct php_shmop *)rsrc->ptr;
  111. shmdt(shmop->addr);
  112. efree(shmop);
  113. }
  114. /* }}} */
  115. /* {{{ PHP_MINIT_FUNCTION
  116. */
  117. PHP_MINIT_FUNCTION(shmop)
  118. {
  119. shm_type = zend_register_list_destructors_ex(rsclean, NULL, "shmop", module_number);
  120. return SUCCESS;
  121. }
  122. /* }}} */
  123. /* {{{ PHP_MINFO_FUNCTION
  124. */
  125. PHP_MINFO_FUNCTION(shmop)
  126. {
  127. php_info_print_table_start();
  128. php_info_print_table_row(2, "shmop support", "enabled");
  129. php_info_print_table_end();
  130. }
  131. /* }}} */
  132. /* {{{ proto int shmop_open (int key, string flags, int mode, int size)
  133. gets and attaches a shared memory segment */
  134. PHP_FUNCTION(shmop_open)
  135. {
  136. long key, mode, size;
  137. struct php_shmop *shmop;
  138. struct shmid_ds shm;
  139. int rsid;
  140. char *flags;
  141. int flags_len;
  142. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsll", &key, &flags, &flags_len, &mode, &size) == FAILURE) {
  143. return;
  144. }
  145. if (flags_len != 1) {
  146. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a valid flag", flags);
  147. RETURN_FALSE;
  148. }
  149. shmop = emalloc(sizeof(struct php_shmop));
  150. memset(shmop, 0, sizeof(struct php_shmop));
  151. shmop->key = key;
  152. shmop->shmflg |= mode;
  153. switch (flags[0])
  154. {
  155. case 'a':
  156. shmop->shmatflg |= SHM_RDONLY;
  157. break;
  158. case 'c':
  159. shmop->shmflg |= IPC_CREAT;
  160. shmop->size = size;
  161. break;
  162. case 'n':
  163. shmop->shmflg |= (IPC_CREAT | IPC_EXCL);
  164. shmop->size = size;
  165. break;
  166. case 'w':
  167. /* noop
  168. shm segment is being opened for read & write
  169. will fail if segment does not exist
  170. */
  171. break;
  172. default:
  173. php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid access mode");
  174. goto err;
  175. }
  176. if (shmop->shmflg & IPC_CREAT && shmop->size < 1) {
  177. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Shared memory segment size must be greater than zero");
  178. goto err;
  179. }
  180. shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg);
  181. if (shmop->shmid == -1) {
  182. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to attach or create shared memory segment");
  183. goto err;
  184. }
  185. if (shmctl(shmop->shmid, IPC_STAT, &shm)) {
  186. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to get shared memory segment information");
  187. goto err;
  188. }
  189. shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg);
  190. if (shmop->addr == (char*) -1) {
  191. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to attach to shared memory segment");
  192. goto err;
  193. }
  194. shmop->size = shm.shm_segsz;
  195. rsid = zend_list_insert(shmop, shm_type TSRMLS_CC);
  196. RETURN_LONG(rsid);
  197. err:
  198. efree(shmop);
  199. RETURN_FALSE;
  200. }
  201. /* }}} */
  202. /* {{{ proto string shmop_read (int shmid, int start, int count)
  203. reads from a shm segment */
  204. PHP_FUNCTION(shmop_read)
  205. {
  206. long shmid, start, count;
  207. struct php_shmop *shmop;
  208. int type;
  209. char *startaddr;
  210. int bytes;
  211. char *return_string;
  212. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &shmid, &start, &count) == FAILURE) {
  213. return;
  214. }
  215. PHP_SHMOP_GET_RES
  216. if (start < 0 || start > shmop->size) {
  217. php_error_docref(NULL TSRMLS_CC, E_WARNING, "start is out of range");
  218. RETURN_FALSE;
  219. }
  220. if (count < 0 || start > (INT_MAX - count) || start + count > shmop->size) {
  221. php_error_docref(NULL TSRMLS_CC, E_WARNING, "count is out of range");
  222. RETURN_FALSE;
  223. }
  224. startaddr = shmop->addr + start;
  225. bytes = count ? count : shmop->size - start;
  226. return_string = emalloc(bytes+1);
  227. memcpy(return_string, startaddr, bytes);
  228. return_string[bytes] = 0;
  229. RETURN_STRINGL(return_string, bytes, 0);
  230. }
  231. /* }}} */
  232. /* {{{ proto void shmop_close (int shmid)
  233. closes a shared memory segment */
  234. PHP_FUNCTION(shmop_close)
  235. {
  236. long shmid;
  237. struct php_shmop *shmop;
  238. int type;
  239. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &shmid) == FAILURE) {
  240. return;
  241. }
  242. PHP_SHMOP_GET_RES
  243. zend_list_delete(shmid);
  244. }
  245. /* }}} */
  246. /* {{{ proto int shmop_size (int shmid)
  247. returns the shm size */
  248. PHP_FUNCTION(shmop_size)
  249. {
  250. long shmid;
  251. struct php_shmop *shmop;
  252. int type;
  253. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &shmid) == FAILURE) {
  254. return;
  255. }
  256. PHP_SHMOP_GET_RES
  257. RETURN_LONG(shmop->size);
  258. }
  259. /* }}} */
  260. /* {{{ proto int shmop_write (int shmid, string data, int offset)
  261. writes to a shared memory segment */
  262. PHP_FUNCTION(shmop_write)
  263. {
  264. struct php_shmop *shmop;
  265. int type;
  266. int writesize;
  267. long shmid, offset;
  268. char *data;
  269. int data_len;
  270. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsl", &shmid, &data, &data_len, &offset) == FAILURE) {
  271. return;
  272. }
  273. PHP_SHMOP_GET_RES
  274. if ((shmop->shmatflg & SHM_RDONLY) == SHM_RDONLY) {
  275. php_error_docref(NULL TSRMLS_CC, E_WARNING, "trying to write to a read only segment");
  276. RETURN_FALSE;
  277. }
  278. if (offset < 0 || offset > shmop->size) {
  279. php_error_docref(NULL TSRMLS_CC, E_WARNING, "offset out of range");
  280. RETURN_FALSE;
  281. }
  282. writesize = (data_len < shmop->size - offset) ? data_len : shmop->size - offset;
  283. memcpy(shmop->addr + offset, data, writesize);
  284. RETURN_LONG(writesize);
  285. }
  286. /* }}} */
  287. /* {{{ proto bool shmop_delete (int shmid)
  288. mark segment for deletion */
  289. PHP_FUNCTION(shmop_delete)
  290. {
  291. long shmid;
  292. struct php_shmop *shmop;
  293. int type;
  294. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &shmid) == FAILURE) {
  295. return;
  296. }
  297. PHP_SHMOP_GET_RES
  298. if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
  299. php_error_docref(NULL TSRMLS_CC, E_WARNING, "can't mark segment for deletion (are you the owner?)");
  300. RETURN_FALSE;
  301. }
  302. RETURN_TRUE;
  303. }
  304. /* }}} */
  305. #endif /* HAVE_SHMOP */
  306. /*
  307. * Local variables:
  308. * tab-width: 4
  309. * c-basic-offset: 4
  310. * End:
  311. * vim600: sw=4 ts=4 fdm=marker
  312. * vim<600: sw=4 ts=4
  313. */