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