77#include <sys/mount.h>
88#include <unistd.h>
99
10+ #include "sd-bus.h"
11+
1012#include "build.h"
13+ #include "bus-locator.h"
14+ #include "bus-error.h"
15+ #include "bus-unit-util.h"
16+ #include "bus-util.h"
1117#include "capability-util.h"
1218#include "chase.h"
19+ #include "constants.h"
1320#include "devnum-util.h"
1421#include "discover-image.h"
1522#include "dissect-image.h"
@@ -45,6 +52,7 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
4552static PagerFlags arg_pager_flags = 0 ;
4653static bool arg_legend = true;
4754static bool arg_force = false;
55+ static bool arg_no_reload = false;
4856static int arg_noexec = -1 ;
4957static ImagePolicy * arg_image_policy = NULL ;
5058
@@ -144,6 +152,87 @@ static int is_our_mount_point(const char *p) {
144152 return true;
145153}
146154
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+
147236static int unmerge_hierarchy (const char * p ) {
148237 int r ;
149238
@@ -169,6 +258,12 @@ static int unmerge_hierarchy(const char *p) {
169258
170259static int unmerge (void ) {
171260 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 ;
172267
173268 STRV_FOREACH (p , arg_hierarchies ) {
174269 _cleanup_free_ char * resolved = NULL ;
@@ -191,6 +286,12 @@ static int unmerge(void) {
191286 ret = r ;
192287 }
193288
289+ if (need_to_reload ) {
290+ r = daemon_reload ();
291+ if (r < 0 )
292+ return r ;
293+ }
294+
194295 return ret ;
195296}
196297
@@ -784,7 +885,19 @@ static int merge(Hashmap *images) {
784885 if (r < 0 )
785886 return r ;
786887
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 ;
788901}
789902
790903static int image_discover_and_read_metadata (Hashmap * * ret_images ) {
@@ -955,6 +1068,7 @@ static int verb_help(int argc, char **argv, void *userdata) {
9551068 " --json=pretty|short|off\n"
9561069 " Generate JSON output\n"
9571070 " --force Ignore version incompatibilities\n"
1071+ " --no-reload Do not reload the service manager\n"
9581072 " --image-policy=POLICY\n"
9591073 " Specify disk image dissection policy\n"
9601074 " --noexec=BOOL Whether to mount extension overlay with noexec\n"
@@ -980,6 +1094,7 @@ static int parse_argv(int argc, char *argv[]) {
9801094 ARG_FORCE ,
9811095 ARG_IMAGE_POLICY ,
9821096 ARG_NOEXEC ,
1097+ ARG_NO_RELOAD ,
9831098 };
9841099
9851100 static const struct option options [] = {
@@ -992,6 +1107,7 @@ static int parse_argv(int argc, char *argv[]) {
9921107 { "force" , no_argument , NULL , ARG_FORCE },
9931108 { "image-policy" , required_argument , NULL , ARG_IMAGE_POLICY },
9941109 { "noexec" , required_argument , NULL , ARG_NOEXEC },
1110+ { "no-reload" , no_argument , NULL , ARG_NO_RELOAD },
9951111 {}
9961112 };
9971113
@@ -1049,6 +1165,10 @@ static int parse_argv(int argc, char *argv[]) {
10491165 arg_noexec = r ;
10501166 break ;
10511167
1168+ case ARG_NO_RELOAD :
1169+ arg_no_reload = true;
1170+ break ;
1171+
10521172 case '?' :
10531173 return - EINVAL ;
10541174
0 commit comments