]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/import-util.c
import: add support for pulling raw tar balls as containers
[thirdparty/systemd.git] / src / import / import-util.c
CommitLineData
56ebfaf1
LP
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 "util.h"
23#include "strv.h"
24#include "copy.h"
25#include "btrfs-util.h"
26#include "import-util.h"
27
28#define FILENAME_ESCAPE "/.#\"\'"
29
30bool http_etag_is_valid(const char *etag) {
31 if (!endswith(etag, "\""))
32 return false;
33
34 if (!startswith(etag, "\"") && !startswith(etag, "W/\""))
35 return false;
36
37 return true;
38}
39
40int import_find_old_etags(const char *url, const char *image_root, int dt, const char *prefix, const char *suffix, char ***etags) {
41 _cleanup_free_ char *escaped_url = NULL;
42 _cleanup_closedir_ DIR *d = NULL;
43 _cleanup_strv_free_ char **l = NULL;
44 struct dirent *de;
45 int r;
46
47 assert(url);
48 assert(etags);
49
50 if (!image_root)
51 image_root = "/var/lib/machines";
52
53 escaped_url = xescape(url, FILENAME_ESCAPE);
54 if (!escaped_url)
55 return -ENOMEM;
56
57 d = opendir(image_root);
58 if (!d) {
59 if (errno == ENOENT) {
60 *etags = NULL;
61 return 0;
62 }
63
64 return -errno;
65 }
66
67 FOREACH_DIRENT_ALL(de, d, return -errno) {
68 const char *a, *b;
69 char *u;
70
71 if (de->d_type != DT_UNKNOWN &&
72 de->d_type != dt)
73 continue;
74
75 if (prefix) {
76 a = startswith(de->d_name, prefix);
77 if (!a)
78 continue;
79 } else
80 a = de->d_name;
81
82 a = startswith(a, escaped_url);
83 if (!a)
84 continue;
85
86 a = startswith(a, ".");
87 if (!a)
88 continue;
89
90 if (suffix) {
91 b = endswith(de->d_name, suffix);
92 if (!b)
93 continue;
94 } else
95 b = strchr(de->d_name, 0);
96
97 if (a >= b)
98 continue;
99
100 u = cunescape_length(a, b - a);
101 if (!u)
102 return -ENOMEM;
103
104 if (!http_etag_is_valid(u)) {
105 free(u);
106 continue;
107 }
108
109 r = strv_consume(&l, u);
110 if (r < 0)
111 return r;
112 }
113
114 *etags = l;
115 l = NULL;
116
117 return 0;
118}
119
120int import_make_local_copy(const char *final, const char *image_root, const char *local, bool force_local) {
121 const char *p;
122 int r;
123
124 assert(final);
125 assert(local);
126
127 if (!image_root)
128 image_root = "/var/lib/machines";
129
130 p = strappenda(image_root, "/", local);
131
132 if (force_local) {
133 (void) btrfs_subvol_remove(p);
134 (void) rm_rf_dangerous(p, false, true, false);
135 }
136
137 r = btrfs_subvol_snapshot(final, p, false, false);
138 if (r == -ENOTTY) {
139 r = copy_tree(final, p, false);
140 if (r < 0)
141 return log_error_errno(r, "Failed to copy image: %m");
142 } else if (r < 0)
143 return log_error_errno(r, "Failed to create local image: %m");
144
145 log_info("Created new local image '%s'.", local);
146
147 return 0;
148}
149
150int import_make_read_only(const char *path) {
151 int r;
152
153 r = btrfs_subvol_set_read_only(path, true);
154 if (r == -ENOTTY) {
155 struct stat st;
156
157 r = stat(path, &st);
158 if (r < 0)
159 return log_error_errno(errno, "Failed to stat temporary image: %m");
160
161 if (chmod(path, st.st_mode & 0755) < 0)
162 return log_error_errno(errno, "Failed to chmod() final image: %m");
163
164 return 0;
165 }
166 if (r < 0)
167 return log_error_errno(r, "Failed to mark final image read-only: %m");
168
169 return 0;
170}
171
172int import_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret) {
173 _cleanup_free_ char *escaped_url = NULL;
174 char *path;
175
176 assert(url);
177 assert(ret);
178
179 if (!image_root)
180 image_root = "/var/lib/machines";
181
182 escaped_url = xescape(url, FILENAME_ESCAPE);
183 if (!escaped_url)
184 return -ENOMEM;
185
186 if (etag) {
187 _cleanup_free_ char *escaped_etag = NULL;
188
189 escaped_etag = xescape(etag, FILENAME_ESCAPE);
190 if (!escaped_etag)
191 return -ENOMEM;
192
193 path = strjoin(image_root, "/", strempty(prefix), escaped_url, ".", escaped_etag, strempty(suffix), NULL);
194 } else
195 path = strjoin(image_root, "/", strempty(prefix), escaped_url, strempty(suffix), NULL);
196 if (!path)
197 return -ENOMEM;
198
199 *ret = path;
200 return 0;
201}