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: 2014-11-22 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-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             :    | 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) ZEND_FETCH_RESOURCE(shm_ptr, sysvshm_shm *, z_ptr, -1, PHP_SHM_RSRC_NAME, php_sysvshm.le_shm)
     116             : 
     117             : THREAD_LS sysvshm_module php_sysvshm;
     118             : 
     119             : static int php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const char *data, zend_long len);
     120             : static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key);
     121             : static int php_remove_shm_data(sysvshm_chunk_head *ptr, zend_long shm_varpos);
     122             : 
     123             : /* {{{ php_release_sysvshm
     124             :  */
     125          12 : static void php_release_sysvshm(zend_resource *rsrc TSRMLS_DC)
     126             : {
     127          12 :         sysvshm_shm *shm_ptr = (sysvshm_shm *) rsrc->ptr;
     128          12 :         shmdt((void *) shm_ptr->ptr);
     129          12 :         efree(shm_ptr);
     130          12 : }
     131             : /* }}} */
     132             : 
     133             : /* {{{ PHP_MINIT_FUNCTION
     134             :  */
     135       20507 : PHP_MINIT_FUNCTION(sysvshm)
     136             : {
     137       20507 :         php_sysvshm.le_shm = zend_register_list_destructors_ex(php_release_sysvshm, NULL, PHP_SHM_RSRC_NAME, module_number);
     138             : 
     139       20507 :         if (cfg_get_long("sysvshm.init_mem", &php_sysvshm.init_mem) == FAILURE) {
     140       20507 :                 php_sysvshm.init_mem=10000;
     141             :         }
     142       20507 :         return SUCCESS;
     143             : }
     144             : /* }}} */
     145             : 
     146             : /* {{{ proto int shm_attach(int key [, int memsize [, int perm]])
     147             :    Creates or open a shared memory segment */
     148          19 : PHP_FUNCTION(shm_attach)
     149             : {
     150             :         sysvshm_shm *shm_list_ptr;
     151             :         char *shm_ptr;
     152             :         sysvshm_chunk_head *chunk_ptr;
     153          19 :         zend_long shm_key, shm_id, shm_size = php_sysvshm.init_mem, shm_flag = 0666;
     154             : 
     155          19 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &shm_key, &shm_size, &shm_flag)) {
     156           2 :                 return;
     157             :         }
     158             : 
     159          17 :         if (shm_size < 1) {
     160           5 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Segment size must be greater than zero");
     161           5 :                 RETURN_FALSE;
     162             :         }
     163             : 
     164          12 :         shm_list_ptr = (sysvshm_shm *) emalloc(sizeof(sysvshm_shm));
     165             : 
     166             :         /* get the id from a specified key or create new shared memory */
     167          12 :         if ((shm_id = shmget(shm_key, 0, 0)) < 0) {
     168           9 :                 if (shm_size < sizeof(sysvshm_chunk_head)) {
     169           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%px: memorysize too small", shm_key);
     170           0 :                         efree(shm_list_ptr);
     171           0 :                         RETURN_FALSE;
     172             :                 }
     173           9 :                 if ((shm_id = shmget(shm_key, shm_size, shm_flag | IPC_CREAT | IPC_EXCL)) < 0) {
     174           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%px: %s", shm_key, strerror(errno));
     175           0 :                         efree(shm_list_ptr);
     176           0 :                         RETURN_FALSE;
     177             :                 }
     178             :         }
     179             : 
     180          12 :         if ((shm_ptr = shmat(shm_id, NULL, 0)) == (void *) -1) {
     181           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%px: %s", shm_key, strerror(errno));
     182           0 :                 efree(shm_list_ptr);
     183           0 :                 RETURN_FALSE;
     184             :         }
     185             : 
     186             :         /* check if shm is already initialized */
     187          12 :         chunk_ptr = (sysvshm_chunk_head *) shm_ptr;
     188          12 :         if (strcmp((char*) &(chunk_ptr->magic), "PHP_SM") != 0) {
     189           9 :                 strcpy((char*) &(chunk_ptr->magic), "PHP_SM"); 
     190           9 :                 chunk_ptr->start = sizeof(sysvshm_chunk_head);
     191           9 :                 chunk_ptr->end = chunk_ptr->start;
     192           9 :                 chunk_ptr->total = shm_size;
     193           9 :                 chunk_ptr->free = shm_size-chunk_ptr->end;
     194             :         }
     195             : 
     196          12 :         shm_list_ptr->key = shm_key;
     197          12 :         shm_list_ptr->id = shm_id;
     198          12 :         shm_list_ptr->ptr = chunk_ptr;
     199             :         
     200          12 :         ZEND_REGISTER_RESOURCE(return_value, shm_list_ptr, php_sysvshm.le_shm);
     201             : }
     202             : /* }}} */
     203             : 
     204             : /* {{{ proto bool shm_detach(resource shm_identifier)
     205             :    Disconnects from shared memory segment */
     206           8 : PHP_FUNCTION(shm_detach)
     207             : {
     208             :         zval *shm_id;
     209             :         sysvshm_shm *shm_list_ptr;
     210             : 
     211           8 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &shm_id)) {
     212           5 :                 return;
     213             :         }
     214           3 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     215           2 :         RETURN_BOOL(SUCCESS == zend_list_close(Z_RES_P(shm_id)));
     216             : }
     217             : /* }}} */
     218             : 
     219             : /* {{{ proto bool shm_remove(resource shm_identifier)
     220             :    Removes shared memory from Unix systems */
     221          20 : PHP_FUNCTION(shm_remove)
     222             : {
     223             :         zval *shm_id;
     224             :         sysvshm_shm *shm_list_ptr;
     225             : 
     226          20 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &shm_id)) {
     227           7 :                 return;
     228             :         }
     229          13 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     230             :         
     231          11 :         if (shmctl(shm_list_ptr->id, IPC_RMID, NULL) < 0) {
     232           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%x, id %ld: %s", shm_list_ptr->key, Z_LVAL_P(shm_id), strerror(errno));
     233           0 :                 RETURN_FALSE;
     234             :         }
     235             : 
     236          11 :         RETURN_TRUE;
     237             : }
     238             : /* }}} */
     239             : 
     240             : /* {{{ proto bool shm_put_var(resource shm_identifier, int variable_key, mixed variable)
     241             :    Inserts or updates a variable in shared memory */
     242          18 : PHP_FUNCTION(shm_put_var)
     243             : {
     244             :         zval *shm_id, *arg_var;
     245             :         int ret;
     246             :         zend_long shm_key;
     247             :         sysvshm_shm *shm_list_ptr;
     248          18 :         smart_str shm_var = {0};
     249             :         php_serialize_data_t var_hash;
     250             : 
     251          18 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &shm_id, &shm_key, &arg_var)) {
     252           3 :                 return;
     253             :         }
     254             :         
     255             :         /* setup string-variable and serialize */
     256          15 :         PHP_VAR_SERIALIZE_INIT(var_hash);
     257          15 :         php_var_serialize(&shm_var, arg_var, &var_hash TSRMLS_CC);
     258          15 :         PHP_VAR_SERIALIZE_DESTROY(var_hash);
     259             :         
     260          15 :         shm_list_ptr = zend_fetch_resource(shm_id TSRMLS_CC, -1, PHP_SHM_RSRC_NAME, NULL, 1, php_sysvshm.le_shm);
     261          15 :         if (!shm_list_ptr) {
     262             :                 smart_str_free(&shm_var);
     263           0 :                 RETURN_FALSE;
     264             :         }
     265             : 
     266             :         /* insert serialized variable into shared memory */
     267          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);
     268             : 
     269             :         /* free string */
     270             :         smart_str_free(&shm_var);
     271             :         
     272          15 :         if (ret == -1) {
     273           1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "not enough shared memory left");
     274           1 :                 RETURN_FALSE;
     275             :         }
     276          14 :         RETURN_TRUE;
     277             : }
     278             : /* }}} */
     279             : 
     280             : /* {{{ proto mixed shm_get_var(resource id, int variable_key)
     281             :    Returns a variable from shared memory */
     282          16 : PHP_FUNCTION(shm_get_var)
     283             : {
     284             :         zval *shm_id;
     285             :         zend_long shm_key;
     286             :         sysvshm_shm *shm_list_ptr;
     287             :         char *shm_data;
     288             :         zend_long shm_varpos;
     289             :         sysvshm_chunk *shm_var;
     290             :         php_unserialize_data_t var_hash;
     291             :         
     292          16 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &shm_id, &shm_key)) {
     293           3 :                 return;
     294             :         }
     295          13 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     296             : 
     297             :         /* setup string-variable and serialize */
     298             :         /* get serialized variable from shared memory */
     299          13 :         shm_varpos = php_check_shm_data((shm_list_ptr->ptr), shm_key);
     300             : 
     301          13 :         if (shm_varpos < 0) {
     302           4 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable key %pd doesn't exist", shm_key);
     303           4 :                 RETURN_FALSE;
     304             :         }
     305           9 :         shm_var = (sysvshm_chunk*) ((char *)shm_list_ptr->ptr + shm_varpos);
     306           9 :         shm_data = &shm_var->mem;
     307             :         
     308           9 :         PHP_VAR_UNSERIALIZE_INIT(var_hash);
     309           9 :         if (php_var_unserialize(return_value, (const unsigned char **) &shm_data, (unsigned char *) shm_data + shm_var->length, &var_hash TSRMLS_CC) != 1) {
     310           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable data in shared memory is corrupted");
     311           0 :                 RETVAL_FALSE;
     312             :         }
     313           9 :         PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
     314             : }
     315             : /* }}} */
     316             : 
     317             : /* {{{ proto bool shm_has_var(resource id, int variable_key)
     318             :         Checks whether a specific entry exists */
     319           0 : PHP_FUNCTION(shm_has_var)
     320             : {
     321             :         zval *shm_id;
     322             :         zend_long shm_key;
     323             :         sysvshm_shm *shm_list_ptr;
     324             :         
     325           0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &shm_id, &shm_key)) {
     326           0 :                 return;
     327             :         }
     328           0 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     329           0 :         RETURN_BOOL(php_check_shm_data(shm_list_ptr->ptr, shm_key) >= 0);
     330             : }
     331             : /* }}} */
     332             : 
     333             : /* {{{ proto bool shm_remove_var(resource id, int variable_key)
     334             :    Removes variable from shared memory */
     335           5 : PHP_FUNCTION(shm_remove_var)
     336             : {
     337             :         zval *shm_id;
     338             :         zend_long shm_key, shm_varpos;
     339             :         sysvshm_shm *shm_list_ptr;
     340             :         
     341           5 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &shm_id, &shm_key)) {
     342           2 :                 return;
     343             :         }
     344           3 :         SHM_FETCH_RESOURCE(shm_list_ptr, shm_id);
     345             : 
     346           3 :         shm_varpos = php_check_shm_data((shm_list_ptr->ptr), shm_key);
     347             : 
     348           3 :         if (shm_varpos < 0) {
     349           2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "variable key %pd doesn't exist", shm_key);
     350           2 :                 RETURN_FALSE;
     351             :         }
     352           1 :         php_remove_shm_data((shm_list_ptr->ptr), shm_varpos);
     353           1 :         RETURN_TRUE;
     354             : }
     355             : /* }}} */
     356             : 
     357             : /* {{{ php_put_shm_data
     358             :  * inserts an ascii-string into shared memory */
     359          15 : static int php_put_shm_data(sysvshm_chunk_head *ptr, zend_long key, const char *data, zend_long len)
     360             : {
     361             :         sysvshm_chunk *shm_var;
     362             :         zend_long total_size;
     363             :         zend_long shm_varpos;
     364             : 
     365          15 :         total_size = ((zend_long) (len + sizeof(sysvshm_chunk) - 1) / sizeof(zend_long)) * sizeof(zend_long) + sizeof(zend_long); /* zend_long alligment */
     366             : 
     367          15 :         if ((shm_varpos = php_check_shm_data(ptr, key)) > 0) {
     368           4 :                 php_remove_shm_data(ptr, shm_varpos);
     369             :         }
     370             :         
     371          15 :         if (ptr->free < total_size) {
     372           1 :                 return -1; /* not enough memory */
     373             :         }
     374             : 
     375          14 :         shm_var = (sysvshm_chunk *) ((char *) ptr + ptr->end);       
     376          14 :         shm_var->key = key;
     377          14 :         shm_var->length = len;
     378          14 :         shm_var->next = total_size;   
     379          14 :         memcpy(&(shm_var->mem), data, len);      
     380          14 :         ptr->end += total_size;
     381          14 :         ptr->free -= total_size;
     382          14 :         return 0;
     383             : }
     384             : /* }}} */
     385             : 
     386             : /* {{{ php_check_shm_data
     387             :  */
     388          31 : static zend_long php_check_shm_data(sysvshm_chunk_head *ptr, zend_long key)
     389             : {
     390             :         zend_long pos;
     391             :         sysvshm_chunk *shm_var;
     392             : 
     393          31 :         pos = ptr->start;
     394             :                         
     395             :         for (;;) {
     396          84 :                 if (pos >= ptr->end) {
     397          17 :                         return -1;
     398             :                 }
     399          67 :                 shm_var = (sysvshm_chunk*) ((char *) ptr + pos);
     400          67 :                 if (shm_var->key == key) {
     401          14 :                         return pos;
     402             :                 }       
     403          53 :                 pos += shm_var->next;
     404             : 
     405          53 :                 if (shm_var->next <= 0 || pos < ptr->start) {
     406           0 :                         return -1;
     407             :                 }
     408          53 :         }
     409             :         return -1;
     410             : }
     411             : /* }}} */
     412             : 
     413             : /* {{{ php_remove_shm_data
     414             :  */
     415           5 : static int php_remove_shm_data(sysvshm_chunk_head *ptr, zend_long shm_varpos)
     416             : {
     417             :         sysvshm_chunk *chunk_ptr, *next_chunk_ptr;
     418             :         zend_long memcpy_len;
     419             :         
     420           5 :         chunk_ptr = (sysvshm_chunk *) ((char *) ptr + shm_varpos);
     421           5 :         next_chunk_ptr = (sysvshm_chunk *) ((char *) ptr + shm_varpos + chunk_ptr->next);
     422             :         
     423           5 :         memcpy_len = ptr->end-shm_varpos - chunk_ptr->next;
     424           5 :         ptr->free += chunk_ptr->next;
     425           5 :         ptr->end -= chunk_ptr->next;
     426           5 :         if (memcpy_len > 0) {
     427           0 :                 memmove(chunk_ptr, next_chunk_ptr, memcpy_len);
     428             :         }
     429           5 :         return 0;
     430             : }
     431             : /* }}} */
     432             : 
     433             : #endif /* HAVE_SYSVSHM */
     434             : 
     435             : /*
     436             :  * Local variables:
     437             :  * tab-width: 4
     438             :  * c-basic-offset: 4
     439             :  * End:
     440             :  * vim600: sw=4 ts=4 fdm=marker
     441             :  * vim<600: sw=4 ts=4
     442             :  */

Generated by: LCOV version 1.10

Generated at Sat, 22 Nov 2014 23:01:27 +0000 (4 days ago)

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