blob: 40e69fa2e59a72525037998af160029a46e74ab5 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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 */
28static __attribute_noinline__ char* get_shm_name(const char *name) __nonnull((1));
29static 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
58int 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
91int 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}