root/ext/shmop/shmop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rsclean
  2. PHP_MINIT_FUNCTION
  3. PHP_MINFO_FUNCTION
  4. PHP_FUNCTION
  5. PHP_FUNCTION
  6. PHP_FUNCTION
  7. PHP_FUNCTION
  8. PHP_FUNCTION
  9. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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$ */
  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  */

/* [<][>][^][v][top][bottom][index][help] */