1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "apr_arch_shm.h"
18 #include "apr_arch_file_io.h"
19
20 #include "apr_general.h"
21 #include "apr_errno.h"
22 #include "apr_user.h"
23 #include "apr_strings.h"
24 #include "apr_hash.h"
25
26 #if APR_USE_SHMEM_MMAP_SHM
27 /*
28 * For portable use, a shared memory object should be identified by a name of
29 * the form /somename; that is, a null-terminated string of up to NAME_MAX
30 * (i.e., 255) characters consisting of an initial slash, followed by one or
31 * more characters, none of which are slashes.
32 */
33 #ifndef NAME_MAX
34 #define NAME_MAX 255
35 #endif
36
37 /* See proc_mutex.c and sem_open for the reason for all this! */
rshash(const char * p)38 static unsigned int rshash (const char *p) {
39 /* hash function from Robert Sedgwicks 'Algorithms in C' book */
40 unsigned int b = 378551;
41 unsigned int a = 63689;
42 unsigned int retval = 0;
43
44 for( ; *p; p++) {
45 retval = retval * a + (*p);
46 a *= b;
47 }
48
49 return retval;
50 }
51
make_shm_open_safe_name(const char * filename,apr_pool_t * pool)52 static const char *make_shm_open_safe_name(const char *filename,
53 apr_pool_t *pool)
54 {
55 apr_ssize_t flen;
56 unsigned int h1, h2;
57
58 if (filename == NULL) {
59 return NULL;
60 }
61
62 flen = strlen(filename);
63 h1 = (apr_hashfunc_default(filename, &flen) & 0xffffffff);
64 h2 = (rshash(filename) & 0xffffffff);
65 return apr_psprintf(pool, "/ShM.%xH%x", h1, h2);
66
67 }
68 #endif
69
70 #if APR_USE_SHMEM_SHMGET
our_ftok(const char * filename)71 static key_t our_ftok(const char *filename)
72 {
73 /* to help avoid collisions while still using
74 * an easily recreated proj_id */
75 apr_ssize_t slen = strlen(filename);
76 return ftok(filename,
77 (int)apr_hashfunc_default(filename, &slen));
78 }
79 #endif
80
shm_cleanup_owner(void * m_)81 static apr_status_t shm_cleanup_owner(void *m_)
82 {
83 apr_shm_t *m = (apr_shm_t *)m_;
84
85 /* anonymous shared memory */
86 if (m->filename == NULL) {
87 #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON
88 if (munmap(m->base, m->realsize) == -1) {
89 return errno;
90 }
91 return APR_SUCCESS;
92 #elif APR_USE_SHMEM_SHMGET_ANON
93 if (shmdt(m->base) == -1) {
94 return errno;
95 }
96 /* This segment will automatically remove itself after all
97 * references have detached. */
98 return APR_SUCCESS;
99 #endif
100 }
101
102 /* name-based shared memory */
103 else {
104 #if APR_USE_SHMEM_MMAP_TMP
105 if (munmap(m->base, m->realsize) == -1) {
106 return errno;
107 }
108 if (access(m->filename, F_OK)) {
109 return APR_SUCCESS;
110 }
111 else {
112 return apr_file_remove(m->filename, m->pool);
113 }
114 #elif APR_USE_SHMEM_MMAP_SHM
115 if (munmap(m->base, m->realsize) == -1) {
116 return errno;
117 }
118 if (shm_unlink(make_shm_open_safe_name(m->filename, m->pool)) == -1 && errno != ENOENT) {
119 return errno;
120 }
121 return APR_SUCCESS;
122 #elif APR_USE_SHMEM_SHMGET
123 /* Indicate that the segment is to be destroyed as soon
124 * as all processes have detached. This also disallows any
125 * new attachments to the segment. */
126 if (shmctl(m->shmid, IPC_RMID, NULL) == -1 && errno != EINVAL) {
127 return errno;
128 }
129 if (shmdt(m->base) == -1) {
130 return errno;
131 }
132 if (access(m->filename, F_OK)) {
133 return APR_SUCCESS;
134 }
135 else {
136 return apr_file_remove(m->filename, m->pool);
137 }
138 #else
139 return APR_ENOTIMPL;
140 #endif
141 }
142 }
143
apr_shm_create(apr_shm_t ** m,apr_size_t reqsize,const char * filename,apr_pool_t * pool)144 APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
145 apr_size_t reqsize,
146 const char *filename,
147 apr_pool_t *pool)
148 {
149 apr_shm_t *new_m;
150 apr_status_t status;
151 #if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
152 struct shmid_ds shmbuf;
153 apr_uid_t uid;
154 apr_gid_t gid;
155 #endif
156 #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \
157 APR_USE_SHMEM_MMAP_ZERO
158 int tmpfd;
159 #endif
160 #if APR_USE_SHMEM_SHMGET
161 apr_size_t nbytes;
162 #endif
163 #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET || \
164 APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
165 apr_file_t *file; /* file where metadata is stored */
166 #endif
167
168 /* Check if they want anonymous or name-based shared memory */
169 if (filename == NULL) {
170 #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON
171 new_m = apr_palloc(pool, sizeof(apr_shm_t));
172 new_m->pool = pool;
173 new_m->reqsize = reqsize;
174 new_m->realsize = reqsize +
175 APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */
176 new_m->filename = NULL;
177
178 #if APR_USE_SHMEM_MMAP_ZERO
179 status = apr_file_open(&file, "/dev/zero", APR_READ | APR_WRITE,
180 APR_OS_DEFAULT, pool);
181 if (status != APR_SUCCESS) {
182 return status;
183 }
184 status = apr_os_file_get(&tmpfd, file);
185 if (status != APR_SUCCESS) {
186 return status;
187 }
188
189 new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE,
190 MAP_SHARED, tmpfd, 0);
191 if (new_m->base == (void *)MAP_FAILED) {
192 return errno;
193 }
194
195 status = apr_file_close(file);
196 if (status != APR_SUCCESS) {
197 return status;
198 }
199
200 /* store the real size in the metadata */
201 *(apr_size_t*)(new_m->base) = new_m->realsize;
202 /* metadata isn't usable */
203 new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
204
205 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
206 apr_pool_cleanup_null);
207 *m = new_m;
208 return APR_SUCCESS;
209
210 #elif APR_USE_SHMEM_MMAP_ANON
211 new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE,
212 MAP_ANON|MAP_SHARED, -1, 0);
213 if (new_m->base == (void *)MAP_FAILED) {
214 return errno;
215 }
216
217 /* store the real size in the metadata */
218 *(apr_size_t*)(new_m->base) = new_m->realsize;
219 /* metadata isn't usable */
220 new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
221
222 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
223 apr_pool_cleanup_null);
224 *m = new_m;
225 return APR_SUCCESS;
226
227 #endif /* APR_USE_SHMEM_MMAP_ZERO */
228 #elif APR_USE_SHMEM_SHMGET_ANON
229 new_m = apr_palloc(pool, sizeof(apr_shm_t));
230 new_m->pool = pool;
231 new_m->reqsize = reqsize;
232 new_m->realsize = reqsize;
233 new_m->filename = NULL;
234 new_m->shmkey = IPC_PRIVATE;
235 if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize,
236 SHM_R | SHM_W | IPC_CREAT)) < 0) {
237 return errno;
238 }
239
240 if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
241 return errno;
242 }
243 new_m->usable = new_m->base;
244
245 if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
246 return errno;
247 }
248 apr_uid_current(&uid, &gid, pool);
249 shmbuf.shm_perm.uid = uid;
250 shmbuf.shm_perm.gid = gid;
251 if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
252 return errno;
253 }
254
255 /* Remove the segment once use count hits zero.
256 * We will not attach to this segment again, since it is
257 * anonymous memory, so it is ok to mark it for deletion.
258 */
259 if (shmctl(new_m->shmid, IPC_RMID, NULL) == -1) {
260 return errno;
261 }
262
263 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
264 apr_pool_cleanup_null);
265 *m = new_m;
266 return APR_SUCCESS;
267 #else
268 /* It is an error if they want anonymous memory but we don't have it. */
269 return APR_ENOTIMPL; /* requested anonymous but we don't have it */
270 #endif
271 }
272
273 /* Name-based shared memory */
274 else {
275 new_m = apr_palloc(pool, sizeof(apr_shm_t));
276 new_m->pool = pool;
277 new_m->reqsize = reqsize;
278 new_m->filename = apr_pstrdup(pool, filename);
279 #if APR_USE_SHMEM_MMAP_SHM
280 const char *shm_name = make_shm_open_safe_name(filename, pool);
281 #endif
282 #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
283 new_m->realsize = reqsize +
284 APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */
285 /* FIXME: Ignore error for now. *
286 * status = apr_file_remove(file, pool);*/
287 status = APR_SUCCESS;
288
289 #if APR_USE_SHMEM_MMAP_TMP
290 /* FIXME: Is APR_OS_DEFAULT sufficient? */
291 status = apr_file_open(&file, filename,
292 APR_READ | APR_WRITE | APR_CREATE | APR_EXCL,
293 APR_OS_DEFAULT, pool);
294 if (status != APR_SUCCESS) {
295 return status;
296 }
297
298 status = apr_os_file_get(&tmpfd, file);
299 if (status != APR_SUCCESS) {
300 apr_file_close(file); /* ignore errors, we're failing */
301 apr_file_remove(new_m->filename, new_m->pool);
302 return status;
303 }
304
305 status = apr_file_trunc(file, new_m->realsize);
306 if (status != APR_SUCCESS && status != APR_ESPIPE) {
307 apr_file_close(file); /* ignore errors, we're failing */
308 apr_file_remove(new_m->filename, new_m->pool);
309 return status;
310 }
311
312 new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
313 MAP_SHARED, tmpfd, 0);
314 /* FIXME: check for errors */
315
316 status = apr_file_close(file);
317 if (status != APR_SUCCESS) {
318 return status;
319 }
320 #endif /* APR_USE_SHMEM_MMAP_TMP */
321 #if APR_USE_SHMEM_MMAP_SHM
322 /* FIXME: SysV uses 0600... should we? */
323 tmpfd = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0644);
324 if (tmpfd == -1) {
325 return errno;
326 }
327
328 status = apr_os_file_put(&file, &tmpfd,
329 APR_READ | APR_WRITE | APR_CREATE | APR_EXCL,
330 pool);
331 if (status != APR_SUCCESS) {
332 return status;
333 }
334
335 status = apr_file_trunc(file, new_m->realsize);
336 if (status != APR_SUCCESS && status != APR_ESPIPE) {
337 shm_unlink(shm_name); /* we're failing, remove the object */
338 return status;
339 }
340 new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
341 MAP_SHARED, tmpfd, 0);
342
343 /* FIXME: check for errors */
344
345 status = apr_file_close(file);
346 if (status != APR_SUCCESS) {
347 return status;
348 }
349 #endif /* APR_USE_SHMEM_MMAP_SHM */
350
351 /* store the real size in the metadata */
352 *(apr_size_t*)(new_m->base) = new_m->realsize;
353 /* metadata isn't usable */
354 new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
355
356 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
357 apr_pool_cleanup_null);
358 *m = new_m;
359 return APR_SUCCESS;
360
361 #elif APR_USE_SHMEM_SHMGET
362 new_m->realsize = reqsize;
363
364 /* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think. */
365 status = apr_file_open(&file, filename,
366 APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL,
367 APR_OS_DEFAULT, pool);
368 if (status != APR_SUCCESS) {
369 return status;
370 }
371
372 /* ftok() (on solaris at least) requires that the file actually
373 * exist before calling ftok(). */
374 new_m->shmkey = our_ftok(filename);
375 if (new_m->shmkey == (key_t)-1) {
376 apr_file_close(file);
377 return errno;
378 }
379
380 if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize,
381 SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) {
382 apr_file_close(file);
383 return errno;
384 }
385
386 if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
387 apr_file_close(file);
388 return errno;
389 }
390 new_m->usable = new_m->base;
391
392 if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
393 apr_file_close(file);
394 return errno;
395 }
396 apr_uid_current(&uid, &gid, pool);
397 shmbuf.shm_perm.uid = uid;
398 shmbuf.shm_perm.gid = gid;
399 if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
400 apr_file_close(file);
401 return errno;
402 }
403
404 nbytes = sizeof(reqsize);
405 status = apr_file_write(file, (const void *)&reqsize,
406 &nbytes);
407 if (status != APR_SUCCESS) {
408 apr_file_close(file);
409 return status;
410 }
411 status = apr_file_close(file);
412 if (status != APR_SUCCESS) {
413 return status;
414 }
415
416 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
417 apr_pool_cleanup_null);
418 *m = new_m;
419 return APR_SUCCESS;
420
421 #else
422 return APR_ENOTIMPL;
423 #endif
424 }
425 }
426
apr_shm_create_ex(apr_shm_t ** m,apr_size_t reqsize,const char * filename,apr_pool_t * p,apr_int32_t flags)427 APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m,
428 apr_size_t reqsize,
429 const char *filename,
430 apr_pool_t *p,
431 apr_int32_t flags)
432 {
433 return apr_shm_create(m, reqsize, filename, p);
434 }
435
apr_shm_remove(const char * filename,apr_pool_t * pool)436 APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
437 apr_pool_t *pool)
438 {
439 #if APR_USE_SHMEM_SHMGET
440 apr_status_t status;
441 apr_file_t *file;
442 key_t shmkey;
443 int shmid;
444 #endif
445
446 #if APR_USE_SHMEM_MMAP_TMP
447 return apr_file_remove(filename, pool);
448 #elif APR_USE_SHMEM_MMAP_SHM
449 const char *shm_name = make_shm_open_safe_name(filename, pool);
450 if (shm_unlink(shm_name) == -1) {
451 return errno;
452 }
453 return APR_SUCCESS;
454 #elif APR_USE_SHMEM_SHMGET
455 /* Presume that the file already exists; just open for writing */
456 status = apr_file_open(&file, filename, APR_FOPEN_WRITE,
457 APR_OS_DEFAULT, pool);
458 if (status) {
459 return status;
460 }
461
462 /* ftok() (on solaris at least) requires that the file actually
463 * exist before calling ftok(). */
464 shmkey = our_ftok(filename);
465 if (shmkey == (key_t)-1) {
466 goto shm_remove_failed;
467 }
468
469 apr_file_close(file);
470
471 if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) {
472 goto shm_remove_failed;
473 }
474
475 /* Indicate that the segment is to be destroyed as soon
476 * as all processes have detached. This also disallows any
477 * new attachments to the segment. */
478 if (shmctl(shmid, IPC_RMID, NULL) == -1) {
479 goto shm_remove_failed;
480 }
481 return apr_file_remove(filename, pool);
482
483 shm_remove_failed:
484 status = errno;
485 /* ensure the file has been removed anyway. */
486 apr_file_remove(filename, pool);
487 return status;
488 #else
489
490 /* No support for anonymous shm */
491 return APR_ENOTIMPL;
492 #endif
493 }
494
apr_shm_delete(apr_shm_t * m)495 APR_DECLARE(apr_status_t) apr_shm_delete(apr_shm_t *m)
496 {
497 if (m->filename) {
498 return apr_shm_remove(m->filename, m->pool);
499 }
500 else {
501 return APR_ENOTIMPL;
502 }
503 }
504
apr_shm_destroy(apr_shm_t * m)505 APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
506 {
507 return apr_pool_cleanup_run(m->pool, m, shm_cleanup_owner);
508 }
509
shm_cleanup_attach(void * m_)510 static apr_status_t shm_cleanup_attach(void *m_)
511 {
512 apr_shm_t *m = (apr_shm_t *)m_;
513
514 if (m->filename == NULL) {
515 /* It doesn't make sense to detach from an anonymous memory segment. */
516 return APR_EINVAL;
517 }
518 else {
519 #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
520 if (munmap(m->base, m->realsize) == -1) {
521 return errno;
522 }
523 return APR_SUCCESS;
524 #elif APR_USE_SHMEM_SHMGET
525 if (shmdt(m->base) == -1) {
526 return errno;
527 }
528 return APR_SUCCESS;
529 #else
530 return APR_ENOTIMPL;
531 #endif
532 }
533 }
534
apr_shm_attach(apr_shm_t ** m,const char * filename,apr_pool_t * pool)535 APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
536 const char *filename,
537 apr_pool_t *pool)
538 {
539 if (filename == NULL) {
540 /* It doesn't make sense to attach to a segment if you don't know
541 * the filename. */
542 return APR_EINVAL;
543 }
544 else {
545 #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
546 apr_shm_t *new_m;
547 apr_status_t status;
548 int tmpfd;
549 apr_file_t *file; /* file where metadata is stored */
550 apr_size_t nbytes;
551
552 new_m = apr_palloc(pool, sizeof(apr_shm_t));
553 new_m->pool = pool;
554 new_m->filename = apr_pstrdup(pool, filename);
555 #if APR_USE_SHMEM_MMAP_SHM
556 const char *shm_name = make_shm_open_safe_name(filename, pool);
557
558 /* FIXME: SysV uses 0600... should we? */
559 tmpfd = shm_open(shm_name, O_RDWR, 0644);
560 if (tmpfd == -1) {
561 return errno;
562 }
563
564 status = apr_os_file_put(&file, &tmpfd,
565 APR_READ | APR_WRITE,
566 pool);
567 if (status != APR_SUCCESS) {
568 return status;
569 }
570
571 #elif APR_USE_SHMEM_MMAP_TMP
572 status = apr_file_open(&file, filename,
573 APR_READ | APR_WRITE,
574 APR_OS_DEFAULT, pool);
575 if (status != APR_SUCCESS) {
576 return status;
577 }
578 status = apr_os_file_get(&tmpfd, file);
579 if (status != APR_SUCCESS) {
580 return status;
581 }
582 #else
583 return APR_ENOTIMPL;
584 #endif
585
586 nbytes = sizeof(new_m->realsize);
587 status = apr_file_read(file, (void *)&(new_m->realsize),
588 &nbytes);
589 if (status != APR_SUCCESS) {
590 return status;
591 }
592
593 status = apr_os_file_get(&tmpfd, file);
594 if (status != APR_SUCCESS) {
595 apr_file_close(file); /* ignore errors, we're failing */
596 apr_file_remove(new_m->filename, new_m->pool);
597 return status;
598 }
599
600 new_m->reqsize = new_m->realsize - sizeof(apr_size_t);
601
602 new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
603 MAP_SHARED, tmpfd, 0);
604 /* FIXME: check for errors */
605
606 status = apr_file_close(file);
607 if (status != APR_SUCCESS) {
608 return status;
609 }
610
611 /* metadata isn't part of the usable segment */
612 new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
613
614 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach,
615 apr_pool_cleanup_null);
616 *m = new_m;
617 return APR_SUCCESS;
618
619 #elif APR_USE_SHMEM_SHMGET
620 apr_shm_t *new_m;
621 apr_status_t status;
622 apr_file_t *file; /* file where metadata is stored */
623 apr_size_t nbytes;
624
625 new_m = apr_palloc(pool, sizeof(apr_shm_t));
626
627 status = apr_file_open(&file, filename,
628 APR_FOPEN_READ, APR_OS_DEFAULT, pool);
629 if (status != APR_SUCCESS) {
630 return status;
631 }
632
633 nbytes = sizeof(new_m->reqsize);
634 status = apr_file_read(file, (void *)&(new_m->reqsize),
635 &nbytes);
636 if (status != APR_SUCCESS) {
637 return status;
638 }
639 status = apr_file_close(file);
640 if (status != APR_SUCCESS) {
641 return status;
642 }
643
644 new_m->filename = apr_pstrdup(pool, filename);
645 new_m->pool = pool;
646 new_m->shmkey = our_ftok(filename);
647 if (new_m->shmkey == (key_t)-1) {
648 return errno;
649 }
650 if ((new_m->shmid = shmget(new_m->shmkey, 0, SHM_R | SHM_W)) == -1) {
651 return errno;
652 }
653 if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
654 return errno;
655 }
656 new_m->usable = new_m->base;
657 new_m->realsize = new_m->reqsize;
658
659 apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach,
660 apr_pool_cleanup_null);
661 *m = new_m;
662 return APR_SUCCESS;
663
664 #else
665 return APR_ENOTIMPL;
666 #endif
667 }
668 }
669
apr_shm_attach_ex(apr_shm_t ** m,const char * filename,apr_pool_t * pool,apr_int32_t flags)670 APR_DECLARE(apr_status_t) apr_shm_attach_ex(apr_shm_t **m,
671 const char *filename,
672 apr_pool_t *pool,
673 apr_int32_t flags)
674 {
675 return apr_shm_attach(m, filename, pool);
676 }
677
apr_shm_detach(apr_shm_t * m)678 APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
679 {
680 apr_status_t rv = shm_cleanup_attach(m);
681 apr_pool_cleanup_kill(m->pool, m, shm_cleanup_attach);
682 return rv;
683 }
684
apr_shm_baseaddr_get(const apr_shm_t * m)685 APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
686 {
687 return m->usable;
688 }
689
apr_shm_size_get(const apr_shm_t * m)690 APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
691 {
692 return m->reqsize;
693 }
694
APR_PERMS_SET_IMPLEMENT(shm)695 APR_PERMS_SET_IMPLEMENT(shm)
696 {
697 #if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
698 struct shmid_ds shmbuf;
699 int shmid;
700 apr_shm_t *m = (apr_shm_t *)theshm;
701
702 if ((shmid = shmget(m->shmkey, 0, SHM_R | SHM_W)) == -1) {
703 return errno;
704 }
705 shmbuf.shm_perm.uid = uid;
706 shmbuf.shm_perm.gid = gid;
707 shmbuf.shm_perm.mode = apr_unix_perms2mode(perms);
708 if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
709 return errno;
710 }
711 return APR_SUCCESS;
712 #else
713 return APR_ENOTIMPL;
714 #endif
715 }
716
717 APR_POOL_IMPLEMENT_ACCESSOR(shm)
718
APR_DECLARE(apr_status_t)719 APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
720 apr_shm_t *shm)
721 {
722 return APR_ENOTIMPL;
723 }
724
apr_os_shm_put(apr_shm_t ** m,apr_os_shm_t * osshm,apr_pool_t * pool)725 APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
726 apr_os_shm_t *osshm,
727 apr_pool_t *pool)
728 {
729 return APR_ENOTIMPL;
730 }
731
732