|
@@ -0,0 +1,98 @@
|
|
|
+
|
|
|
+ *
|
|
|
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <features.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <fcntl.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+#ifndef O_CLOEXEC
|
|
|
+#include <errno.h>
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef _PATH_SHM
|
|
|
+#define _PATH_SHM "/dev/shm/"
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifndef NAME_MAX
|
|
|
+#define NAME_MAX 255
|
|
|
+#endif
|
|
|
+
|
|
|
+
|
|
|
+ * Returns a malloc'ed buffer containing the OS specific path
|
|
|
+ * to the shm filename or NULL upon failure.
|
|
|
+ */
|
|
|
+static __attribute_noinline__ char* get_shm_name(const char*name) __nonnull((1));
|
|
|
+static char* get_shm_name(const char*name)
|
|
|
+{
|
|
|
+ char *path;
|
|
|
+ int i;
|
|
|
+
|
|
|
+
|
|
|
+ while (*name == '/')
|
|
|
+ ++name;
|
|
|
+#ifdef __USE_GNU
|
|
|
+ i = asprintf(&path, _PATH_SHM "%s", name);
|
|
|
+ if (i < 0)
|
|
|
+ return NULL;
|
|
|
+#else
|
|
|
+ path = malloc(NAME_MAX);
|
|
|
+ if (path == NULL)
|
|
|
+ return NULL;
|
|
|
+ i = snprintf(path, NAME_MAX, _PATH_SHM "%s", name);
|
|
|
+ if (i < 0) {
|
|
|
+ free(path);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ return path;
|
|
|
+}
|
|
|
+
|
|
|
+int shm_open(const char *name, int oflag, mode_t mode)
|
|
|
+{
|
|
|
+ int fd, old_errno;
|
|
|
+ char *shm_name = get_shm_name(name);
|
|
|
+
|
|
|
+
|
|
|
+ if (shm_name == NULL)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ * file descriptor is set. */
|
|
|
+#ifdef O_CLOEXEC
|
|
|
+
|
|
|
+ fd = open(shm_name, oflag | O_CLOEXEC, mode);
|
|
|
+#else
|
|
|
+ fd = open(shm_name, oflag, mode);
|
|
|
+ if (fd >= 0) {
|
|
|
+ int fdflags = fcntl(fd, F_GETFD, 0);
|
|
|
+ if (fdflags >= 0)
|
|
|
+ fdflags = fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
|
|
|
+ if (fdflags < 0) {
|
|
|
+ close(fd);
|
|
|
+ fd = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ old_errno = errno;
|
|
|
+ free(shm_name);
|
|
|
+ errno = old_errno;
|
|
|
+ return fd;
|
|
|
+}
|
|
|
+
|
|
|
+int shm_unlink(const char *name)
|
|
|
+{
|
|
|
+ char *shm_name = get_shm_name(name);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+
|
|
|
+ if (shm_name == NULL)
|
|
|
+ return -1;
|
|
|
+ ret = unlink(shm_name);
|
|
|
+ free(shm_name);
|
|
|
+ return ret;
|
|
|
+}
|