Annotation of embedaddon/php/ext/shmop/shmop.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 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: shmop.c 321634 2012-01-01 13:15:04Z felipe $ */
! 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:
! 229: rsid = zend_list_insert(shmop, shm_type);
! 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>