123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- /* Copyright (C) 2009 Bernhard Reutner-Fischer <uclibc@uclibc.org>
- *
- * 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 <sys/mman.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #ifndef _PATH_SHM
- #define _PATH_SHM "/dev/shm/"
- #endif
- #ifndef NAME_MAX
- #define NAME_MAX 255
- #endif
- /* Get name of dummy shm operation handle.
- * 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;
- /* Skip leading slashes */
- 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;
- } else if (i >= NAME_MAX) {
- free(path);
- __set_errno(ENAMETOOLONG);
- return NULL;
- }
- #endif
- return path;
- }
- int shm_open(const char *name, int oflag, mode_t mode)
- {
- int fd;
- char *shm_name = get_shm_name(name);
- /* Stripped multiple '/' from start; may have set errno properly */
- if (shm_name == NULL)
- return -1;
- /* The FD_CLOEXEC file descriptor flag associated with the new
- * file descriptor is set. */
- #ifdef O_CLOEXEC
- /* Just open it with CLOEXEC set, for brevity */
- fd = open(shm_name, oflag | O_CLOEXEC, mode);
- #else
- fd = open(shm_name, oflag, mode);
- if (fd >= 0) {
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- /* thus far, {G,S}ETFD only has this single flag,
- * and setting it never fails.
- *int fdflags = fcntl(fd, F_GETFD);
- *if (fdflags >= 0)
- * fdflags = fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC);
- *if (fdflags < 0) {
- * close(fd);
- * fd = -1;
- *}
- */
- }
- #endif
- if (fd < 0 && errno == EISDIR)
- /* EISDIR is not valid for shm_open, replace it with EINVAL as glibc. */
- __set_errno (EINVAL);
- free(shm_name); /* doesn't affect errno */
- return fd;
- }
- int shm_unlink(const char *name)
- {
- char *shm_name = get_shm_name(name);
- int ret;
- /* Stripped multiple '/' from start; may have set errno properly */
- if (shm_name == NULL)
- return -1;
- ret = unlink(shm_name);
- free(shm_name); /* doesn't affect errno */
- return ret;
- }
|