File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / shmop / shmop.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:55 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    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: shmop.c,v 1.1.1.4 2014/06/15 20:03:55 misho Exp $ */
   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 TSRMLS_CC);
  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>