]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/memfd-util.c
dhcp6-option: Add helper function for uncompressed domain names
[thirdparty/systemd.git] / src / basic / memfd-util.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>
ddeb4241 24#include <sys/mman.h>
7f96b1d8 25#include <sys/prctl.h>
ddeb4241 26
27c64db6
ZJS
27#ifdef HAVE_LINUX_MEMFD_H
28# include <linux/memfd.h>
29#endif
30
ddeb4241 31#include "util.h"
a09abc4a 32#include "memfd-util.h"
8f2807ba 33#include "utf8.h"
27c64db6 34#include "missing.h"
ddeb4241 35
4531a9bc 36int memfd_new(const char *name) {
7f96b1d8 37 _cleanup_free_ char *g = NULL;
4531a9bc 38 int fd;
ddeb4241 39
5755381f 40 if (!name) {
7f96b1d8
LP
41 char pr[17] = {};
42
43 /* If no name is specified we generate one. We include
44 * a hint indicating our library implementation, and
45 * add the thread name to it */
46
47 assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
48
49 if (isempty(pr))
50 name = "sd";
51 else {
5755381f
LP
52 _cleanup_free_ char *e = NULL;
53
54 e = utf8_escape_invalid(pr);
55 if (!e)
56 return -ENOMEM;
57
58 g = strappend("sd-", e);
7f96b1d8
LP
59 if (!g)
60 return -ENOMEM;
61
62 name = g;
63 }
64 }
65
45071fca 66 fd = memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC);
4531a9bc 67 if (fd < 0)
a6082d77 68 return -errno;
ddeb4241 69
4531a9bc 70 return fd;
ddeb4241
LP
71}
72
fac9c0d5 73int memfd_map(int fd, uint64_t offset, size_t size, void **p) {
ddeb4241
LP
74 void *q;
75 int sealed;
76
4531a9bc
LP
77 assert(fd >= 0);
78 assert(size > 0);
79 assert(p);
ddeb4241 80
fac9c0d5 81 sealed = memfd_get_sealed(fd);
ddeb4241
LP
82 if (sealed < 0)
83 return sealed;
84
23972f42 85 if (sealed)
fac9c0d5 86 q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset);
23972f42 87 else
fac9c0d5 88 q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
23972f42 89
ddeb4241
LP
90 if (q == MAP_FAILED)
91 return -errno;
92
93 *p = q;
94 return 0;
95}
96
fac9c0d5 97int memfd_set_sealed(int fd) {
ddeb4241
LP
98 int r;
99
4531a9bc 100 assert(fd >= 0);
ddeb4241 101
db74cc0d 102 r = fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
ddeb4241
LP
103 if (r < 0)
104 return -errno;
105
106 return 0;
107}
108
fac9c0d5 109int memfd_get_sealed(int fd) {
a6082d77 110 int r;
ddeb4241 111
4531a9bc 112 assert(fd >= 0);
ddeb4241 113
fac9c0d5 114 r = fcntl(fd, F_GET_SEALS);
ddeb4241
LP
115 if (r < 0)
116 return -errno;
117
db74cc0d 118 return r == (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
ddeb4241
LP
119}
120
fac9c0d5 121int memfd_get_size(int fd, uint64_t *sz) {
a6082d77 122 struct stat stat;
4531a9bc 123 int r;
ddeb4241 124
4531a9bc
LP
125 assert(fd >= 0);
126 assert(sz);
ddeb4241 127
fac9c0d5 128 r = fstat(fd, &stat);
ddeb4241
LP
129 if (r < 0)
130 return -errno;
131
a6082d77 132 *sz = stat.st_size;
5755381f 133 return 0;
ddeb4241
LP
134}
135
fac9c0d5 136int memfd_set_size(int fd, uint64_t sz) {
ddeb4241
LP
137 int r;
138
4531a9bc 139 assert(fd >= 0);
ddeb4241 140
fac9c0d5 141 r = ftruncate(fd, sz);
ddeb4241
LP
142 if (r < 0)
143 return -errno;
144
5755381f 145 return 0;
ddeb4241 146}
453a0c29 147
4531a9bc
LP
148int memfd_new_and_map(const char *name, size_t sz, void **p) {
149 _cleanup_close_ int fd = -1;
453a0c29
LP
150 int r;
151
4531a9bc
LP
152 assert(sz > 0);
153 assert(p);
154
155 fd = memfd_new(name);
156 if (fd < 0)
157 return fd;
453a0c29 158
4531a9bc 159 r = memfd_set_size(fd, sz);
8a02deca 160 if (r < 0)
453a0c29 161 return r;
453a0c29 162
4531a9bc 163 r = memfd_map(fd, 0, sz, p);
8a02deca 164 if (r < 0)
453a0c29 165 return r;
453a0c29 166
4531a9bc
LP
167 r = fd;
168 fd = -1;
169
170 return r;
453a0c29 171}