]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/import-util.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / shared / import-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 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 "btrfs-util.h"
23 #include "string-util.h"
24 #include "util.h"
25 #include "import-util.h"
26
27 int import_url_last_component(const char *url, char **ret) {
28 const char *e, *p;
29 char *s;
30
31 e = strchrnul(url, '?');
32
33 while (e > url && e[-1] == '/')
34 e--;
35
36 p = e;
37 while (p > url && p[-1] != '/')
38 p--;
39
40 if (e <= p)
41 return -EINVAL;
42
43 s = strndup(p, e - p);
44 if (!s)
45 return -ENOMEM;
46
47 *ret = s;
48 return 0;
49 }
50
51
52 int import_url_change_last_component(const char *url, const char *suffix, char **ret) {
53 const char *e;
54 char *s;
55
56 assert(url);
57 assert(ret);
58
59 e = strchrnul(url, '?');
60
61 while (e > url && e[-1] == '/')
62 e--;
63
64 while (e > url && e[-1] != '/')
65 e--;
66
67 if (e <= url)
68 return -EINVAL;
69
70 s = new(char, (e - url) + strlen(suffix) + 1);
71 if (!s)
72 return -ENOMEM;
73
74 strcpy(mempcpy(s, url, e - url), suffix);
75 *ret = s;
76 return 0;
77 }
78
79 static const char* const import_verify_table[_IMPORT_VERIFY_MAX] = {
80 [IMPORT_VERIFY_NO] = "no",
81 [IMPORT_VERIFY_CHECKSUM] = "checksum",
82 [IMPORT_VERIFY_SIGNATURE] = "signature",
83 };
84
85 DEFINE_STRING_TABLE_LOOKUP(import_verify, ImportVerify);
86
87 int tar_strip_suffixes(const char *name, char **ret) {
88 const char *e;
89 char *s;
90
91 e = endswith(name, ".tar");
92 if (!e)
93 e = endswith(name, ".tar.xz");
94 if (!e)
95 e = endswith(name, ".tar.gz");
96 if (!e)
97 e = endswith(name, ".tar.bz2");
98 if (!e)
99 e = endswith(name, ".tgz");
100 if (!e)
101 e = strchr(name, 0);
102
103 if (e <= name)
104 return -EINVAL;
105
106 s = strndup(name, e - name);
107 if (!s)
108 return -ENOMEM;
109
110 *ret = s;
111 return 0;
112 }
113
114 int raw_strip_suffixes(const char *p, char **ret) {
115
116 static const char suffixes[] =
117 ".xz\0"
118 ".gz\0"
119 ".bz2\0"
120 ".raw\0"
121 ".qcow2\0"
122 ".img\0"
123 ".bin\0";
124
125 _cleanup_free_ char *q = NULL;
126
127 q = strdup(p);
128 if (!q)
129 return -ENOMEM;
130
131 for (;;) {
132 const char *sfx;
133 bool changed = false;
134
135 NULSTR_FOREACH(sfx, suffixes) {
136 char *e;
137
138 e = endswith(q, sfx);
139 if (e) {
140 *e = 0;
141 changed = true;
142 }
143 }
144
145 if (!changed)
146 break;
147 }
148
149 *ret = q;
150 q = NULL;
151
152 return 0;
153 }
154
155 bool dkr_digest_is_valid(const char *digest) {
156 /* 7 chars for prefix, 64 chars for the digest itself */
157 if (strlen(digest) != 71)
158 return false;
159
160 return startswith(digest, "sha256:") && in_charset(digest + 7, "0123456789abcdef");
161 }
162
163 bool dkr_ref_is_valid(const char *ref) {
164 const char *colon;
165
166 if (isempty(ref))
167 return false;
168
169 colon = strchr(ref, ':');
170 if (!colon)
171 return filename_is_valid(ref);
172
173 return dkr_digest_is_valid(ref);
174 }
175
176 bool dkr_name_is_valid(const char *name) {
177 const char *slash, *p;
178
179 if (isempty(name))
180 return false;
181
182 slash = strchr(name, '/');
183 if (!slash)
184 return false;
185
186 if (!filename_is_valid(slash + 1))
187 return false;
188
189 p = strndupa(name, slash - name);
190 if (!filename_is_valid(p))
191 return false;
192
193 return true;
194 }
195
196 bool dkr_id_is_valid(const char *id) {
197
198 if (!filename_is_valid(id))
199 return false;
200
201 if (!in_charset(id, "0123456789abcdef"))
202 return false;
203
204 return true;
205 }
206
207 int import_assign_pool_quota_and_warn(const char *path) {
208 int r;
209
210 r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true);
211 if (r == -ENOTTY) {
212 log_debug_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, as directory is not on btrfs or not a subvolume. Ignoring.");
213 return 0;
214 }
215 if (r < 0)
216 return log_error_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines: %m");
217 if (r > 0)
218 log_info("Set up default quota hierarchy for /var/lib/machines.");
219
220 r = btrfs_subvol_auto_qgroup(path, 0, true);
221 if (r == -ENOTTY) {
222 log_debug_errno(r, "Failed to set up quota hierarchy for %s, as directory is not on btrfs or not a subvolume. Ignoring.", path);
223 return 0;
224 }
225 if (r < 0)
226 return log_error_errno(r, "Failed to set up default quota hierarchy for %s: %m", path);
227 if (r > 0)
228 log_info("Set up default quota hierarchy for %s.", path);
229
230 return 0;
231 }