PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/sysvshm - sysvshm.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 113 134 84.3 %
Date: 2015-03-20 Functions: 11 12 91.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2015 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             :    | Author: Christian Cartus <cartus@atrior.de>                          |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : /* This has been built and tested on Linux 2.2.14
      22             :  *
      23             :  * This has been built and tested on Solaris 2.6.
      24             :  * It may not compile or execute correctly on other systems.
      25             :  */
      26             : 
      27             : #ifdef HAVE_CONFIG_H
      28             : #include "config.h"
      29             : #endif
      30             : 
      31             : #include "php.h"
      32             : 
      33             : #if HAVE_SYSVSHM
      34             : 
      35             : #include <errno.h>
      36             : 
      37             : #include "php_sysvshm.h"
      38             : #include "ext/standard/php_var.h"
      39             : #include "zend_smart_str.h"
      40             : #include "php_ini.h"
      41             : 
      42             : /* {{{ arginfo */
      43             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_attach, 0, 0, 1)
      44             :         ZEND_ARG_INFO(0, key)
      45             :         ZEND_ARG_INFO(0, memsize)
      46             :         ZEND_ARG_INFO(0, perm)
      47             : ZEND_END_ARG_INFO()
      48             : 
      49             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_detach, 0, 0, 1)
      50             :         ZEND_ARG_INFO(0, shm_identifier)
      51             : ZEND_END_ARG_INFO()
      52             : 
      53             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_has_var, 0, 0, 2)
      54             :         ZEND_ARG_INFO(0, id)
      55             :         ZEND_ARG_INFO(0, variable_key)
      56             : ZEND_END_ARG_INFO()
      57             : 
      58             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_remove, 0, 0, 1)
      59             :         ZEND_ARG_INFO(0, shm_identifier)
      60             : ZEND_END_ARG_INFO()
      61             : 
      62             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_put_var, 0, 0, 3)
      63             :         ZEND_ARG_INFO(0, shm_identifier)
      64             :         ZEND_ARG_INFO(0, variable_key)
      65             :         ZEND_ARG_INFO(0, variable)
      66             : ZEND_END_ARG_INFO()
      67             : 
      68             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_get_var, 0, 0, 2)
      69             :         ZEND_ARG_INFO(0, id)
      70             :         ZEND_ARG_INFO(0, variable_key)
      71             : ZEND_END_ARG_INFO()
      72             : 
      73             : ZEND_BEGIN_ARG_INFO_EX(arginfo_shm_remove_var, 0, 0, 2)
      74             :         ZEND_ARG_INFO(0, id)
      75             :         ZEND_ARG_INFO(0, variable_key)
      76             : ZEND_END_ARG_INFO()
      77             : /* }}} */
      78             : 
      79             : /* {{{ sysvshm_functions[]
      80             :  */
      81             : const zend_function_entry sysvshm_functions[] = {
      82             :         PHP_FE(shm_attach,              arginfo_shm_attach)
      83             :         PHP_FE(shm_remove,              arginfo_shm_detach)
      84             :         PHP_FE(shm_detach,              arginfo_shm_remove)
      85             :         PHP_FE(shm_put_var,             arginfo_shm_put_var)
      86             :         PHP_FE(shm_has_var,             arginfo_shm_has_var)
      87             :         PHP_FE(shm_get_var,             arginfo_shm_get_var)
      88             :         PHP_FE(shm_remove_var,  arginfo_shm_remove_var)
      89             :         PHP_FE_END
      90             : };
      91             : /* }}} */
      92             : 
      93             : /* {{{ sysvshm_module_entry
      94             :  */
      95             : zend_module_entry sysvshm_module_entry = {
      96             :         STANDARD_MODULE_HEADER,
      97             :         "sysvshm",
      98             :         sysvshm_functions,
      99             :         PHP_MINIT(sysvshm),
     100             :         NULL,
     101             :         NULL,
     102             :         NULL,
     103             :         NULL,
     104             :         NO_VERSION_YET,
     105             :         STANDARD_MODULE_PROPERTIES
     106             : };
     107             : /* }}} */
     108             : 
     109             : #ifdef COMPILE_DL_SYSVSHM
     110             : ZEND_GET_MODULE(sysvshm)
     111             : #endif
     112             : 
     113             : #undef shm_ptr                                  /* undefine AIX-specific macro */
     114             : 
     115             : #define SHM_FETCH_RESOURCE(shm_ptr, z_ptr) do { \
     116             :         if ((shm_ptr = (sysvshm_shm *)zend_fetch_resource(Z_RES_P(z_ptr), PHP_SHM_RSRC_NAME, php_sysvshm.le_shm)) == NULL) { \
     117             :                 RETURN_FALSE; \
     118             :         } \
     119             : } while (0)
     120             : 
     121             : THREAD_LS sysvshm_module php_sysvshm;
     122             : 
     123             : static int php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const char *data, zend_long len);
     124             : static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key);
     125             : static int php_remove_shm_data(sysvshm_chunk_head *ptr, zend_long shm_varpos);
     126             : 
     127             : /* {{{ php_release_sysvshm
     128             :  */
     129          12 : static void php_release_sysvshm(zend_resource *rsrc)
     130             : {
     131          12 :         sysvshm_shm *shm_ptr = (sysvshm_shm *) rsrc->ptr;
     132          12 :         shmdt((void *) shm_ptr->ptr);
     133          12 :         efree(shm_ptr);
     134          12 : }
     135             : /* }}} */
     136             : 
     137             : /* {{{ PHP_MINIT_FUNCTION
     138             :  */
     139       20871 : PHP_MINIT_FUNCTION(sysvshm)
     140             : {
     141       20871 :         php_sysvshm.le_shm = zend_register_list_destructors_ex(php_release_sysvshm, NULL, PHP_SHM_RSRC_NAME, module_number);
     142             : 
     143       20871 :         if (cfg_get_long("sysvshm.init_mem", &php_sysvshm.init_mem) == FAILURE) {
     144       20871 :                 php_sysvshm.init_mem=10000;
     145             :         }
     146       20871 :         return SUCCESS;
     147             : }
     148             : /* }}} */
     149             : 
     150             : /* {{{ proto int shm_attach(int key [, int memsize [, int perm]])
     151             :    Creates or open a shared memory segment */
     152          19 : PHP_FUNCTION(shm_attach)
     153             : {
     154             :         sysvshm_shm *shm_list_ptr;
     155             :         char *shm_ptr;
     156             :         sysvshm_chunk_head *chunk_ptr;
     157          19 :         zend_long shm_key, shm_id, shm_size = php_sysvshm.init_mem, shm_flag = 0666;
     158             : 
     159          19 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &shm_key, &shm_size, &shm_flag)) {
     160           2 :                 return;
     161             :         }
     162             : 
     163          17 :         if (shm_size < 1) {
     164           5 :                 php_error_docref(NULL, E_WARNING, "Segment size must be greater than zero");
     165           5 :                 RETURN_FALSE;
     166             :         }
     167             : 
     168          12 :         shm_list_ptr = (sysvshm_shm *) emalloc(sizeof(sysvshm_shm));
     169             : 
     170             :         /* get the id from a specified key or create new shared memory */
     171          12 :         if ((shm_id = shmget(shm_key, 0, 0)) < 0) {
     172           9 :                 if (shm_size < sizeof(sysvshm_chunk_head)) {
     173           0 :                         php_error_docref(NULL, E_WARNING, "failed for key 0x%px: memorysize too small", shm_key);
     174           0 :                         efree(shm_list_ptr);
     175           0 :                         RETURN_FALSE;
     176             :                 }
     177           9 :                 if ((shm_id = shmget(shm_key, shm_size, shm_flag | IPC_CREAT | IPC_EXCL)) < 0) {
     178           0 :                         php_error_docref(NULL, E_WARNING, "failed for key 0x%px: %s", shm_key, strerror(errno));
     179           0 :                         efree(shm_list_ptr);
     180           0 :                         RETURN_FALSE;
     181             :                 }
     182             :         }
     183             : 
     184          12 :         if ((shm_ptr = shmat(shm_id, NULL, 0)) == (void *) -1) {
     185           0 :                 php_error_docref(NULL, E_WARNING, "failed for key 0x%px: %s", shm_key, strerror(errno));
     186           0 :                 efree(shm_list_ptr);
     187           0 :                 RETURN_FALSE;
     188             :         }
     189             : 
     190             :         /* check if shm is already initialized */
     191          12 :         chunk_ptr = (sysvshm_chunk_head *) shm_ptr;
     192          12 :         if (strcmp((char*) &(chunk_ptr->magic), "PHP_SM") != 0) {
     193           9 :                 strcpy((char*) &(chunk_ptr->magic), "PHP_SM");
     194           9 :                 chunk_ptr->start = sizeof(sysvshm_chunk_head);
     195           9 :                 chunk_ptr->end = chunk_ptr->start;
     196           9 :                 chunk_ptr->total = shm_size;
     197           9 :                 chunk_ptr->free = shm_size-chunk_ptr->end;
     198             :         }
     199             : 
     200          12 :         shm_list_ptr->key = shm_key;
     201          12 :         shm_list_ptr->id = shm_id;
     202          12 :         shm_list_ptr->ptr = chunk_ptr;
     203             : 
     204          12 :         RETURN_RES(zend_register_resource(shm_list_ptr, php_sysvshm.le_shm));
     205             : }
     206             : /* }}} */
     207             : 
     208             : /* {{{ proto bool shm_detach(resource shm_identifier)
     209             :    Disconnects from shared memory segment */
     210           8 : PHP_FUNCTION(shm_detach)
     211             : {
     212             :         zval *shm_id;
     213             :         sysvshm_shm *shm_list_ptr;
     214             : 
     215           8 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shm_id)) {
     216           5 :                 return;
     217             :         }
     218           3 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     219           2 :         RETURN_BOOL(SUCCESS == zend_list_close(Z_RES_P(shm_id)));
     220             : }
     221             : /* }}} */
     222             : 
     223             : /* {{{ proto bool shm_remove(resource shm_identifier)
     224             :    Removes shared memory from Unix systems */
     225          20 : PHP_FUNCTION(shm_remove)
     226             : {
     227             :         zval *shm_id;
     228             :         sysvshm_shm *shm_list_ptr;
     229             : 
     230          20 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shm_id)) {
     231           7 :                 return;
     232             :         }
     233          13 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     234             : 
     235          11 :         if (shmctl(shm_list_ptr->id, IPC_RMID, NULL) < 0) {
     236           0 :                 php_error_docref(NULL, E_WARNING, "failed for key 0x%x, id %ld: %s", shm_list_ptr->key, Z_LVAL_P(shm_id), strerror(errno));
     237           0 :                 RETURN_FALSE;
     238             :         }
     239             : 
     240          11 :         RETURN_TRUE;
     241             : }
     242             : /* }}} */
     243             : 
     244             : /* {{{ proto bool shm_put_var(resource shm_identifier, int variable_key, mixed variable)
     245             :    Inserts or updates a variable in shared memory */
     246          18 : PHP_FUNCTION(shm_put_var)
     247             : {
     248             :         zval *shm_id, *arg_var;
     249             :         int ret;
     250             :         zend_long shm_key;
     251             :         sysvshm_shm *shm_list_ptr;
     252          18 :         smart_str shm_var = {0};
     253             :         php_serialize_data_t var_hash;
     254             : 
     255          18 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &shm_id, &shm_key, &arg_var)) {
     256           3 :                 return;
     257             :         }
     258             : 
     259             :         /* setup string-variable and serialize */
     260          15 :         PHP_VAR_SERIALIZE_INIT(var_hash);
     261          15 :         php_var_serialize(&shm_var, arg_var, &var_hash);
     262          15 :         PHP_VAR_SERIALIZE_DESTROY(var_hash);
     263             : 
     264          15 :         shm_list_ptr = zend_fetch_resource(Z_RES_P(shm_id), PHP_SHM_RSRC_NAME, php_sysvshm.le_shm);
     265          15 :         if (!shm_list_ptr) {
     266             :                 smart_str_free(&shm_var);
     267           0 :                 RETURN_FALSE;
     268             :         }
     269             : 
     270             :         /* insert serialized variable into shared memory */
     271          15 :         ret = php_put_shm_data(shm_list_ptr->ptr, shm_key, shm_var.s? shm_var.s->val : NULL, shm_var.s? shm_var.s->len : 0);
     272             : 
     273             :         /* free string */
     274             :         smart_str_free(&shm_var);
     275             : 
     276          15 :         if (ret == -1) {
     277           1 :                 php_error_docref(NULL, E_WARNING, "not enough shared memory left");
     278           1 :                 RETURN_FALSE;
     279             :         }
     280          14 :         RETURN_TRUE;
     281             : }
     282             : /* }}} */
     283             : 
     284             : /* {{{ proto mixed shm_get_var(resource id, int variable_key)
     285             :    Returns a variable from shared memory */
     286          16 : PHP_FUNCTION(shm_get_var)
     287             : {
     288             :         zval *shm_id;
     289             :         zend_long shm_key;
     290             :         sysvshm_shm *shm_list_ptr;
     291             :         char *shm_data;
     292             :         zend_long shm_varpos;
     293             :         sysvshm_chunk *shm_var;
     294             :         php_unserialize_data_t var_hash;
     295             : 
     296          16 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &shm_id, &shm_key)) {
     297           3 :                 return;
     298             :         }
     299          13 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     300             : 
     301             :         /* setup string-variable and serialize */
     302             :         /* get serialized variable from shared memory */
     303          13 :         shm_varpos = php_check_shm_data((shm_list_ptr->ptr), shm_key);
     304             : 
     305          13 :         if (shm_varpos < 0) {
     306           4 :                 php_error_docref(NULL, E_WARNING, "variable key %pd doesn't exist", shm_key);
     307           4 :                 RETURN_FALSE;
     308             :         }
     309           9 :         shm_var = (sysvshm_chunk*) ((char *)shm_list_ptr->ptr + shm_varpos);
     310           9 :         shm_data = &shm_var->mem;
     311             : 
     312           9 :         PHP_VAR_UNSERIALIZE_INIT(var_hash);
     313           9 :         if (php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash) != 1) {
     314           0 :                 php_error_docref(NULL, E_WARNING, "variable data in shared memory is corrupted");
     315           0 :                 RETVAL_FALSE;
     316             :         }
     317           9 :         PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
     318             : }
     319             : /* }}} */
     320             : 
     321             : /* {{{ proto bool shm_has_var(resource id, int variable_key)
     322             :         Checks whether a specific entry exists */
     323           0 : PHP_FUNCTION(shm_has_var)
     324             : {
     325             :         zval *shm_id;
     326             :         zend_long shm_key;
     327             :         sysvshm_shm *shm_list_ptr;
     328             : 
     329           0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &shm_id, &shm_key)) {
     330           0 :                 return;
     331             :         }
     332           0 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     333           0 :         RETURN_BOOL(php_check_shm_data(shm_list_ptr->ptr, shm_key) >= 0);
     334             : }
     335             : /* }}} */
     336             : 
     337             : /* {{{ proto bool shm_remove_var(resource id, int variable_key)
     338             :    Removes variable from shared memory */
     339           5 : PHP_FUNCTION(shm_remove_var)
     340             : {
     341             :         zval *shm_id;
     342             :         zend_long shm_key, shm_varpos;
     343             :         sysvshm_shm *shm_list_ptr;
     344             : 
     345           5 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &shm_id, &shm_key)) {
     346           2 :                 return;
     347             :         }
     348           3 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     349             : 
     350           3 :         shm_varpos = php_check_shm_data((shm_list_ptr->ptr), shm_key);
     351             : 
     352           3 :         if (shm_varpos < 0) {
     353           2 :                 php_error_docref(NULL, E_WARNING, "variable key %pd doesn't exist", shm_key);
     354           2 :                 RETURN_FALSE;
     355             :         }
     356           1 :         php_remove_shm_data((shm_list_ptr->ptr), shm_varpos);
     357           1 :         RETURN_TRUE;
     358             : }
     359             : /* }}} */
     360             : 
     361             : /* {{{ php_put_shm_data
     362             :  * inserts an ascii-string into shared memory */
     363          15 : static int php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const char *data, zend_long len)
     364             : {
     365             :         sysvshm_chunk *shm_var;
     366             :         zend_long total_size;
     367             :         zend_long shm_varpos;
     368             : 
     369          15 :         total_size = ((zend_long) (len + sizeof(sysvshm_chunk) - 1) / sizeof(zend_long)) * sizeof(zend_long) + sizeof(zend_long); /* zend_long alligment */
     370             : 
     371          15 :         if ((shm_varpos = php_check_shm_data(ptr, key)) > 0) {
     372           4 :                 php_remove_shm_data(ptr, shm_varpos);
     373             :         }
     374             : 
     375          15 :         if (ptr->free < total_size) {
     376           1 :                 return -1; /* not enough memory */
     377             :         }
     378             : 
     379          14 :         shm_var = (sysvshm_chunk *) ((char *) ptr + ptr->end);
     380          14 :         shm_var->key = key;
     381          14 :         shm_var->length = len;
     382          14 :         shm_var->next = total_size;
     383          14 :         memcpy(&(shm_var->mem), data, len);
     384          14 :         ptr->end += total_size;
     385          14 :         ptr->free -= total_size;
     386          14 :         return 0;
     387             : }
     388             : /* }}} */
     389             : 
     390             : /* {{{ php_check_shm_data
     391             :  */
     392          31 : static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key)
     393             : {
     394             :         zend_long pos;
     395             :         sysvshm_chunk *shm_var;
     396             : 
     397          31 :         pos = ptr->start;
     398             : 
     399             :         for (;;) {
     400          84 :                 if (pos >= ptr->end) {
     401          17 :                         return -1;
     402             :                 }
     403          67 :                 shm_var = (sysvshm_chunk*) ((char *) ptr + pos);
     404          67 :                 if (shm_var->key == key) {
     405          14 :                         return pos;
     406             :                 }
     407          53 :                 pos += shm_var->next;
     408             : 
     409          53 :                 if (shm_var->next <= 0 || pos < ptr->start) {
     410           0 :                         return -1;
     411             :                 }
     412          53 :         }
     413             :         return -1;
     414             : }
     415             : /* }}} */
     416             : 
     417             : /* {{{ php_remove_shm_data
     418             :  */
     419           5 : static int php_remove_shm_data(sysvshm_chunk_head *ptr, zend_long shm_varpos)
     420             : {
     421             :         sysvshm_chunk *chunk_ptr, *next_chunk_ptr;
     422             :         zend_long memcpy_len;
     423             : 
     424           5 :         chunk_ptr = (sysvshm_chunk *) ((char *) ptr + shm_varpos);
     425           5 :         next_chunk_ptr = (sysvshm_chunk *) ((char *) ptr + shm_varpos + chunk_ptr->next);
     426             : 
     427           5 :         memcpy_len = ptr->end-shm_varpos - chunk_ptr->next;
     428           5 :         ptr->free += chunk_ptr->next;
     429           5 :         ptr->end -= chunk_ptr->next;
     430           5 :         if (memcpy_len > 0) {
     431           0 :                 memmove(chunk_ptr, next_chunk_ptr, memcpy_len);
     432             :         }
     433           5 :         return 0;
     434             : }
     435             : /* }}} */
     436             : 
     437             : #endif /* HAVE_SYSVSHM */
     438             : 
     439             : /*
     440             :  * Local variables:
     441             :  * tab-width: 4
     442             :  * c-basic-offset: 4
     443             :  * End:
     444             :  * vim600: sw=4 ts=4 fdm=marker
     445             :  * vim<600: sw=4 ts=4
     446             :  */

Generated by: LCOV version 1.10

Generated at Fri, 20 Mar 2015 23:40:38 +0000 (6 days ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.