chiark / gitweb /
macro: introduce new TAKE_FD() macro
[elogind.git] / src / basic / memfd-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2013 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #if HAVE_LINUX_MEMFD_H
26 #include <linux/memfd.h>
27 #endif
28 #include <stdio.h>
29 #include <sys/mman.h>
30 #include <sys/prctl.h>
31
32 #include "alloc-util.h"
33 #include "fd-util.h"
34 #include "macro.h"
35 #include "memfd-util.h"
36 #include "missing.h"
37 #include "string-util.h"
38 #include "utf8.h"
39
40 int memfd_new(const char *name) {
41         _cleanup_free_ char *g = NULL;
42         int fd;
43
44         if (!name) {
45                 char pr[17] = {};
46
47                 /* If no name is specified we generate one. We include
48                  * a hint indicating our library implementation, and
49                  * add the thread name to it */
50
51                 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
52
53                 if (isempty(pr))
54                         name = "sd";
55                 else {
56                         _cleanup_free_ char *e = NULL;
57
58                         e = utf8_escape_invalid(pr);
59                         if (!e)
60                                 return -ENOMEM;
61
62                         g = strappend("sd-", e);
63                         if (!g)
64                                 return -ENOMEM;
65
66                         name = g;
67                 }
68         }
69
70         fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
71         if (fd < 0)
72                 return -errno;
73
74         return fd;
75 }
76
77 #if 0 /// UNNEEDED by elogind
78 int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
79         void *q;
80         int sealed;
81
82         assert(fd >= 0);
83         assert(size > 0);
84         assert(p);
85
86         sealed = memfd_get_sealed(fd);
87         if (sealed < 0)
88                 return sealed;
89
90         if (sealed)
91                 q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
92         else
93                 q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
94
95         if (q == MAP_FAILED)
96                 return -errno;
97
98         *p = q;
99         return 0;
100 }
101 #endif // 0
102
103 int memfd_set_sealed(int fd) {
104         int r;
105
106         assert(fd >= 0);
107
108         r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
109         if (r < 0)
110                 return -errno;
111
112         return 0;
113 }
114
115 #if 0 /// UNNEEDED by elogind
116 int memfd_get_sealed(int fd) {
117         int r;
118
119         assert(fd >= 0);
120
121         r = fcntl(fd, F_GET_SEALS);
122         if (r < 0)
123                 return -errno;
124
125         return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
126 }
127 #endif // 0
128
129 int memfd_get_size(int fd, uint64_t *sz) {
130         struct stat stat;
131         int r;
132
133         assert(fd >= 0);
134         assert(sz);
135
136         r = fstat(fd, &stat);
137         if (r < 0)
138                 return -errno;
139
140         *sz = stat.st_size;
141         return 0;
142 }
143
144 int memfd_set_size(int fd, uint64_t sz) {
145         int r;
146
147         assert(fd >= 0);
148
149         r = ftruncate(fd, sz);
150         if (r < 0)
151                 return -errno;
152
153         return 0;
154 }
155
156 #if 0 /// UNNEEDED by elogind
157 int memfd_new_and_map(const char *name, size_t sz, void **p) {
158         _cleanup_close_ int fd = -1;
159         int r;
160
161         assert(sz > 0);
162         assert(p);
163
164         fd = memfd_new(name);
165         if (fd < 0)
166                 return fd;
167
168         r = memfd_set_size(fd, sz);
169         if (r < 0)
170                 return r;
171
172         r = memfd_map(fd, 0, sz, p);
173         if (r < 0)
174                 return r;
175
176         return TAKE_FD(fd);
177 }
178 #endif // 0