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>