root/ext/shmop/shmop.c

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

DEFINITIONS

This source file includes following definitions.
  1. ZEND_GET_MODULE
  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         PHP_SHMOP_VERSION,
 106         STANDARD_MODULE_PROPERTIES
 107 };
 108 /* }}} */
 109 
 110 #ifdef COMPILE_DL_SHMOP
 111 ZEND_GET_MODULE(shmop)
 112 #endif
 113 
 114 /* {{{ rsclean
 115  */
 116 static void rsclean(zend_resource *rsrc)
 117 {
 118         struct php_shmop *shmop = (struct php_shmop *)rsrc->ptr;
 119 
 120         shmdt(shmop->addr);
 121         efree(shmop);
 122 }
 123 /* }}} */
 124 
 125 /* {{{ PHP_MINIT_FUNCTION
 126  */
 127 PHP_MINIT_FUNCTION(shmop)
 128 {
 129         shm_type = zend_register_list_destructors_ex(rsclean, NULL, "shmop", module_number);
 130 
 131         return SUCCESS;
 132 }
 133 /* }}} */
 134 
 135 /* {{{ PHP_MINFO_FUNCTION
 136  */
 137 PHP_MINFO_FUNCTION(shmop)
 138 {
 139         php_info_print_table_start();
 140         php_info_print_table_row(2, "shmop support", "enabled");
 141         php_info_print_table_end();
 142 }
 143 /* }}} */
 144 
 145 /* {{{ proto int shmop_open (int key, string flags, int mode, int size)
 146    gets and attaches a shared memory segment */
 147 PHP_FUNCTION(shmop_open)
 148 {
 149         zend_long key, mode, size;
 150         struct php_shmop *shmop;
 151         struct shmid_ds shm;
 152         char *flags;
 153         size_t flags_len;
 154 
 155         if (zend_parse_parameters(ZEND_NUM_ARGS(), "lsll", &key, &flags, &flags_len, &mode, &size) == FAILURE) {
 156                 return;
 157         }
 158 
 159         if (flags_len != 1) {
 160                 php_error_docref(NULL, E_WARNING, "%s is not a valid flag", flags);
 161                 RETURN_FALSE;
 162         }
 163 
 164         shmop = emalloc(sizeof(struct php_shmop));
 165         memset(shmop, 0, sizeof(struct php_shmop));
 166 
 167         shmop->key = key;
 168         shmop->shmflg |= mode;
 169 
 170         switch (flags[0])
 171         {
 172                 case 'a':
 173                         shmop->shmatflg |= SHM_RDONLY;
 174                         break;
 175                 case 'c':
 176                         shmop->shmflg |= IPC_CREAT;
 177                         shmop->size = size;
 178                         break;
 179                 case 'n':
 180                         shmop->shmflg |= (IPC_CREAT | IPC_EXCL);
 181                         shmop->size = size;
 182                         break;
 183                 case 'w':
 184                         /* noop
 185                                 shm segment is being opened for read & write
 186                                 will fail if segment does not exist
 187                         */
 188                         break;
 189                 default:
 190                         php_error_docref(NULL, E_WARNING, "invalid access mode");
 191                         goto err;
 192         }
 193 
 194         if (shmop->shmflg & IPC_CREAT && shmop->size < 1) {
 195                 php_error_docref(NULL, E_WARNING, "Shared memory segment size must be greater than zero");
 196                 goto err;
 197         }
 198 
 199         shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg);
 200         if (shmop->shmid == -1) {
 201                 php_error_docref(NULL, E_WARNING, "unable to attach or create shared memory segment '%s'", strerror(errno));
 202                 goto err;
 203         }
 204 
 205         if (shmctl(shmop->shmid, IPC_STAT, &shm)) {
 206                 php_error_docref(NULL, E_WARNING, "unable to get shared memory segment information '%s'", strerror(errno));
 207                 goto err;
 208         }
 209 
 210         shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg);
 211         if (shmop->addr == (char*) -1) {
 212                 php_error_docref(NULL, E_WARNING, "unable to attach to shared memory segment '%s'", strerror(errno));
 213                 goto err;
 214         }
 215 
 216         shmop->size = shm.shm_segsz;
 217 
 218         RETURN_RES(zend_register_resource(shmop, shm_type));
 219 err:
 220         efree(shmop);
 221         RETURN_FALSE;
 222 }
 223 /* }}} */
 224 
 225 /* {{{ proto string shmop_read (int shmid, int start, int count)
 226    reads from a shm segment */
 227 PHP_FUNCTION(shmop_read)
 228 {
 229         zval *shmid;
 230         zend_long start, count;
 231         struct php_shmop *shmop;
 232         char *startaddr;
 233         int bytes;
 234         zend_string *return_string;
 235 
 236         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &shmid, &start, &count) == FAILURE) {
 237                 return;
 238         }
 239 
 240         if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
 241                 RETURN_FALSE;
 242         }
 243 
 244         if (start < 0 || start > shmop->size) {
 245                 php_error_docref(NULL, E_WARNING, "start is out of range");
 246                 RETURN_FALSE;
 247         }
 248 
 249         if (count < 0 || start > (INT_MAX - count) || start + count > shmop->size) {
 250                 php_error_docref(NULL, E_WARNING, "count is out of range");
 251                 RETURN_FALSE;
 252         }
 253 
 254         startaddr = shmop->addr + start;
 255         bytes = count ? count : shmop->size - start;
 256 
 257         return_string = zend_string_init(startaddr, bytes, 0);
 258 
 259         RETURN_NEW_STR(return_string);
 260 }
 261 /* }}} */
 262 
 263 /* {{{ proto void shmop_close (int shmid)
 264    closes a shared memory segment */
 265 PHP_FUNCTION(shmop_close)
 266 {
 267         zval *shmid;
 268         struct php_shmop *shmop;
 269 
 270         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
 271                 return;
 272         }
 273 
 274 
 275         if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
 276                 RETURN_FALSE;
 277         }
 278 
 279         zend_list_close(Z_RES_P(shmid));
 280 }
 281 /* }}} */
 282 
 283 /* {{{ proto int shmop_size (int shmid)
 284    returns the shm size */
 285 PHP_FUNCTION(shmop_size)
 286 {
 287         zval *shmid;
 288         struct php_shmop *shmop;
 289 
 290         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
 291                 return;
 292         }
 293 
 294         if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
 295                 RETURN_FALSE;
 296         }
 297 
 298         RETURN_LONG(shmop->size);
 299 }
 300 /* }}} */
 301 
 302 /* {{{ proto int shmop_write (int shmid, string data, int offset)
 303    writes to a shared memory segment */
 304 PHP_FUNCTION(shmop_write)
 305 {
 306         struct php_shmop *shmop;
 307         int writesize;
 308         zend_long offset;
 309         zend_string *data;
 310         zval *shmid;
 311 
 312         if (zend_parse_parameters(ZEND_NUM_ARGS(), "rSl", &shmid, &data, &offset) == FAILURE) {
 313                 return;
 314         }
 315 
 316         if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
 317                 RETURN_FALSE;
 318         }
 319 
 320         if ((shmop->shmatflg & SHM_RDONLY) == SHM_RDONLY) {
 321                 php_error_docref(NULL, E_WARNING, "trying to write to a read only segment");
 322                 RETURN_FALSE;
 323         }
 324 
 325         if (offset < 0 || offset > shmop->size) {
 326                 php_error_docref(NULL, E_WARNING, "offset out of range");
 327                 RETURN_FALSE;
 328         }
 329 
 330         writesize = (ZSTR_LEN(data) < shmop->size - offset) ? ZSTR_LEN(data) : shmop->size - offset;
 331         memcpy(shmop->addr + offset, ZSTR_VAL(data), writesize);
 332 
 333         RETURN_LONG(writesize);
 334 }
 335 /* }}} */
 336 
 337 /* {{{ proto bool shmop_delete (int shmid)
 338    mark segment for deletion */
 339 PHP_FUNCTION(shmop_delete)
 340 {
 341         zval *shmid;
 342         struct php_shmop *shmop;
 343 
 344         if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
 345                 return;
 346         }
 347 
 348         if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
 349                 RETURN_FALSE;
 350         }
 351 
 352         if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
 353                 php_error_docref(NULL, E_WARNING, "can't mark segment for deletion (are you the owner?)");
 354                 RETURN_FALSE;
 355         }
 356 
 357         RETURN_TRUE;
 358 }
 359 /* }}} */
 360 
 361 #endif  /* HAVE_SHMOP */
 362 
 363 /*
 364  * Local variables:
 365  * tab-width: 4
 366  * c-basic-offset: 4
 367  * End:
 368  * vim600: sw=4 ts=4 fdm=marker
 369  * vim<600: sw=4 ts=4
 370  */

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