]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-bus/sd-memfd.c
libsystemd: split up into subdirs
[thirdparty/systemd.git] / src / libsystemd / sd-bus / sd-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
27 #include "util.h"
28 #include "kdbus.h"
29
30 #include "sd-memfd.h"
31
32 struct sd_memfd {
33 int fd;
34 FILE *f;
35 };
36
37 _public_ int sd_memfd_new(sd_memfd **m) {
38 struct kdbus_cmd_memfd_make cmd = {
39 .size = sizeof(struct kdbus_cmd_memfd_make),
40 };
41 _cleanup_close_ int kdbus = -1;
42 sd_memfd *n;
43
44 assert_return(m, -EINVAL);
45
46 kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
47 if (kdbus < 0)
48 return -errno;
49
50 if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &cmd) < 0)
51 return -errno;
52
53 n = new0(struct sd_memfd, 1);
54 if (!n) {
55 close_nointr_nofail(cmd.fd);
56 return -ENOMEM;
57 }
58
59 n->fd = cmd.fd;
60 *m = n;
61 return 0;
62 }
63
64 _public_ int sd_memfd_make(int fd, sd_memfd **m) {
65 sd_memfd *n;
66 uint64_t sz;
67
68 assert_return(m, -EINVAL);
69 assert_return(fd >= 0, -EINVAL);
70
71 /* Check if this is a valid memfd */
72 if (ioctl(fd, KDBUS_CMD_MEMFD_SIZE_GET, &sz) < 0)
73 return -ENOTTY;
74
75 n = new0(struct sd_memfd, 1);
76 if (!n)
77 return -ENOMEM;
78
79 n->fd = fd;
80 *m = n;
81
82 return 0;
83 }
84
85 _public_ void sd_memfd_free(sd_memfd *m) {
86 if (!m)
87 return;
88
89 if (m->f)
90 fclose(m->f);
91 else
92 close_nointr_nofail(m->fd);
93
94 free(m);
95 }
96
97 _public_ int sd_memfd_get_fd(sd_memfd *m) {
98 assert_return(m, -EINVAL);
99
100 return m->fd;
101 }
102
103 _public_ int sd_memfd_get_file(sd_memfd *m, FILE **f) {
104 assert_return(m, -EINVAL);
105 assert_return(f, -EINVAL);
106
107 if (!m->f) {
108 m->f = fdopen(m->fd, "r+");
109 if (!m->f)
110 return -errno;
111 }
112
113 *f = m->f;
114 return 0;
115 }
116
117 _public_ int sd_memfd_dup_fd(sd_memfd *m) {
118 int fd;
119
120 assert_return(m, -EINVAL);
121
122 fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
123 if (fd < 0)
124 return -errno;
125
126 return fd;
127 }
128
129 _public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
130 void *q;
131 int sealed;
132
133 assert_return(m, -EINVAL);
134 assert_return(size > 0, -EINVAL);
135 assert_return(p, -EINVAL);
136
137 sealed = sd_memfd_get_sealed(m);
138 if (sealed < 0)
139 return sealed;
140
141 q = mmap(NULL, size, sealed ? PROT_READ : PROT_READ|PROT_WRITE, MAP_SHARED, m->fd, offset);
142 if (q == MAP_FAILED)
143 return -errno;
144
145 *p = q;
146 return 0;
147 }
148
149 _public_ int sd_memfd_set_sealed(sd_memfd *m, int b) {
150 int r;
151
152 assert_return(m, -EINVAL);
153
154 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_SET, b);
155 if (r < 0)
156 return -errno;
157
158 return 0;
159 }
160
161 _public_ int sd_memfd_get_sealed(sd_memfd *m) {
162 int r, b;
163
164 assert_return(m, -EINVAL);
165
166 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SEAL_GET, &b);
167 if (r < 0)
168 return -errno;
169
170 return !!b;
171 }
172
173 _public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
174 int r;
175
176 assert_return(m, -EINVAL);
177 assert_return(sz, -EINVAL);
178
179 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_GET, sz);
180 if (r < 0)
181 return -errno;
182
183 return r;
184 }
185
186 _public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
187 int r;
188
189 assert_return(m, -EINVAL);
190
191 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
192 if (r < 0)
193 return -errno;
194
195 return r;
196 }
197
198 _public_ int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p) {
199 sd_memfd *n;
200 int r;
201
202 r = sd_memfd_new(&n);
203 if (r < 0)
204 return r;
205
206 r = sd_memfd_set_size(n, sz);
207 if (r < 0) {
208 sd_memfd_free(n);
209 return r;
210 }
211
212 r = sd_memfd_map(n, 0, sz, p);
213 if (r < 0) {
214 sd_memfd_free(n);
215 return r;
216 }
217
218 *m = n;
219 return 0;
220 }