~ubuntu-branches/ubuntu/precise/eglibc/precise

« back to all changes in this revision

Viewing changes to debian/patches/hurd-i386/submitted-sysvshm.diff

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2011-10-04 17:48:26 UTC
  • mfrom: (216.1.23 oneiric)
  • Revision ID: package-import@ubuntu.com-20111004174826-2cyb9ewn3ucymlsx
Tags: 2.13-20ubuntu5
libc6-dev: Don't break the current {gnat,gcj}-4.4-base versons. LP: #853688.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# All lines beginning with `# DP:' are a description of the patch.
 
2
# DP: Description: Implement SysV shared memory for GNU/Hurd.
 
3
# DP: Dpatch author: Michael Banck <mbanck@debian.org>
 
4
# DP: Patch author: Marcus Brinkmann
 
5
# DP: Upstream status: Unsubmitted, copyright assignments needed
 
6
# DP: Date: 2005-07-11
 
7
 
 
8
2005-07-11  Marcus Brinkmann  <marcus@gnu.org>
 
9
 
 
10
        * hurd/Makefile (routines): Add sysvshm.
 
11
        (distribute): Add sysvshm.h.
 
12
        * hurd/sysvshm.h: New file.
 
13
        * hurd/sysvshm.c: New file.
 
14
        * sysdeps/mach/hurd/bits/stat.h (S_IMMAP0): New macro.
 
15
        (S_ISPARE): Unset the S_IMMAP0 flag.
 
16
        * sysdeps/mach/hurd/ftok.c: New file.
 
17
        * sysdeps/mach/hurd/shmat.c: New file.
 
18
        * sysdeps/mach/hurd/shmctl.c: New file.
 
19
        * sysdeps/mach/hurd/shmdt.c: New file.
 
20
        * sysdeps/mach/hurd/bits/posix_opt.h: Define _XOPEN_SHM to 1.
 
21
 
 
22
---
 
23
 hurd/Makefile                      |    3 
 
24
 hurd/sysvshm.c                     |   96 ++++++++++++++
 
25
 hurd/sysvshm.h                     |   47 +++++++
 
26
 sysdeps/mach/hurd/bits/posix_opt.h |    4 
 
27
 sysdeps/mach/hurd/ftok.c           |   43 ++++++
 
28
 sysdeps/mach/hurd/shmat.c          |   78 +++++++++++
 
29
 sysdeps/mach/hurd/shmctl.c         |  132 +++++++++++++++++++
 
30
 sysdeps/mach/hurd/shmdt.c          |   51 +++++++
 
31
 sysdeps/mach/hurd/shmget.c         |  245 +++++++++++++++++++++++++++++++++++++
 
32
 9 files changed, 696 insertions(+), 3 deletions(-)
 
33
 
 
34
--- a/hurd/Makefile
 
35
+++ b/hurd/Makefile
 
36
@@ -60,6 +60,7 @@
 
37
           vpprintf \
 
38
           ports-get ports-set hurdports hurdmsg \
 
39
           errno-loc \
 
40
+          sysvshm \
 
41
           $(sig) $(dtable) $(inlines) port-cleanup report-wait xattr
 
42
 sig    = hurdsig hurdfault siginfo hurd-raise preempt-sig \
 
43
          trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind \
 
44
@@ -68,7 +69,7 @@
 
45
          getdport openport \
 
46
          fd-close fd-read fd-write hurdioctl ctty-input ctty-output
 
47
 inlines = $(inline-headers:%.h=%-inlines)
 
48
-distribute = hurdstartup.h hurdfault.h hurdhost.h \
 
49
+distribute = hurdstartup.h hurdfault.h hurdhost.h sysvshm.h \
 
50
             faultexc.defs intr-rpc.defs intr-rpc.h intr-msg.h Notes
 
51
 
 
52
 # XXX this is a temporary hack; see hurdmalloc.h
 
53
--- /dev/null
 
54
+++ b/hurd/sysvshm.c
 
55
@@ -0,0 +1,96 @@
 
56
+/* Copyright (C) 2005 Free Software Foundation, Inc.
 
57
+   This file is part of the GNU C Library.
 
58
+
 
59
+   The GNU C Library is free software; you can redistribute it and/or
 
60
+   modify it under the terms of the GNU Lesser General Public
 
61
+   License as published by the Free Software Foundation; either
 
62
+   version 2.1 of the License, or (at your option) any later version.
 
63
+
 
64
+   The GNU C Library is distributed in the hope that it will be useful,
 
65
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
66
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
67
+   Lesser General Public License for more details.
 
68
+
 
69
+   You should have received a copy of the GNU Lesser General Public
 
70
+   License along with the GNU C Library; if not, write to the Free
 
71
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
72
+   02111-1307 USA.  */
 
73
+
 
74
+#include <string.h>
 
75
+#include <stdlib.h>
 
76
+#include <stdio.h>
 
77
+#include <stddef.h>
 
78
+#include <errno.h>
 
79
+#include <unistd.h>
 
80
+#include <fcntl.h>
 
81
+#include <dirent.h>
 
82
+#include <sys/stat.h>
 
83
+#include <sys/shm.h>
 
84
+
 
85
+
 
86
+/* Description of an shm attachment.  */
 
87
+struct sysvshm_attach
 
88
+{
 
89
+  /* Linked list.  */
 
90
+  struct sysvshm_attach *next;
 
91
+
 
92
+  /* Map address.  */
 
93
+  void *addr;
 
94
+
 
95
+  /* Map size.  */
 
96
+  size_t size;
 
97
+};
 
98
+
 
99
+/* List of attachments.  */
 
100
+static struct sysvshm_attach *attach_list;
 
101
+
 
102
+/* A lock to protect the linked list of shared memory attachments.  */
 
103
+static struct mutex sysvshm_lock = MUTEX_INITIALIZER;
 
104
+
 
105
+
 
106
+/* Adds a segment attachment.  */
 
107
+error_t
 
108
+__sysvshm_add (void *addr, size_t size)
 
109
+{
 
110
+  struct sysvshm_attach *shm;
 
111
+
 
112
+  shm = malloc (sizeof (*shm));
 
113
+  if (!shm)
 
114
+    return errno;
 
115
+
 
116
+  __mutex_lock (&sysvshm_lock);
 
117
+  shm->addr = addr;
 
118
+  shm->size = size;
 
119
+  shm->next = attach_list;
 
120
+  attach_list = shm;
 
121
+  __mutex_unlock (&sysvshm_lock);
 
122
+
 
123
+  return 0;
 
124
+}
 
125
+
 
126
+/* Removes a segment attachment.  Returns its size if found, or EINVAL
 
127
+   otherwise.  */
 
128
+error_t
 
129
+__sysvshm_remove (void *addr, size_t *size)
 
130
+{
 
131
+  struct sysvshm_attach *shm;
 
132
+  struct sysvshm_attach **pshm = &attach_list;
 
133
+
 
134
+  __mutex_lock (&sysvshm_lock);
 
135
+  shm = attach_list;
 
136
+  while (shm)
 
137
+    {
 
138
+      shm = *pshm;
 
139
+      if (shm->addr == addr)
 
140
+       {
 
141
+         *pshm = shm->next;
 
142
+         *size = shm->size;
 
143
+         __mutex_unlock (&sysvshm_lock);
 
144
+         return 0;
 
145
+       }
 
146
+      pshm = &shm->next;
 
147
+      shm = shm->next;
 
148
+    }
 
149
+  __mutex_unlock (&sysvshm_lock);
 
150
+  return EINVAL;
 
151
+}
 
152
--- /dev/null
 
153
+++ b/hurd/sysvshm.h
 
154
@@ -0,0 +1,47 @@
 
155
+/* Copyright (C) 2005 Free Software Foundation, Inc.
 
156
+   This file is part of the GNU C Library.
 
157
+
 
158
+   The GNU C Library is free software; you can redistribute it and/or
 
159
+   modify it under the terms of the GNU Lesser General Public
 
160
+   License as published by the Free Software Foundation; either
 
161
+   version 2.1 of the License, or (at your option) any later version.
 
162
+
 
163
+   The GNU C Library is distributed in the hope that it will be useful,
 
164
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
165
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
166
+   Lesser General Public License for more details.
 
167
+
 
168
+   You should have received a copy of the GNU Lesser General Public
 
169
+   License along with the GNU C Library; if not, write to the Free
 
170
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
171
+   02111-1307 USA.  */
 
172
+
 
173
+#include <paths.h>
 
174
+#include <hurd.h>
 
175
+
 
176
+/* The area (from top to bottom) that is used for private keys.  These
 
177
+   are all keys that have the second highest bit set.  */
 
178
+#define SHM_PRIV_KEY_START INT_MAX
 
179
+#define SHM_PRIV_KEY_END ((INT_MAX / 2) + 1)
 
180
+
 
181
+#define SHM_PREFIX "shm-"
 
182
+#define SHM_DIR _PATH_DEV "shm/"
 
183
+
 
184
+/* The maximum number of characters in a shared memory segment file name.
 
185
+   32 is the max number of characters in a 128 bit number in hex.  */
 
186
+#if __WORDSIZE > 128
 
187
+#error Need to increase SHM_NAMEMAX.
 
188
+#else
 
189
+#define SHM_NAMEMAX (sizeof (SHM_PREFIX) - 1 + 32 + 1)
 
190
+#endif
 
191
+
 
192
+/* Use this with printf and its variants.  */
 
193
+#define SHM_NAMEPRI SHM_PREFIX "%0x"
 
194
+
 
195
+
 
196
+/* Adds a segment attachment.  */
 
197
+error_t __sysvshm_add (void *addr, size_t size);
 
198
+
 
199
+/* Removes a segment attachment.  Returns its size if found, or EINVAL
 
200
+   otherwise.  */
 
201
+error_t __sysvshm_remove (void *addr, size_t *size);
 
202
--- /dev/null
 
203
+++ b/sysdeps/mach/hurd/ftok.c
 
204
@@ -0,0 +1,43 @@
 
205
+/* Copyright (C) 1995, 1996, 2000, 2005 Free Software Foundation, Inc.
 
206
+   This file is part of the GNU C Library.
 
207
+   Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
 
208
+
 
209
+   The GNU C Library is free software; you can redistribute it and/or
 
210
+   modify it under the terms of the GNU Lesser General Public
 
211
+   License as published by the Free Software Foundation; either
 
212
+   version 2.1 of the License, or (at your option) any later version.
 
213
+
 
214
+   The GNU C Library is distributed in the hope that it will be useful,
 
215
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
216
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
217
+   Lesser General Public License for more details.
 
218
+
 
219
+   You should have received a copy of the GNU Lesser General Public
 
220
+   License along with the GNU C Library; if not, write to the Free
 
221
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
222
+   02111-1307 USA.  */
 
223
+
 
224
+#include <sys/ipc.h>
 
225
+#include <sys/stat.h>
 
226
+
 
227
+
 
228
+/* In the Hurd, we use the second-to-most-significant bit as flag for
 
229
+   private keys.  We use a different order of the components so that
 
230
+   the biggest one---the inode number---is affected by this.  */
 
231
+
 
232
+key_t
 
233
+ftok (pathname, proj_id)
 
234
+     const char *pathname;
 
235
+     int proj_id;
 
236
+{
 
237
+  struct stat64 st;
 
238
+  key_t key;
 
239
+
 
240
+  if (__xstat64 (_STAT_VER, pathname, &st) < 0)
 
241
+    return (key_t) -1;
 
242
+
 
243
+  key = ((st.st_dev & 0xff) | ((proj_id & 0xff) << 8)
 
244
+        | ((st.st_ino & 0x3fff) << 16));
 
245
+
 
246
+  return key;
 
247
+}
 
248
--- /dev/null
 
249
+++ b/sysdeps/mach/hurd/shmat.c
 
250
@@ -0,0 +1,78 @@
 
251
+/* Copyright (C) 2005 Free Software Foundation, Inc.
 
252
+   This file is part of the GNU C Library.
 
253
+
 
254
+   The GNU C Library is free software; you can redistribute it and/or
 
255
+   modify it under the terms of the GNU Lesser General Public
 
256
+   License as published by the Free Software Foundation; either
 
257
+   version 2.1 of the License, or (at your option) any later version.
 
258
+
 
259
+   The GNU C Library is distributed in the hope that it will be useful,
 
260
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
261
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
262
+   Lesser General Public License for more details.
 
263
+
 
264
+   You should have received a copy of the GNU Lesser General Public
 
265
+   License along with the GNU C Library; if not, write to the Free
 
266
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
267
+   02111-1307 USA.  */
 
268
+
 
269
+#include <errno.h>
 
270
+#include <utime.h>
 
271
+#include <stdio.h>
 
272
+#include <assert.h>
 
273
+#include <sys/mman.h>
 
274
+#include <sys/ipc.h>
 
275
+#include <sys/shm.h>
 
276
+#include <sys/time.h>
 
277
+#include <sys/stat.h>
 
278
+#include <fcntl.h>
 
279
+
 
280
+#include "sysvshm.h"
 
281
+
 
282
+/* Attach the shared memory segment associated with SHMID to the data
 
283
+   segment of the calling process.  SHMADDR and SHMFLG determine how
 
284
+   and where the segment is attached.  */
 
285
+void *
 
286
+__shmat (int shmid, const void *shmaddr, int shmflg)
 
287
+{
 
288
+  error_t err;
 
289
+  char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
 
290
+  int fd;
 
291
+  void *addr;
 
292
+  struct stat statbuf;
 
293
+  int res;
 
294
+
 
295
+  sprintf (filename, SHM_DIR SHM_NAMEPRI, shmid);
 
296
+  fd = __open (filename, (shmflg & SHM_RDONLY) ? O_RDONLY : O_RDWR);
 
297
+  if (fd < 0)
 
298
+    {
 
299
+      if (errno == ENOENT)
 
300
+       errno = EINVAL;
 
301
+      return (void *) -1;
 
302
+    }
 
303
+
 
304
+  res = __fstat (fd, &statbuf);
 
305
+  if (res < 0)
 
306
+    {
 
307
+      __close (fd);
 
308
+      return (void *) -1;
 
309
+    }
 
310
+
 
311
+  addr = __mmap ((void *) shmaddr, statbuf.st_size,
 
312
+                PROT_READ | ((shmflg & SHM_RDONLY) ? 0 : PROT_WRITE),
 
313
+                MAP_SHARED, fd, 0);
 
314
+  __close (fd);
 
315
+  if (addr == MAP_FAILED)
 
316
+    return (void *) -1;
 
317
+
 
318
+  err = __sysvshm_add (addr, statbuf.st_size);
 
319
+  if (err)
 
320
+    {
 
321
+      munmap (addr, statbuf.st_size);
 
322
+      return (void *) -1;
 
323
+    }
 
324
+
 
325
+  return addr;
 
326
+}
 
327
+
 
328
+weak_alias(__shmat, shmat)
 
329
--- /dev/null
 
330
+++ b/sysdeps/mach/hurd/shmctl.c
 
331
@@ -0,0 +1,132 @@
 
332
+/* Copyright (C) 2005 Free Software Foundation, Inc.
 
333
+   This file is part of the GNU C Library.
 
334
+
 
335
+   The GNU C Library is free software; you can redistribute it and/or
 
336
+   modify it under the terms of the GNU Lesser General Public
 
337
+   License as published by the Free Software Foundation; either
 
338
+   version 2.1 of the License, or (at your option) any later version.
 
339
+
 
340
+   The GNU C Library is distributed in the hope that it will be useful,
 
341
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
342
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
343
+   Lesser General Public License for more details.
 
344
+
 
345
+   You should have received a copy of the GNU Lesser General Public
 
346
+   License along with the GNU C Library; if not, write to the Free
 
347
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
348
+   02111-1307 USA.  */
 
349
+
 
350
+#include <errno.h>
 
351
+#include <stdio.h>
 
352
+#include <unistd.h>
 
353
+#include <sys/mman.h>
 
354
+#include <sys/ipc.h>
 
355
+#include <sys/shm.h>
 
356
+#include <sys/stat.h>
 
357
+#include <fcntl.h>
 
358
+
 
359
+#include "sysvshm.h"
 
360
+
 
361
+/* Provide operations to control over shared memory segments.  */
 
362
+int
 
363
+__shmctl (int id, int cmd, struct shmid_ds *buf)
 
364
+{
 
365
+  error_t err = 0;
 
366
+  int fd;
 
367
+  int res;
 
368
+  char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
 
369
+  struct stat statbuf;
 
370
+
 
371
+  sprintf (filename, SHM_DIR SHM_NAMEPRI, id);
 
372
+  /* SysV requires read access for IPC_STAT.  */
 
373
+  fd = __open (filename, O_NORW);
 
374
+  if (fd < 0)
 
375
+    {
 
376
+      if (errno == ENOENT)
 
377
+       errno = EINVAL;
 
378
+      return -1;
 
379
+    }
 
380
+
 
381
+  res = __fstat (fd, &statbuf);
 
382
+  if (res < 0)
 
383
+    {
 
384
+      err = errno;
 
385
+      __close (fd);
 
386
+      errno = err;
 
387
+      return -1;
 
388
+    }
 
389
+  
 
390
+  switch (cmd)
 
391
+    {
 
392
+    case IPC_STAT:
 
393
+
 
394
+      buf->shm_perm.__key = id;
 
395
+      buf->shm_perm.uid = statbuf.st_uid;
 
396
+      buf->shm_perm.gid = statbuf.st_gid;
 
397
+
 
398
+      /* We do not support the creator.  */
 
399
+      buf->shm_perm.cuid = statbuf.st_uid;
 
400
+      buf->shm_perm.cgid = statbuf.st_gid;
 
401
+
 
402
+      /* We just want the protection bits.  */
 
403
+      buf->shm_perm.mode = statbuf.st_mode & 0777;
 
404
+      /* Hopeless.  We do not support a sequence number.  */
 
405
+      buf->shm_perm.__seq = statbuf.st_ino;
 
406
+      buf->shm_segsz = statbuf.st_size;
 
407
+
 
408
+      /* Hopeless.  We do not support any of these.  */
 
409
+      buf->shm_atime = statbuf.st_atime;
 
410
+      buf->shm_dtime = statbuf.st_mtime;
 
411
+      /* Well, this comes at least close.  */
 
412
+      buf->shm_ctime = statbuf.st_ctime;
 
413
+
 
414
+      /* We do not support the PID.  */
 
415
+      buf->shm_cpid = 0;
 
416
+      buf->shm_lpid = 0;
 
417
+
 
418
+      if (statbuf.st_mode & S_IMMAP0)
 
419
+        buf->shm_nattch = 0;
 
420
+      else
 
421
+        /* 42 is the answer.  Of course this is bogus, but for most
 
422
+          applications, this should be fine.  */
 
423
+        buf->shm_nattch = 42;
 
424
+
 
425
+      break;
 
426
+
 
427
+    case IPC_SET:
 
428
+      if (statbuf.st_uid != buf->shm_perm.uid
 
429
+         || statbuf.st_gid != buf->shm_perm.gid)
 
430
+       {
 
431
+         res = __fchown (fd,
 
432
+                         (statbuf.st_uid != buf->shm_perm.uid)
 
433
+                         ? buf->shm_perm.uid : -1,
 
434
+                         (statbuf.st_gid != buf->shm_perm.gid)
 
435
+                         ? buf->shm_perm.gid : -1);
 
436
+         if (res < 0)
 
437
+           err = errno;
 
438
+       }
 
439
+
 
440
+      if (!err && statbuf.st_mode & 0777 != buf->shm_perm.mode & 0777)
 
441
+       {
 
442
+         res = __fchmod (fd, (statbuf.st_mode & ~0777)
 
443
+                         | (buf->shm_perm.mode & 0777));
 
444
+         if (res < 0)
 
445
+           err = errno;
 
446
+       }
 
447
+      break;
 
448
+
 
449
+    case IPC_RMID:
 
450
+      res = __unlink (filename);
 
451
+      /* FIXME: Check error (mapping ENOENT to EINVAL).  */
 
452
+      break;
 
453
+
 
454
+    default:
 
455
+      err = EINVAL;
 
456
+    }
 
457
+
 
458
+  __close (fd);
 
459
+  errno = err;
 
460
+  return err ? -1 : 0;
 
461
+}
 
462
+
 
463
+weak_alias(__shmctl, shmctl)
 
464
--- /dev/null
 
465
+++ b/sysdeps/mach/hurd/shmdt.c
 
466
@@ -0,0 +1,51 @@
 
467
+/* Copyright (C) 2005 Free Software Foundation, Inc.
 
468
+   This file is part of the GNU C Library.
 
469
+
 
470
+   The GNU C Library is free software; you can redistribute it and/or
 
471
+   modify it under the terms of the GNU Lesser General Public
 
472
+   License as published by the Free Software Foundation; either
 
473
+   version 2.1 of the License, or (at your option) any later version.
 
474
+
 
475
+   The GNU C Library is distributed in the hope that it will be useful,
 
476
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
477
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
478
+   Lesser General Public License for more details.
 
479
+
 
480
+   You should have received a copy of the GNU Lesser General Public
 
481
+   License along with the GNU C Library; if not, write to the Free
 
482
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
483
+   02111-1307 USA.  */
 
484
+
 
485
+#include <stdio.h>
 
486
+#include <errno.h>
 
487
+#include <fcntl.h>
 
488
+#include <unistd.h>
 
489
+#include <assert.h>
 
490
+#include <sys/mman.h>
 
491
+#include <sys/ipc.h>
 
492
+#include <sys/shm.h>
 
493
+#include <sys/time.h>
 
494
+#include <sys/stat.h>
 
495
+
 
496
+#include "sysvshm.h"
 
497
+
 
498
+/* Detach shared memory segment starting at address specified by
 
499
+   SHMADDR from the caller's data segment.  */
 
500
+int
 
501
+__shmdt (const void *shmaddr)
 
502
+{
 
503
+  error_t err;
 
504
+  size_t size;
 
505
+
 
506
+  err = __sysvshm_remove ((void *) shmaddr, &size);
 
507
+  if (err)
 
508
+    {
 
509
+      errno = err;
 
510
+      return -1;
 
511
+    }
 
512
+
 
513
+  __munmap ((void *) shmaddr, size);
 
514
+  return 0;
 
515
+}
 
516
+
 
517
+weak_alias(__shmdt, shmdt)
 
518
--- /dev/null
 
519
+++ b/sysdeps/mach/hurd/shmget.c
 
520
@@ -0,0 +1,242 @@
 
521
+/* Copyright (C) 2005 Free Software Foundation, Inc.
 
522
+   This file is part of the GNU C Library.
 
523
+
 
524
+   The GNU C Library is free software; you can redistribute it and/or
 
525
+   modify it under the terms of the GNU Lesser General Public
 
526
+   License as published by the Free Software Foundation; either
 
527
+   version 2.1 of the License, or (at your option) any later version.
 
528
+
 
529
+   The GNU C Library is distributed in the hope that it will be useful,
 
530
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
531
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
532
+   Lesser General Public License for more details.
 
533
+
 
534
+   You should have received a copy of the GNU Lesser General Public
 
535
+   License along with the GNU C Library; if not, write to the Free
 
536
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
537
+   02111-1307 USA.  */
 
538
+
 
539
+#include <stdbool.h>
 
540
+#include <stdlib.h>
 
541
+#include <errno.h>
 
542
+#include <sys/shm.h>
 
543
+#include <sys/types.h>
 
544
+#include <sys/stat.h>
 
545
+#include <limits.h>
 
546
+#include <stdio.h>
 
547
+#include <fcntl.h>
 
548
+#include <unistd.h>
 
549
+
 
550
+#include <hurd/fd.h>
 
551
+
 
552
+#include "sysvshm.h"
 
553
+
 
554
+/* Create a new shared memory segment file without linking it into the
 
555
+   filesystem.  Return the directory and file ports in R_DIR and R_FILE.  */
 
556
+static error_t
 
557
+create_shm_file (size_t size, int flags, file_t *r_dir, file_t *r_file)
 
558
+{
 
559
+  error_t err;
 
560
+  file_t dir;
 
561
+  file_t file;
 
562
+
 
563
+  flags &= 0777;
 
564
+
 
565
+  /* Get a port to the directory that will contain the file.  */
 
566
+  dir = __file_name_lookup (SHM_DIR, 0, 0);
 
567
+  if (dir == MACH_PORT_NULL)
 
568
+    return errno;
 
569
+
 
570
+  /* Create an unnamed file in the directory.  */
 
571
+  err = __dir_mkfile (dir, O_RDWR, flags, &file);
 
572
+  if (err)
 
573
+    {
 
574
+      __mach_port_deallocate (__mach_task_self (), dir);
 
575
+      return err;
 
576
+    }
 
577
+
 
578
+  err = __file_set_size (file, size);
 
579
+  if (err)
 
580
+    {
 
581
+      __mach_port_deallocate (__mach_task_self (), file);
 
582
+      __mach_port_deallocate (__mach_task_self (), dir);
 
583
+
 
584
+      return err;
 
585
+    }
 
586
+
 
587
+  *r_dir = dir;
 
588
+  *r_file = file;
 
589
+
 
590
+  return 0;
 
591
+}
 
592
+  
 
593
+
 
594
+/* Open the shared memory segment *R_KEY and return a file descriptor
 
595
+   to it in R_FD.  If KEY is IPC_PRIVATE, use a private key and return
 
596
+   it in R_KEY.  */
 
597
+static error_t
 
598
+get_exclusive (int shmflags, size_t size, key_t *r_key, int *r_fd)
 
599
+{
 
600
+  error_t err;
 
601
+  file_t dir;
 
602
+  file_t file;
 
603
+  char filename[SHM_NAMEMAX];
 
604
+  key_t key = *r_key;
 
605
+  bool is_private;
 
606
+
 
607
+  /* Create the shared memory segment.  */
 
608
+  err = create_shm_file (size, shmflags, &dir, &file);
 
609
+  if (err)
 
610
+    return err;
 
611
+
 
612
+  if (key == IPC_PRIVATE)
 
613
+    {
 
614
+      is_private = true;
 
615
+      key = SHM_PRIV_KEY_START;
 
616
+
 
617
+      /* Try to link the shared memory segment into the filesystem
 
618
+        (exclusively).  Private segments have negative keys.  */
 
619
+      do
 
620
+       {
 
621
+         sprintf (filename, SHM_NAMEPRI, key);
 
622
+         err = __dir_link (dir, file, filename, 1);
 
623
+         if (!err)
 
624
+           {
 
625
+             /* We are done.  */
 
626
+             *r_key = key;
 
627
+             break;
 
628
+           }
 
629
+         else if (err == EEXIST)
 
630
+           {
 
631
+             /* Check if we ran out of keys.  If not, try again with new
 
632
+                key.  */
 
633
+             if (key == SHM_PRIV_KEY_END)
 
634
+               err = ENOSPC;
 
635
+             else
 
636
+               err = 0;
 
637
+
 
638
+             key--;
 
639
+           }
 
640
+       }
 
641
+      while (!err);
 
642
+    }
 
643
+  else
 
644
+    {
 
645
+      /* Try to link the shared memory segment into the filesystem
 
646
+        (exclusively) under the given key.  */
 
647
+      sprintf (filename, SHM_NAMEPRI, key);
 
648
+      err = __dir_link (dir, file, filename, 1);
 
649
+    }
 
650
+
 
651
+  __mach_port_deallocate (__mach_task_self (), dir);
 
652
+
 
653
+  if (!err)
 
654
+    {
 
655
+      int fd;
 
656
+
 
657
+      /* Get a file descriptor for that port.  */
 
658
+      fd = _hurd_intern_fd (file, O_RDWR, 1); /* dealloc on error */
 
659
+      if (fd < 0)
 
660
+       err = errno;
 
661
+      else
 
662
+       *r_fd = fd;
 
663
+    }
 
664
+
 
665
+  return err;
 
666
+}
 
667
+
 
668
+
 
669
+/* Open the shared memory segment KEY (creating it if it doesn't yet
 
670
+   exist) and return a file descriptor to it in R_FD.  */
 
671
+static error_t
 
672
+get_shared (int shmflags, size_t size, key_t key, int *r_fd)
 
673
+{
 
674
+  error_t err = 0;
 
675
+  char filename[sizeof (SHM_DIR) - 1 + SHM_NAMEMAX];
 
676
+  int fd = -1;
 
677
+  sprintf (filename, SHM_DIR SHM_NAMEPRI, key);
 
678
+
 
679
+  do
 
680
+    {
 
681
+      fd = __open (filename, O_NORW, shmflags & 0777);
 
682
+
 
683
+      if (fd < 0 && errno != ENOENT)
 
684
+       /* We give up.  */
 
685
+       return errno;
 
686
+      else if (fd >= 0)
 
687
+       {
 
688
+         int res;
 
689
+         struct stat statbuf;
 
690
+
 
691
+         /* Check the size (we only need to do this if we did not
 
692
+            create the shared memory segment file ourselves).  */
 
693
+         res = __fstat (fd, &statbuf);
 
694
+         if (res < 0)
 
695
+           {
 
696
+             err = errno;
 
697
+             __close (fd);
 
698
+             return err;
 
699
+           }
 
700
+
 
701
+         if (statbuf.st_size < size)
 
702
+           {
 
703
+             __close (fd);
 
704
+             return EINVAL;
 
705
+           }
 
706
+       }         
 
707
+      else
 
708
+       {
 
709
+         /* The memory segment doesn't exist.  */
 
710
+         if (shmflags & IPC_CREAT)
 
711
+           {
 
712
+             /* Try to create it exclusively.  */
 
713
+             err = get_exclusive (shmflags, size, &key, &fd);
 
714
+             if (err == EEXIST)
 
715
+               /* If somebody created it in the meanwhile, just try again.  */
 
716
+               err = 0;
 
717
+           }
 
718
+         else
 
719
+           err = ENOENT;
 
720
+       }
 
721
+    }
 
722
+  while (fd < 0 && !err);
 
723
+
 
724
+  if (!err)
 
725
+    *r_fd = fd;
 
726
+  else
 
727
+    *r_fd = -1;
 
728
+
 
729
+  return err;
 
730
+}
 
731
+
 
732
+/* Return an identifier for an shared memory segment of at least size
 
733
+   SIZE which is associated with KEY.  */
 
734
+int
 
735
+__shmget (key_t key, size_t size, int shmflags)
 
736
+{
 
737
+  error_t err;
 
738
+  int fd;
 
739
+
 
740
+  if (key == IPC_PRIVATE || shmflags & IPC_EXCL)
 
741
+    /* An exclusive shared memory segment must be created.  */
 
742
+    err = get_exclusive (shmflags, size, &key, &fd);
 
743
+  else
 
744
+    err = get_shared (shmflags, size, key, &fd);
 
745
+
 
746
+  if (err)
 
747
+    {
 
748
+      errno = err;
 
749
+      return -1;
 
750
+    }
 
751
+
 
752
+  /* From here, we can't fail.  That's important, as otherwise we
 
753
+     would need to unlink the file if we created it (in that case, the
 
754
+     code above would have to be changed to pass a "created" flag down
 
755
+     to the caller).  */
 
756
+
 
757
+  __close (fd);
 
758
+
 
759
+  return key;
 
760
+}
 
761
+
 
762
+weak_alias(__shmget, shmget)
 
763
--- a/sysdeps/mach/hurd/bits/posix_opt.h
 
764
+++ b/sysdeps/mach/hurd/bits/posix_opt.h
 
765
@@ -69,8 +69,8 @@
 
766
 /* X/Open thread realtime support is not supported.  */
 
767
 #undef _XOPEN_REALTIME_THREADS
 
768
 
 
769
-/* XPG4.2 shared memory is not supported.  */
 
770
-#undef _XOPEN_SHM
 
771
+/* XPG4.2 shared memory is supported.  */
 
772
+#define        _XOPEN_SHM      1
 
773
 
 
774
 /* We do not have the POSIX threads interface.  */
 
775
 #define _POSIX_THREADS -1