chiark / gitweb /
memfd: drop memfd_get_name() as it is unused
[elogind.git] / src / shared / memfd.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <sys/ioctl.h>
25 #include <sys/mman.h>
26 #include <sys/prctl.h>
27
28 #ifdef HAVE_LINUX_MEMFD_H
29 #  include <linux/memfd.h>
30 #endif
31
32 #include "util.h"
33 #include "bus-label.h"
34 #include "memfd.h"
35 #include "utf8.h"
36 #include "missing.h"
37
38 int memfd_new(const char *name) {
39         _cleanup_free_ char *g = NULL;
40         int fd;
41
42         if (!name) {
43                 char pr[17] = {};
44
45                 /* If no name is specified we generate one. We include
46                  * a hint indicating our library implementation, and
47                  * add the thread name to it */
48
49                 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
50
51                 if (isempty(pr))
52                         name = "sd";
53                 else {
54                         _cleanup_free_ char *e = NULL;
55
56                         e = utf8_escape_invalid(pr);
57                         if (!e)
58                                 return -ENOMEM;
59
60                         g = strappend("sd-", e);
61                         if (!g)
62                                 return -ENOMEM;
63
64                         name = g;
65                 }
66         }
67
68         fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
69         if (fd < 0)
70                 return -errno;
71
72         return fd;
73 }
74
75 int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
76         void *q;
77         int sealed;
78
79         assert(fd >= 0);
80         assert(size > 0);
81         assert(p);
82
83         sealed = memfd_get_sealed(fd);
84         if (sealed < 0)
85                 return sealed;
86
87         if (sealed)
88                 q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
89         else
90                 q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
91
92         if (q == MAP_FAILED)
93                 return -errno;
94
95         *p = q;
96         return 0;
97 }
98
99 int memfd_set_sealed(int fd) {
100         int r;
101
102         assert(fd >= 0);
103
104         r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
105         if (r < 0)
106                 return -errno;
107
108         return 0;
109 }
110
111 int memfd_get_sealed(int fd) {
112         int r;
113
114         assert(fd >= 0);
115
116         r = fcntl(fd, F_GET_SEALS);
117         if (r < 0)
118                 return -errno;
119
120         return (r & (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)) ==
121                     (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
122 }
123
124 int memfd_get_size(int fd, uint64_t *sz) {
125         struct stat stat;
126         int r;
127
128         assert(fd >= 0);
129         assert(sz);
130
131         r = fstat(fd, &stat);
132         if (r < 0)
133                 return -errno;
134
135         *sz = stat.st_size;
136         return 0;
137 }
138
139 int memfd_set_size(int fd, uint64_t sz) {
140         int r;
141
142         assert(fd >= 0);
143
144         r = ftruncate(fd, sz);
145         if (r < 0)
146                 return -errno;
147
148         return 0;
149 }
150
151 int memfd_new_and_map(const char *name, size_t sz, void **p) {
152         _cleanup_close_ int fd = -1;
153         int r;
154
155         assert(sz > 0);
156         assert(p);
157
158         fd = memfd_new(name);
159         if (fd < 0)
160                 return fd;
161
162         r = memfd_set_size(fd, sz);
163         if (r < 0)
164                 return r;
165
166         r = memfd_map(fd, 0, sz, p);
167         if (r < 0)
168                 return r;
169
170         r = fd;
171         fd = -1;
172
173         return r;
174 }