Return to shmop.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / shmop |
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: */