~ubuntu-branches/ubuntu/feisty/apache2/feisty-security

« back to all changes in this revision

Viewing changes to srclib/apr/shmem/unix/shm.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
 
 
19
#include "apr_general.h"
 
20
#include "apr_errno.h"
 
21
#include "apr_user.h"
 
22
#include "apr_strings.h"
 
23
 
 
24
static apr_status_t shm_cleanup_owner(void *m_)
 
25
{
 
26
    apr_shm_t *m = (apr_shm_t *)m_;
 
27
 
 
28
    /* anonymous shared memory */
 
29
    if (m->filename == NULL) {
 
30
#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON
 
31
        if (munmap(m->base, m->realsize) == -1) {
 
32
            return errno;
 
33
        }
 
34
        return APR_SUCCESS;
 
35
#endif
 
36
#if APR_USE_SHMEM_SHMGET_ANON
 
37
        if (shmdt(m->base) == -1) {
 
38
            return errno;
 
39
        }
 
40
        /* This segment will automatically remove itself after all
 
41
         * references have detached. */
 
42
        return APR_SUCCESS;
 
43
#endif
 
44
    }
 
45
 
 
46
    /* name-based shared memory */
 
47
    else {
 
48
#if APR_USE_SHMEM_MMAP_TMP
 
49
        if (munmap(m->base, m->realsize) == -1) {
 
50
            return errno;
 
51
        }
 
52
        return apr_file_remove(m->filename, m->pool);
 
53
#endif
 
54
#if APR_USE_SHMEM_MMAP_SHM
 
55
        if (munmap(m->base, m->realsize) == -1) {
 
56
            return errno;
 
57
        }
 
58
        if (shm_unlink(m->filename) == -1) {
 
59
            return errno;
 
60
        }
 
61
        return APR_SUCCESS;
 
62
#endif
 
63
#if APR_USE_SHMEM_SHMGET
 
64
        /* Indicate that the segment is to be destroyed as soon
 
65
         * as all processes have detached. This also disallows any
 
66
         * new attachments to the segment. */
 
67
        if (shmctl(m->shmid, IPC_RMID, NULL) == -1) {
 
68
            return errno;
 
69
        }
 
70
        if (shmdt(m->base) == -1) {
 
71
            return errno;
 
72
        }
 
73
        return apr_file_remove(m->filename, m->pool);
 
74
#endif
 
75
    }
 
76
 
 
77
    return APR_ENOTIMPL;
 
78
}
 
79
 
 
80
APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
 
81
                                         apr_size_t reqsize, 
 
82
                                         const char *filename,
 
83
                                         apr_pool_t *pool)
 
84
{
 
85
    apr_shm_t *new_m;
 
86
    apr_status_t status;
 
87
#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
 
88
    struct shmid_ds shmbuf;
 
89
    apr_uid_t uid;
 
90
    apr_gid_t gid;
 
91
#endif
 
92
#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \
 
93
    APR_USE_SHMEM_MMAP_ZERO
 
94
    int tmpfd;
 
95
#endif
 
96
#if APR_USE_SHMEM_SHMGET
 
97
    apr_size_t nbytes;
 
98
    key_t shmkey;
 
99
#endif
 
100
#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET || \
 
101
    APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
 
102
    apr_file_t *file;   /* file where metadata is stored */
 
103
#endif
 
104
 
 
105
    /* Check if they want anonymous or name-based shared memory */
 
106
    if (filename == NULL) {
 
107
#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON
 
108
        new_m = apr_palloc(pool, sizeof(apr_shm_t));
 
109
        new_m->pool = pool;
 
110
        new_m->reqsize = reqsize;
 
111
        new_m->realsize = reqsize + 
 
112
            APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */
 
113
        new_m->filename = NULL;
 
114
    
 
115
#if APR_USE_SHMEM_MMAP_ZERO
 
116
        status = apr_file_open(&file, "/dev/zero", APR_READ | APR_WRITE, 
 
117
                               APR_OS_DEFAULT, pool);
 
118
        if (status != APR_SUCCESS) {
 
119
            return status;
 
120
        }
 
121
        status = apr_os_file_get(&tmpfd, file);
 
122
        if (status != APR_SUCCESS) {
 
123
            return status;
 
124
        }
 
125
 
 
126
        new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE,
 
127
                           MAP_SHARED, tmpfd, 0);
 
128
        if (new_m->base == (void *)MAP_FAILED) {
 
129
            return errno;
 
130
        }
 
131
 
 
132
        status = apr_file_close(file);
 
133
        if (status != APR_SUCCESS) {
 
134
            return status;
 
135
        }
 
136
 
 
137
        /* store the real size in the metadata */
 
138
        *(apr_size_t*)(new_m->base) = new_m->realsize;
 
139
        /* metadata isn't usable */
 
140
        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
 
141
 
 
142
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
 
143
                                  apr_pool_cleanup_null);
 
144
        *m = new_m;
 
145
        return APR_SUCCESS;
 
146
 
 
147
#elif APR_USE_SHMEM_MMAP_ANON
 
148
        new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE,
 
149
                           MAP_ANON|MAP_SHARED, -1, 0);
 
150
        if (new_m->base == (void *)MAP_FAILED) {
 
151
            return errno;
 
152
        }
 
153
 
 
154
        /* store the real size in the metadata */
 
155
        *(apr_size_t*)(new_m->base) = new_m->realsize;
 
156
        /* metadata isn't usable */
 
157
        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
 
158
 
 
159
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
 
160
                                  apr_pool_cleanup_null);
 
161
        *m = new_m;
 
162
        return APR_SUCCESS;
 
163
 
 
164
#endif /* APR_USE_SHMEM_MMAP_ZERO */
 
165
#endif /* APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON */
 
166
#if APR_USE_SHMEM_SHMGET_ANON
 
167
 
 
168
        new_m = apr_palloc(pool, sizeof(apr_shm_t));
 
169
        new_m->pool = pool;
 
170
        new_m->reqsize = reqsize;
 
171
        new_m->realsize = reqsize;
 
172
        new_m->filename = NULL;
 
173
 
 
174
        if ((new_m->shmid = shmget(IPC_PRIVATE, new_m->realsize,
 
175
                                   SHM_R | SHM_W | IPC_CREAT)) < 0) {
 
176
            return errno;
 
177
        }
 
178
 
 
179
        if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
 
180
            return errno;
 
181
        }
 
182
        new_m->usable = new_m->base;
 
183
 
 
184
        if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
 
185
            return errno;
 
186
        }
 
187
        apr_uid_current(&uid, &gid, pool);
 
188
        shmbuf.shm_perm.uid = uid;
 
189
        shmbuf.shm_perm.gid = gid;
 
190
        if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
 
191
            return errno;
 
192
        }
 
193
 
 
194
        /* Remove the segment once use count hits zero.
 
195
         * We will not attach to this segment again, since it is
 
196
         * anonymous memory, so it is ok to mark it for deletion.
 
197
         */
 
198
        if (shmctl(new_m->shmid, IPC_RMID, NULL) == -1) {
 
199
            return errno;
 
200
        }
 
201
 
 
202
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
 
203
                                  apr_pool_cleanup_null);
 
204
        *m = new_m;
 
205
        return APR_SUCCESS;
 
206
#endif /* APR_USE_SHMEM_SHMGET_ANON */
 
207
        /* It is an error if they want anonymous memory but we don't have it. */
 
208
        return APR_ENOTIMPL; /* requested anonymous but we don't have it */
 
209
    }
 
210
 
 
211
    /* Name-based shared memory */
 
212
    else {
 
213
        new_m = apr_palloc(pool, sizeof(apr_shm_t));
 
214
        new_m->pool = pool;
 
215
        new_m->reqsize = reqsize;
 
216
        new_m->filename = apr_pstrdup(pool, filename);
 
217
 
 
218
#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
 
219
        new_m->realsize = reqsize + 
 
220
            APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */
 
221
        /* FIXME: Ignore error for now. *
 
222
         * status = apr_file_remove(file, pool);*/
 
223
        status = APR_SUCCESS;
 
224
    
 
225
#if APR_USE_SHMEM_MMAP_TMP
 
226
        /* FIXME: Is APR_OS_DEFAULT sufficient? */
 
227
        status = apr_file_open(&file, filename, 
 
228
                               APR_READ | APR_WRITE | APR_CREATE | APR_EXCL,
 
229
                               APR_OS_DEFAULT, pool);
 
230
        if (status != APR_SUCCESS) {
 
231
            return status;
 
232
        }
 
233
 
 
234
        status = apr_os_file_get(&tmpfd, file);
 
235
        if (status != APR_SUCCESS) {
 
236
            apr_file_close(file); /* ignore errors, we're failing */
 
237
            apr_file_remove(new_m->filename, new_m->pool);
 
238
            return status;
 
239
        }
 
240
 
 
241
        status = apr_file_trunc(file, new_m->realsize);
 
242
        if (status != APR_SUCCESS) {
 
243
            apr_file_close(file); /* ignore errors, we're failing */
 
244
            apr_file_remove(new_m->filename, new_m->pool);
 
245
            return status;
 
246
        }
 
247
 
 
248
        new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
 
249
                           MAP_SHARED, tmpfd, 0);
 
250
        /* FIXME: check for errors */
 
251
 
 
252
        status = apr_file_close(file);
 
253
        if (status != APR_SUCCESS) {
 
254
            return status;
 
255
        }
 
256
#endif /* APR_USE_SHMEM_MMAP_TMP */
 
257
#if APR_USE_SHMEM_MMAP_SHM
 
258
        tmpfd = shm_open(filename, O_RDWR | O_CREAT | O_EXCL, 0644);
 
259
        if (tmpfd == -1) {
 
260
            return errno;
 
261
        }
 
262
 
 
263
        status = apr_os_file_put(&file, &tmpfd,
 
264
                                 APR_READ | APR_WRITE | APR_CREATE | APR_EXCL,
 
265
                                 pool); 
 
266
        if (status != APR_SUCCESS) {
 
267
            return status;
 
268
        }
 
269
 
 
270
        status = apr_file_trunc(file, new_m->realsize);
 
271
        if (status != APR_SUCCESS) {
 
272
            shm_unlink(filename); /* we're failing, remove the object */
 
273
            return status;
 
274
        }
 
275
        new_m->base = mmap(NULL, reqsize, PROT_READ | PROT_WRITE,
 
276
                           MAP_SHARED, tmpfd, 0);
 
277
 
 
278
        /* FIXME: check for errors */
 
279
 
 
280
        status = apr_file_close(file);
 
281
        if (status != APR_SUCCESS) {
 
282
            return status;
 
283
        }
 
284
#endif /* APR_USE_SHMEM_MMAP_SHM */
 
285
 
 
286
        /* store the real size in the metadata */
 
287
        *(apr_size_t*)(new_m->base) = new_m->realsize;
 
288
        /* metadata isn't usable */
 
289
        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
 
290
 
 
291
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
 
292
                                  apr_pool_cleanup_null);
 
293
        *m = new_m;
 
294
        return APR_SUCCESS;
 
295
 
 
296
#endif /* APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM */
 
297
 
 
298
#if APR_USE_SHMEM_SHMGET
 
299
        new_m->realsize = reqsize;
 
300
 
 
301
        /* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think. */
 
302
        status = apr_file_open(&file, filename, 
 
303
                               APR_WRITE | APR_CREATE | APR_EXCL,
 
304
                               APR_OS_DEFAULT, pool);
 
305
        if (status != APR_SUCCESS) {
 
306
            return status;
 
307
        }
 
308
 
 
309
        /* ftok() (on solaris at least) requires that the file actually
 
310
         * exist before calling ftok(). */
 
311
        shmkey = ftok(filename, 1);
 
312
        if (shmkey == (key_t)-1) {
 
313
            return errno;
 
314
        }
 
315
 
 
316
        if ((new_m->shmid = shmget(shmkey, new_m->realsize,
 
317
                                   SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) {
 
318
            return errno;
 
319
        }
 
320
 
 
321
        if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
 
322
            return errno;
 
323
        }
 
324
        new_m->usable = new_m->base;
 
325
 
 
326
        if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
 
327
            return errno;
 
328
        }
 
329
        apr_uid_current(&uid, &gid, pool);
 
330
        shmbuf.shm_perm.uid = uid;
 
331
        shmbuf.shm_perm.gid = gid;
 
332
        if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
 
333
            return errno;
 
334
        }
 
335
 
 
336
        nbytes = sizeof(reqsize);
 
337
        status = apr_file_write(file, (const void *)&reqsize,
 
338
                                &nbytes);
 
339
        if (status != APR_SUCCESS) {
 
340
            return status;
 
341
        }
 
342
        status = apr_file_close(file);
 
343
        if (status != APR_SUCCESS) {
 
344
            return status;
 
345
        }
 
346
 
 
347
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner,
 
348
                                  apr_pool_cleanup_null);
 
349
        *m = new_m; 
 
350
        return APR_SUCCESS;
 
351
 
 
352
#endif /* APR_USE_SHMEM_SHMGET */
 
353
    }
 
354
 
 
355
    return APR_ENOTIMPL;
 
356
}
 
357
 
 
358
APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
 
359
                                         apr_pool_t *pool)
 
360
{
 
361
#if APR_USE_SHMEM_SHMGET
 
362
    apr_status_t status;
 
363
    apr_file_t *file;  
 
364
    key_t shmkey;
 
365
    int shmid;
 
366
#endif
 
367
 
 
368
#if APR_USE_SHMEM_MMAP_TMP
 
369
    return apr_file_remove(filename, pool);
 
370
#endif
 
371
#if APR_USE_SHMEM_MMAP_SHM
 
372
    if (shm_unlink(filename) == -1) {
 
373
        return errno;
 
374
    }
 
375
    return APR_SUCCESS;
 
376
#endif
 
377
#if APR_USE_SHMEM_SHMGET
 
378
    /* Presume that the file already exists; just open for writing */    
 
379
    status = apr_file_open(&file, filename, APR_WRITE,
 
380
                           APR_OS_DEFAULT, pool);
 
381
    if (status) {
 
382
        return status;
 
383
    }
 
384
 
 
385
    /* ftok() (on solaris at least) requires that the file actually
 
386
     * exist before calling ftok(). */
 
387
    shmkey = ftok(filename, 1);
 
388
    if (shmkey == (key_t)-1) {
 
389
        goto shm_remove_failed;
 
390
    }
 
391
 
 
392
    apr_file_close(file);
 
393
 
 
394
    if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) {
 
395
        goto shm_remove_failed;
 
396
    }
 
397
 
 
398
    /* Indicate that the segment is to be destroyed as soon
 
399
     * as all processes have detached. This also disallows any
 
400
     * new attachments to the segment. */
 
401
    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
 
402
        goto shm_remove_failed;
 
403
    }
 
404
    return apr_file_remove(filename, pool);
 
405
 
 
406
shm_remove_failed:
 
407
    status = errno;
 
408
    /* ensure the file has been removed anyway. */
 
409
    apr_file_remove(filename, pool);
 
410
    return status;
 
411
#endif
 
412
 
 
413
    /* No support for anonymous shm */
 
414
    return APR_ENOTIMPL;
 
415
 
416
 
 
417
APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
 
418
{
 
419
    return apr_pool_cleanup_run(m->pool, m, shm_cleanup_owner);
 
420
}
 
421
 
 
422
static apr_status_t shm_cleanup_attach(void *m_)
 
423
{
 
424
    apr_shm_t *m = (apr_shm_t *)m_;
 
425
 
 
426
    if (m->filename == NULL) {
 
427
        /* It doesn't make sense to detach from an anonymous memory segment. */
 
428
        return APR_EINVAL;
 
429
    }
 
430
    else {
 
431
#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
 
432
        if (munmap(m->base, m->realsize) == -1) {
 
433
            return errno;
 
434
        }
 
435
        return APR_SUCCESS;
 
436
#endif /* APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM */
 
437
#if APR_USE_SHMEM_SHMGET
 
438
        if (shmdt(m->base) == -1) {
 
439
            return errno;
 
440
        }
 
441
        return APR_SUCCESS;
 
442
#endif
 
443
    }
 
444
 
 
445
    return APR_ENOTIMPL;
 
446
}
 
447
 
 
448
APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
 
449
                                         const char *filename,
 
450
                                         apr_pool_t *pool)
 
451
{
 
452
    if (filename == NULL) {
 
453
        /* It doesn't make sense to attach to a segment if you don't know
 
454
         * the filename. */
 
455
        return APR_EINVAL;
 
456
    }
 
457
    else {
 
458
#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM
 
459
        apr_shm_t *new_m;
 
460
        apr_status_t status;
 
461
        int tmpfd;
 
462
        apr_file_t *file;   /* file where metadata is stored */
 
463
        apr_size_t nbytes;
 
464
 
 
465
        new_m = apr_palloc(pool, sizeof(apr_shm_t));
 
466
        new_m->pool = pool;
 
467
        new_m->filename = apr_pstrdup(pool, filename);
 
468
 
 
469
        status = apr_file_open(&file, filename, 
 
470
                               APR_READ | APR_WRITE,
 
471
                               APR_OS_DEFAULT, pool);
 
472
        if (status != APR_SUCCESS) {
 
473
            return status;
 
474
        }
 
475
        status = apr_os_file_get(&tmpfd, file);
 
476
        if (status != APR_SUCCESS) {
 
477
            return status;
 
478
        }
 
479
 
 
480
        nbytes = sizeof(new_m->realsize);
 
481
        status = apr_file_read(file, (void *)&(new_m->realsize),
 
482
                               &nbytes);
 
483
        if (status != APR_SUCCESS) {
 
484
            return status;
 
485
        }
 
486
 
 
487
        status = apr_os_file_get(&tmpfd, file);
 
488
        if (status != APR_SUCCESS) {
 
489
            apr_file_close(file); /* ignore errors, we're failing */
 
490
            apr_file_remove(new_m->filename, new_m->pool);
 
491
            return status;
 
492
        }
 
493
 
 
494
        new_m->reqsize = new_m->realsize - sizeof(apr_size_t);
 
495
 
 
496
        new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE,
 
497
                           MAP_SHARED, tmpfd, 0);
 
498
        /* FIXME: check for errors */
 
499
        
 
500
        status = apr_file_close(file);
 
501
        if (status != APR_SUCCESS) {
 
502
            return status;
 
503
        }
 
504
 
 
505
        /* metadata isn't part of the usable segment */
 
506
        new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t));
 
507
 
 
508
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach,
 
509
                                  apr_pool_cleanup_null);
 
510
        *m = new_m;
 
511
        return APR_SUCCESS;
 
512
 
 
513
#endif /* APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM */
 
514
#if APR_USE_SHMEM_SHMGET
 
515
        apr_shm_t *new_m;
 
516
        apr_status_t status;
 
517
        apr_file_t *file;   /* file where metadata is stored */
 
518
        apr_size_t nbytes;
 
519
        key_t shmkey;
 
520
 
 
521
        new_m = apr_palloc(pool, sizeof(apr_shm_t));
 
522
 
 
523
        status = apr_file_open(&file, filename, 
 
524
                               APR_READ, APR_OS_DEFAULT, pool);
 
525
        if (status != APR_SUCCESS) {
 
526
            return status;
 
527
        }
 
528
 
 
529
        nbytes = sizeof(new_m->reqsize);
 
530
        status = apr_file_read(file, (void *)&(new_m->reqsize),
 
531
                               &nbytes);
 
532
        if (status != APR_SUCCESS) {
 
533
            return status;
 
534
        }
 
535
        status = apr_file_close(file);
 
536
        if (status != APR_SUCCESS) {
 
537
            return status;
 
538
        }
 
539
 
 
540
        new_m->filename = apr_pstrdup(pool, filename);
 
541
        new_m->pool = pool;
 
542
        shmkey = ftok(filename, 1);
 
543
        if (shmkey == (key_t)-1) {
 
544
            return errno;
 
545
        }
 
546
        if ((new_m->shmid = shmget(shmkey, 0, SHM_R | SHM_W)) == -1) {
 
547
            return errno;
 
548
        }
 
549
        if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
 
550
            return errno;
 
551
        }
 
552
        new_m->usable = new_m->base;
 
553
        new_m->realsize = new_m->reqsize;
 
554
 
 
555
        apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach,
 
556
                                  apr_pool_cleanup_null);
 
557
        *m = new_m;
 
558
        return APR_SUCCESS;
 
559
 
 
560
#endif /* APR_USE_SHMEM_SHMGET */
 
561
    }
 
562
 
 
563
    return APR_ENOTIMPL;
 
564
}
 
565
 
 
566
APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m)
 
567
{
 
568
    apr_status_t rv = shm_cleanup_attach(m);
 
569
    apr_pool_cleanup_kill(m->pool, m, shm_cleanup_attach);
 
570
    return rv;
 
571
}
 
572
 
 
573
APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m)
 
574
{
 
575
    return m->usable;
 
576
}
 
577
 
 
578
APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m)
 
579
{
 
580
    return m->reqsize;
 
581
}
 
582
 
 
583
APR_POOL_IMPLEMENT_ACCESSOR(shm)
 
584
 
 
585
APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm,
 
586
                                         apr_shm_t *shm)
 
587
{
 
588
    return APR_ENOTIMPL;
 
589
}
 
590
 
 
591
APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m,
 
592
                                         apr_os_shm_t *osshm,
 
593
                                         apr_pool_t *pool)
 
594
{
 
595
    return APR_ENOTIMPL;
 
596
}    
 
597