php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
shmop.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | PHP version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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 | https://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
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24#include "php.h"
25#include "php_shmop.h"
27
28#include "shmop_arginfo.h"
29
30# ifndef PHP_WIN32
31# include <sys/ipc.h>
32# include <sys/shm.h>
33#else
34#include "tsrm_win32.h"
35#endif
36
37
38#ifdef HAVE_SHMOP
39
40#include "ext/standard/info.h"
41
42/* {{{ shmop_module_entry */
43zend_module_entry shmop_module_entry = {
45 "shmop",
46 ext_functions,
47 PHP_MINIT(shmop),
48 NULL,
49 NULL,
50 NULL,
51 PHP_MINFO(shmop),
52 PHP_SHMOP_VERSION,
54};
55/* }}} */
56
57#ifdef COMPILE_DL_SHMOP
58ZEND_GET_MODULE(shmop)
59#endif
60
61typedef struct php_shmop
62{
63 int shmid;
64 key_t key;
65 int shmflg;
66 int shmatflg;
67 char *addr;
69 zend_object std;
70} php_shmop;
71
72zend_class_entry *shmop_ce;
73static zend_object_handlers shmop_object_handlers;
74
75static inline php_shmop *shmop_from_obj(zend_object *obj)
76{
77 return (php_shmop *)((char *)(obj) - XtOffsetOf(php_shmop, std));
78}
79
80#define Z_SHMOP_P(zv) shmop_from_obj(Z_OBJ_P(zv))
81
82static zend_object *shmop_create_object(zend_class_entry *class_type)
83{
84 php_shmop *intern = zend_object_alloc(sizeof(php_shmop), class_type);
85
86 zend_object_std_init(&intern->std, class_type);
87 object_properties_init(&intern->std, class_type);
88
89 return &intern->std;
90}
91
92static zend_function *shmop_get_constructor(zend_object *object)
93{
94 zend_throw_error(NULL, "Cannot directly construct Shmop, use shmop_open() instead");
95 return NULL;
96}
97
98static void shmop_free_obj(zend_object *object)
99{
100 php_shmop *shmop = shmop_from_obj(object);
101
102 shmdt(shmop->addr);
103
104 zend_object_std_dtor(&shmop->std);
105}
106
107/* {{{ PHP_MINIT_FUNCTION */
109{
110 shmop_ce = register_class_Shmop();
111 shmop_ce->create_object = shmop_create_object;
112 shmop_ce->default_object_handlers = &shmop_object_handlers;
113
114 memcpy(&shmop_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
115 shmop_object_handlers.offset = XtOffsetOf(php_shmop, std);
116 shmop_object_handlers.free_obj = shmop_free_obj;
117 shmop_object_handlers.get_constructor = shmop_get_constructor;
118 shmop_object_handlers.clone_obj = NULL;
119 shmop_object_handlers.compare = zend_objects_not_comparable;
120
121 register_shmop_symbols(module_number);
122
123 return SUCCESS;
124}
125/* }}} */
126
127/* {{{ PHP_MINFO_FUNCTION */
129{
131 php_info_print_table_row(2, "shmop support", "enabled");
133}
134/* }}} */
135
136/* {{{ gets and attaches a shared memory segment */
138{
140 php_shmop *shmop;
141 struct shmid_ds shm;
142 char *flags;
143 size_t flags_len;
144
145 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lsll", &key, &flags, &flags_len, &mode, &size) == FAILURE) {
147 }
148
149 if (flags_len != 1) {
150 zend_argument_value_error(2, "must be a valid access mode");
152 }
153
154 object_init_ex(return_value, shmop_ce);
155 shmop = Z_SHMOP_P(return_value);
156 shmop->key = key;
157 shmop->shmflg |= mode;
158
159 switch (flags[0])
160 {
161 case 'a':
162 shmop->shmatflg |= SHM_RDONLY;
163 break;
164 case 'c':
165 shmop->shmflg |= IPC_CREAT;
166 shmop->size = size;
167 break;
168 case 'n':
169 shmop->shmflg |= (IPC_CREAT | IPC_EXCL);
170 shmop->size = size;
171 break;
172 case 'w':
173 /* noop
174 shm segment is being opened for read & write
175 will fail if segment does not exist
176 */
177 break;
178 default:
179 zend_argument_value_error(2, "must be a valid access mode");
180 goto err;
181 }
182
183 if (shmop->shmflg & IPC_CREAT && shmop->size < 1) {
184 zend_argument_value_error(4, "must be greater than 0 for the \"c\" and \"n\" access modes");
185 goto err;
186 }
187
188 shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg);
189 if (shmop->shmid == -1) {
190 php_error_docref(NULL, E_WARNING, "Unable to attach or create shared memory segment \"%s\"", strerror(errno));
191 goto err;
192 }
193
194 if (shmctl(shmop->shmid, IPC_STAT, &shm)) {
195 /* please do not add coverage here: the segment would be leaked and impossible to delete via php */
196 php_error_docref(NULL, E_WARNING, "Unable to get shared memory segment information \"%s\"", strerror(errno));
197 goto err;
198 }
199
200 if (shm.shm_segsz > ZEND_LONG_MAX) {
201 zend_argument_value_error(4, "is too large");
202 goto err;
203 }
204
205 shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg);
206 if (shmop->addr == (char*) -1) {
207 php_error_docref(NULL, E_WARNING, "Unable to attach to shared memory segment \"%s\"", strerror(errno));
208 goto err;
209 }
210
211 shmop->size = shm.shm_segsz;
212 return;
213
214err:
215 zend_object_release(Z_OBJ_P(return_value));
217}
218/* }}} */
219
220/* {{{ reads from a shm segment */
222{
223 zval *shmid;
225 php_shmop *shmop;
226 char *startaddr;
227 int bytes;
228 zend_string *return_string;
229
230 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oll", &shmid, shmop_ce, &start, &count) == FAILURE) {
232 }
233
234 shmop = Z_SHMOP_P(shmid);
235
236 if (start < 0 || start > shmop->size) {
237 zend_argument_value_error(2, "must be between 0 and the segment size");
239 }
240
241 if (count < 0 || start > (ZEND_LONG_MAX - count) || start + count > shmop->size) {
242 zend_argument_value_error(3, "is out of range");
244 }
245
246 startaddr = shmop->addr + start;
247 bytes = count ? count : shmop->size - start;
248
249 return_string = zend_string_init(startaddr, bytes, 0);
250
251 RETURN_NEW_STR(return_string);
252}
253/* }}} */
254
255/* {{{ used to close a shared memory segment; now a NOP */
257{
258 zval *shmid;
259
260 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
262 }
263}
264/* }}} */
265
266/* {{{ returns the shm size */
268{
269 zval *shmid;
270 php_shmop *shmop;
271
272 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
274 }
275
276 shmop = Z_SHMOP_P(shmid);
277
278 RETURN_LONG(shmop->size);
279}
280/* }}} */
281
282/* {{{ writes to a shared memory segment */
284{
285 php_shmop *shmop;
286 zend_long writesize;
289 zval *shmid;
290
291 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &shmid, shmop_ce, &data, &offset) == FAILURE) {
293 }
294
295 shmop = Z_SHMOP_P(shmid);
296
297 if ((shmop->shmatflg & SHM_RDONLY) == SHM_RDONLY) {
298 zend_throw_error(NULL, "Read-only segment cannot be written");
300 }
301
302 if (offset < 0 || offset > shmop->size) {
303 zend_argument_value_error(3, "is out of range");
305 }
306
307 writesize = ((zend_long)ZSTR_LEN(data) < shmop->size - offset) ? (zend_long)ZSTR_LEN(data) : shmop->size - offset;
308 memcpy(shmop->addr + offset, ZSTR_VAL(data), writesize);
309
310 RETURN_LONG(writesize);
311}
312/* }}} */
313
314/* {{{ mark segment for deletion */
316{
317 zval *shmid;
318 php_shmop *shmop;
319
320 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
322 }
323
324 shmop = Z_SHMOP_P(shmid);
325
326 if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
327 php_error_docref(NULL, E_WARNING, "Can't mark segment for deletion (are you the owner?)");
329 }
330
332}
333/* }}} */
334
335#endif /* HAVE_SHMOP */
count(Countable|array $value, int $mode=COUNT_NORMAL)
new_type size
Definition ffi.c:4365
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
buf start
Definition ffi.c:4687
void * addr
Definition ffi.c:3030
zend_long offset
char * mode
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
int key_t
Definition ipc.h:26
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_MINIT
Definition php.h:392
unsigned char key[REFLECTION_KEY_LEN]
zend_constant * data
shmop_size(Shmop $shmop)
shmop_read(Shmop $shmop, int $offset, int $size)
shmop_write(Shmop $shmop, string $data, int $offset)
shmop_open(int $key, string $mode, int $permissions, int $size)
shmop_delete(Shmop $shmop)
shmop_close(Shmop $shmop)
zend_object *(* create_object)(zend_class_entry *class_type)
Definition zend.h:195
const zend_object_handlers * default_object_handlers
Definition zend.h:186
zend_object_compare_t compare
zend_object_free_obj_t free_obj
zend_object_get_constructor_t get_constructor
zend_object_clone_obj_t clone_obj
#define errno
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_FALSE
Definition zend_API.h:1058
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETURN_TRUE
Definition zend_API.h:1059
struct _zval_struct zval
#define E_WARNING
Definition zend_errors.h:24
union _zend_function zend_function
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
#define STANDARD_MODULE_HEADER
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
ZEND_API int zend_objects_not_comparable(zval *o1, zval *o2)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
#define XtOffsetOf(s_type, field)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
@ FAILURE
Definition zend_types.h:61
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
zval * return_value