1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/ioctl.h>
26 #include <sys/prctl.h>
39 _public_ int sd_memfd_new(const char *name, sd_memfd **m) {
41 struct kdbus_cmd_memfd_make *cmd;
42 struct kdbus_item *item;
43 _cleanup_close_ int kdbus = -1;
44 _cleanup_free_ char *g = NULL;
48 assert_return(m, -EINVAL);
50 kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
55 /* The kernel side is pretty picky about the character
56 * set here, let's do the usual bus escaping to deal
59 g = sd_bus_label_escape(name);
68 /* If no name is specified we generate one. We include
69 * a hint indicating our library implementation, and
70 * add the thread name to it */
72 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
77 _cleanup_free_ char *e = NULL;
79 e = sd_bus_label_escape(pr);
83 g = strappend("sd-", e);
92 sz = ALIGN8(offsetof(struct kdbus_cmd_memfd_make, items)) +
93 ALIGN8(offsetof(struct kdbus_item, str)) +
98 item->size = ALIGN8(offsetof(struct kdbus_item, str)) + l + 1;
99 item->type = KDBUS_ITEM_MEMFD_NAME;
100 memcpy(item->str, name, l + 1);
102 if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, cmd) < 0)
105 n = new0(struct sd_memfd, 1);
107 close_nointr_nofail(cmd->fd);
116 _public_ int sd_memfd_make(int fd, sd_memfd **m) {
120 assert_return(m, -EINVAL);
121 assert_return(fd >= 0, -EINVAL);
123 /* Check if this is a valid memfd */
124 if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
127 n = new0(struct sd_memfd, 1);
137 _public_ void sd_memfd_free(sd_memfd *m) {
144 close_nointr_nofail(m->fd);
149 _public_ int sd_memfd_get_fd(sd_memfd *m) {
150 assert_return(m, -EINVAL);
155 _public_ int sd_memfd_get_file(sd_memfd *m, FILE **f) {
156 assert_return(m, -EINVAL);
157 assert_return(f, -EINVAL);
160 m->f = fdopen(m->fd, "r+");
169 _public_ int sd_memfd_dup_fd(sd_memfd *m) {
172 assert_return(m, -EINVAL);
174 fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
181 _public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
185 assert_return(m, -EINVAL);
186 assert_return(size > 0, -EINVAL);
187 assert_return(p, -EINVAL);
189 sealed = sd_memfd_get_sealed(m);
193 q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
201 _public_ int sd_memfd_set_sealed(sd_memfd *m, int b) {
204 assert_return(m, -EINVAL);
206 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
213 _public_ int sd_memfd_get_sealed(sd_memfd *m) {
216 assert_return(m, -EINVAL);
218 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
225 _public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
228 assert_return(m, -EINVAL);
229 assert_return(sz, -EINVAL);
231 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
238 _public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
241 assert_return(m, -EINVAL);
243 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
250 _public_ int sd_memfd_new_and_map(const char *name, sd_memfd **m, size_t sz, void **p) {
254 r = sd_memfd_new(name, &n);
258 r = sd_memfd_set_size(n, sz);
264 r = sd_memfd_map(n, 0, sz, p);
274 _public_ int sd_memfd_get_name(sd_memfd *m, char **name) {
275 char path[sizeof("/proc/self/fd/") + DECIMAL_STR_MAX(int)], buf[FILENAME_MAX+1], *e;
276 const char *delim, *end;
277 _cleanup_free_ char *n = NULL;
280 assert_return(m, -EINVAL);
281 assert_return(name, -EINVAL);
283 sprintf(path, "/proc/self/fd/%i", m->fd);
285 k = readlink(path, buf, sizeof(buf));
289 if ((size_t) k >= sizeof(buf))
294 delim = strstr(buf, ":[");
298 delim = strchr(delim + 2, ':');
304 end = strchr(delim, ']');
308 n = strndup(delim, end - delim);
312 e = sd_bus_label_unescape(n);