Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | /* 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; } |