]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/librt/shm.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / librt / shm.c
1 /* Copyright (C) 2009 Bernhard Reutner-Fischer <uclibc@uclibc.org>
2  *
3  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
4  */
5
6 #include <features.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/mman.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15
16 #ifndef _PATH_SHM
17 #define _PATH_SHM "/dev/shm/"
18 #endif
19
20 #ifndef NAME_MAX
21 #define NAME_MAX 255
22 #endif
23
24 /* Get name of dummy shm operation handle.
25  * Returns a malloc'ed buffer containing the OS specific path
26  * to the shm filename or NULL upon failure.
27  */
28 static __attribute_noinline__ char* get_shm_name(const char *name) __nonnull((1));
29 static char* get_shm_name(const char *name)
30 {
31         char *path;
32         int i;
33
34         /* Skip leading slashes */
35         while (*name == '/')
36                 ++name;
37 #ifdef __USE_GNU
38         i = asprintf(&path, _PATH_SHM "%s", name);
39         if (i < 0)
40                 return NULL;
41 #else
42         path = malloc(NAME_MAX);
43         if (path == NULL)
44                 return NULL;
45         i = snprintf(path, NAME_MAX, _PATH_SHM "%s", name);
46         if (i < 0) {
47                 free(path);
48                 return NULL;
49         } else if (i >= NAME_MAX) {
50                 free(path);
51                 __set_errno(ENAMETOOLONG);
52                 return NULL;
53         }
54 #endif
55         return path;
56 }
57
58 int shm_open(const char *name, int oflag, mode_t mode)
59 {
60         int fd;
61         char *shm_name = get_shm_name(name);
62
63         /* Stripped multiple '/' from start; may have set errno properly */
64         if (shm_name == NULL)
65                 return -1;
66         /* The FD_CLOEXEC file descriptor flag associated with the new
67          * file descriptor is set.  */
68 #ifdef O_CLOEXEC
69          /* Just open it with CLOEXEC set, for brevity */
70         fd = open(shm_name, oflag | O_CLOEXEC, mode);
71 #else
72         fd = open(shm_name, oflag, mode);
73         if (fd >= 0) {
74                 fcntl(fd, F_SETFD, FD_CLOEXEC);
75                 /* thus far, {G,S}ETFD only has this single flag,
76                  * and setting it never fails.
77                  *int fdflags = fcntl(fd, F_GETFD);
78                  *if (fdflags >= 0)
79                  *      fdflags = fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
80                  *if (fdflags < 0) {
81                  *      close(fd);
82                  *      fd = -1;
83                  *}
84                  */
85         }
86 #endif
87         free(shm_name); /* doesn't affect errno */
88         return fd;
89 }
90
91 int shm_unlink(const char *name)
92 {
93         char *shm_name = get_shm_name(name);
94         int ret;
95
96         /* Stripped multiple '/' from start; may have set errno properly */
97         if (shm_name == NULL)
98                 return -1;
99         ret = unlink(shm_name);
100         free(shm_name); /* doesn't affect errno */
101         return ret;
102 }