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>