7
7
#include <sys/mount.h>
8
8
#include <unistd.h>
9
9
10
+ #include "sd-bus.h"
11
+
10
12
#include "build.h"
13
+ #include "bus-locator.h"
14
+ #include "bus-error.h"
15
+ #include "bus-unit-util.h"
16
+ #include "bus-util.h"
11
17
#include "capability-util.h"
12
18
#include "chase.h"
19
+ #include "constants.h"
13
20
#include "devnum-util.h"
14
21
#include "discover-image.h"
15
22
#include "dissect-image.h"
@@ -45,6 +52,7 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
45
52
static PagerFlags arg_pager_flags = 0 ;
46
53
static bool arg_legend = true;
47
54
static bool arg_force = false;
55
+ static bool arg_no_reload = false;
48
56
static int arg_noexec = -1 ;
49
57
static ImagePolicy * arg_image_policy = NULL ;
50
58
@@ -144,6 +152,87 @@ static int is_our_mount_point(const char *p) {
144
152
return true;
145
153
}
146
154
155
+ static int need_reload (void ) {
156
+ /* Parse the mounted images to find out if we need
157
+ to reload the daemon. */
158
+ int r ;
159
+
160
+ if (arg_no_reload )
161
+ return false;
162
+
163
+ STRV_FOREACH (p , arg_hierarchies ) {
164
+ _cleanup_free_ char * f = NULL , * buf = NULL , * resolved = NULL ;
165
+ _cleanup_strv_free_ char * * mounted_extensions = NULL ;
166
+
167
+ r = chase (* p , arg_root , CHASE_PREFIX_ROOT , & resolved , NULL );
168
+ if (r == - ENOENT ) {
169
+ log_debug_errno (r , "Hierarchy '%s%s' does not exist, ignoring." , strempty (arg_root ), * p );
170
+ continue ;
171
+ }
172
+ if (r < 0 ) {
173
+ log_warning_errno (r , "Failed to resolve path to hierarchy '%s%s': %m, ignoring." , strempty (arg_root ), * p );
174
+ continue ;
175
+ }
176
+
177
+ r = is_our_mount_point (resolved );
178
+ if (r < 0 )
179
+ return r ;
180
+ if (!r )
181
+ continue ;
182
+
183
+ f = path_join (* p , image_class_info [arg_image_class ].dot_directory_name , image_class_info [arg_image_class ].short_identifier_plural );
184
+ if (!f )
185
+ return log_oom ();
186
+
187
+ r = read_full_file (f , & buf , NULL );
188
+ if (r < 0 )
189
+ return log_error_errno (r , "Failed to open '%s': %m" , f );
190
+
191
+ mounted_extensions = strv_split_newlines (buf );
192
+ if (!mounted_extensions )
193
+ return log_oom ();
194
+
195
+ STRV_FOREACH (extension , mounted_extensions ) {
196
+ _cleanup_strv_free_ char * * extension_release = NULL ;
197
+ const char * extension_reload_manager = NULL ;
198
+ int b ;
199
+
200
+ r = load_extension_release_pairs (arg_root , arg_image_class , * extension , /* relax_extension_release_check */ true, & extension_release );
201
+ if (r < 0 ) {
202
+ log_debug_errno (r , "Failed to parse extension-release metadata of %s, ignoring: %m" , * extension );
203
+ continue ;
204
+ }
205
+
206
+ extension_reload_manager = strv_env_pairs_get (extension_release , "EXTENSION_RELOAD_MANAGER" );
207
+ if (isempty (extension_reload_manager ))
208
+ continue ;
209
+
210
+ b = parse_boolean (extension_reload_manager );
211
+ if (b < 0 ) {
212
+ log_warning_errno (b , "Failed to parse the extension metadata to know if the manager needs to be reloaded, ignoring: %m" );
213
+ continue ;
214
+ }
215
+
216
+ if (b )
217
+ /* If at least one extension wants a reload, we reload. */
218
+ return true;
219
+ }
220
+ }
221
+
222
+ return false;
223
+ }
224
+
225
+ static int daemon_reload (void ) {
226
+ sd_bus * bus ;
227
+ int r ;
228
+
229
+ r = bus_connect_system_systemd (& bus );
230
+ if (r < 0 )
231
+ return log_error_errno (r , "Failed to get D-Bus connection: %m" );
232
+
233
+ return bus_service_manager_reload (bus );
234
+ }
235
+
147
236
static int unmerge_hierarchy (const char * p ) {
148
237
int r ;
149
238
@@ -169,6 +258,12 @@ static int unmerge_hierarchy(const char *p) {
169
258
170
259
static int unmerge (void ) {
171
260
int r , ret = 0 ;
261
+ bool need_to_reload ;
262
+
263
+ r = need_reload ();
264
+ if (r < 0 )
265
+ return r ;
266
+ need_to_reload = r > 0 ;
172
267
173
268
STRV_FOREACH (p , arg_hierarchies ) {
174
269
_cleanup_free_ char * resolved = NULL ;
@@ -191,6 +286,12 @@ static int unmerge(void) {
191
286
ret = r ;
192
287
}
193
288
289
+ if (need_to_reload ) {
290
+ r = daemon_reload ();
291
+ if (r < 0 )
292
+ return r ;
293
+ }
294
+
194
295
return ret ;
195
296
}
196
297
@@ -784,7 +885,19 @@ static int merge(Hashmap *images) {
784
885
if (r < 0 )
785
886
return r ;
786
887
787
- return r != 123 ; /* exit code 123 means: didn't do anything */
888
+ if (r == 123 ) /* exit code 123 means: didn't do anything */
889
+ return 0 ;
890
+
891
+ r = need_reload ();
892
+ if (r < 0 )
893
+ return r ;
894
+ if (r > 0 ) {
895
+ r = daemon_reload ();
896
+ if (r < 0 )
897
+ return r ;
898
+ }
899
+
900
+ return 1 ;
788
901
}
789
902
790
903
static int image_discover_and_read_metadata (Hashmap * * ret_images ) {
@@ -955,6 +1068,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
955
1068
" --json=pretty|short|off\n"
956
1069
" Generate JSON output\n"
957
1070
" --force Ignore version incompatibilities\n"
1071
+ " --no-reload Do not reload the service manager\n"
958
1072
" --image-policy=POLICY\n"
959
1073
" Specify disk image dissection policy\n"
960
1074
" --noexec=BOOL Whether to mount extension overlay with noexec\n"
@@ -980,6 +1094,7 @@ static int parse_argv(int argc, char *argv[]) {
980
1094
ARG_FORCE ,
981
1095
ARG_IMAGE_POLICY ,
982
1096
ARG_NOEXEC ,
1097
+ ARG_NO_RELOAD ,
983
1098
};
984
1099
985
1100
static const struct option options [] = {
@@ -992,6 +1107,7 @@ static int parse_argv(int argc, char *argv[]) {
992
1107
{ "force" , no_argument , NULL , ARG_FORCE },
993
1108
{ "image-policy" , required_argument , NULL , ARG_IMAGE_POLICY },
994
1109
{ "noexec" , required_argument , NULL , ARG_NOEXEC },
1110
+ { "no-reload" , no_argument , NULL , ARG_NO_RELOAD },
995
1111
{}
996
1112
};
997
1113
@@ -1049,6 +1165,10 @@ static int parse_argv(int argc, char *argv[]) {
1049
1165
arg_noexec = r ;
1050
1166
break ;
1051
1167
1168
+ case ARG_NO_RELOAD :
1169
+ arg_no_reload = true;
1170
+ break ;
1171
+
1052
1172
case '?' :
1053
1173
return - EINVAL ;
1054
1174
0 commit comments