]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/sd-memfd.c
libsystemd: split up into subdirs
[thirdparty/systemd.git] / src / libsystemd / sd-bus / sd-memfd.c
CommitLineData
ddeb4241
LP
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
32struct sd_memfd {
33 int fd;
34 FILE *f;
35};
36
d9f644e2 37_public_ int sd_memfd_new(sd_memfd **m) {
135a4eb4
KS
38 struct kdbus_cmd_memfd_make cmd = {
39 .size = sizeof(struct kdbus_cmd_memfd_make),
40 };
ddeb4241
LP
41 _cleanup_close_ int kdbus = -1;
42 sd_memfd *n;
ddeb4241 43
53ab52ac 44 assert_return(m, -EINVAL);
ddeb4241
LP
45
46 kdbus = open("/dev/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
0d1b9a96 47 if (kdbus < 0)
ddeb4241
LP
48 return -errno;
49
135a4eb4 50 if (ioctl(kdbus, KDBUS_CMD_MEMFD_NEW, &cmd) < 0)
ddeb4241
LP
51 return -errno;
52
53 n = new0(struct sd_memfd, 1);
135a4eb4
KS
54 if (!n) {
55 close_nointr_nofail(cmd.fd);
ddeb4241 56 return -ENOMEM;
135a4eb4 57 }
ddeb4241 58
135a4eb4 59 n->fd = cmd.fd;
ddeb4241
LP
60 *m = n;
61 return 0;
62}
63
d9f644e2 64_public_ int sd_memfd_make(int fd, sd_memfd **m) {
ddeb4241
LP
65 sd_memfd *n;
66 uint64_t sz;
67
53ab52ac
TA
68 assert_return(m, -EINVAL);
69 assert_return(fd >= 0, -EINVAL);
ddeb4241
LP
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
d9f644e2 85_public_ void sd_memfd_free(sd_memfd *m) {
ddeb4241
LP
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
d9f644e2 97_public_ int sd_memfd_get_fd(sd_memfd *m) {
53ab52ac 98 assert_return(m, -EINVAL);
ddeb4241
LP
99
100 return m->fd;
101}
102
d9f644e2 103_public_ int sd_memfd_get_file(sd_memfd *m, FILE **f) {
53ab52ac
TA
104 assert_return(m, -EINVAL);
105 assert_return(f, -EINVAL);
ddeb4241 106
a7c54c8c 107 if (!m->f) {
ddeb4241
LP
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
d9f644e2 117_public_ int sd_memfd_dup_fd(sd_memfd *m) {
ddeb4241
LP
118 int fd;
119
53ab52ac 120 assert_return(m, -EINVAL);
ddeb4241
LP
121
122 fd = fcntl(m->fd, F_DUPFD_CLOEXEC, 3);
123 if (fd < 0)
124 return -errno;
125
126 return fd;
127}
128
d9f644e2 129_public_ int sd_memfd_map(sd_memfd *m, uint64_t offset, size_t size, void **p) {
ddeb4241
LP
130 void *q;
131 int sealed;
132
53ab52ac
TA
133 assert_return(m, -EINVAL);
134 assert_return(size > 0, -EINVAL);
135 assert_return(p, -EINVAL);
ddeb4241
LP
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
d9f644e2 149_public_ int sd_memfd_set_sealed(sd_memfd *m, int b) {
ddeb4241
LP
150 int r;
151
53ab52ac 152 assert_return(m, -EINVAL);
ddeb4241
LP
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
d9f644e2 161_public_ int sd_memfd_get_sealed(sd_memfd *m) {
ddeb4241
LP
162 int r, b;
163
53ab52ac 164 assert_return(m, -EINVAL);
ddeb4241
LP
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
d9f644e2 173_public_ int sd_memfd_get_size(sd_memfd *m, uint64_t *sz) {
ddeb4241
LP
174 int r;
175
53ab52ac
TA
176 assert_return(m, -EINVAL);
177 assert_return(sz, -EINVAL);
ddeb4241
LP
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
d9f644e2 186_public_ int sd_memfd_set_size(sd_memfd *m, uint64_t sz) {
ddeb4241
LP
187 int r;
188
53ab52ac 189 assert_return(m, -EINVAL);
ddeb4241
LP
190
191 r = ioctl(m->fd, KDBUS_CMD_MEMFD_SIZE_SET, &sz);
192 if (r < 0)
193 return -errno;
194
195 return r;
196}
453a0c29 197
d9f644e2 198_public_ int sd_memfd_new_and_map(sd_memfd **m, size_t sz, void **p) {
453a0c29
LP
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}