@@ -1091,6 +1091,70 @@ static int property_get_extension_images(
10911091 return sd_bus_message_close_container (reply );
10921092}
10931093
1094+ static int bus_property_get_exec_dir (
1095+ sd_bus * bus ,
1096+ const char * path ,
1097+ const char * interface ,
1098+ const char * property ,
1099+ sd_bus_message * reply ,
1100+ void * userdata ,
1101+ sd_bus_error * error ) {
1102+
1103+ ExecDirectory * d = userdata ;
1104+ int r ;
1105+
1106+ assert (bus );
1107+ assert (d );
1108+ assert (property );
1109+ assert (reply );
1110+
1111+ r = sd_bus_message_open_container (reply , 'a' , "s" );
1112+ if (r < 0 )
1113+ return r ;
1114+
1115+ for (size_t i = 0 ; i < d -> n_items ; i ++ ) {
1116+ r = sd_bus_message_append_basic (reply , 's' , d -> items [i ].path );
1117+ if (r < 0 )
1118+ return r ;
1119+ }
1120+
1121+ return sd_bus_message_close_container (reply );
1122+ }
1123+
1124+ static int bus_property_get_exec_dir_symlink (
1125+ sd_bus * bus ,
1126+ const char * path ,
1127+ const char * interface ,
1128+ const char * property ,
1129+ sd_bus_message * reply ,
1130+ void * userdata ,
1131+ sd_bus_error * error ) {
1132+
1133+ ExecDirectory * d = userdata ;
1134+ int r ;
1135+
1136+ assert (bus );
1137+ assert (d );
1138+ assert (property );
1139+ assert (reply );
1140+
1141+ r = sd_bus_message_open_container (reply , 'a' , "(sst)" );
1142+ if (r < 0 )
1143+ return r ;
1144+
1145+ for (size_t i = 0 ; i < d -> n_items ; i ++ ) {
1146+ char * * dst ;
1147+
1148+ STRV_FOREACH (dst , d -> items [i ].symlinks ) {
1149+ r = sd_bus_message_append (reply , "(sst)" , d -> items [i ].path , * dst , 0 /* flags, unused for now */ );
1150+ if (r < 0 )
1151+ return r ;
1152+ }
1153+ }
1154+
1155+ return sd_bus_message_close_container (reply );
1156+ }
1157+
10941158const sd_bus_vtable bus_exec_vtable [] = {
10951159 SD_BUS_VTABLE_START (0 ),
10961160 SD_BUS_PROPERTY ("Environment" , "as" , NULL , offsetof(ExecContext , environment ), SD_BUS_VTABLE_PROPERTY_CONST ),
@@ -1224,17 +1288,21 @@ const sd_bus_vtable bus_exec_vtable[] = {
12241288 SD_BUS_PROPERTY ("Personality" , "s" , property_get_personality , offsetof(ExecContext , personality ), SD_BUS_VTABLE_PROPERTY_CONST ),
12251289 SD_BUS_PROPERTY ("LockPersonality" , "b" , bus_property_get_bool , offsetof(ExecContext , lock_personality ), SD_BUS_VTABLE_PROPERTY_CONST ),
12261290 SD_BUS_PROPERTY ("RestrictAddressFamilies" , "(bas)" , property_get_address_families , 0 , SD_BUS_VTABLE_PROPERTY_CONST ),
1291+ SD_BUS_PROPERTY ("RuntimeDirectorySymlink" , "a(sst)" , bus_property_get_exec_dir_symlink , offsetof(ExecContext , directories [EXEC_DIRECTORY_RUNTIME ]), SD_BUS_VTABLE_PROPERTY_CONST ),
12271292 SD_BUS_PROPERTY ("RuntimeDirectoryPreserve" , "s" , property_get_exec_preserve_mode , offsetof(ExecContext , runtime_directory_preserve_mode ), SD_BUS_VTABLE_PROPERTY_CONST ),
12281293 SD_BUS_PROPERTY ("RuntimeDirectoryMode" , "u" , bus_property_get_mode , offsetof(ExecContext , directories [EXEC_DIRECTORY_RUNTIME ].mode ), SD_BUS_VTABLE_PROPERTY_CONST ),
1229- SD_BUS_PROPERTY ("RuntimeDirectory" , "as" , NULL , offsetof(ExecContext , directories [EXEC_DIRECTORY_RUNTIME ].paths ), SD_BUS_VTABLE_PROPERTY_CONST ),
1294+ SD_BUS_PROPERTY ("RuntimeDirectory" , "as" , bus_property_get_exec_dir , offsetof(ExecContext , directories [EXEC_DIRECTORY_RUNTIME ]), SD_BUS_VTABLE_PROPERTY_CONST ),
1295+ SD_BUS_PROPERTY ("StateDirectorySymlink" , "a(sst)" , bus_property_get_exec_dir_symlink , offsetof(ExecContext , directories [EXEC_DIRECTORY_STATE ]), SD_BUS_VTABLE_PROPERTY_CONST ),
12301296 SD_BUS_PROPERTY ("StateDirectoryMode" , "u" , bus_property_get_mode , offsetof(ExecContext , directories [EXEC_DIRECTORY_STATE ].mode ), SD_BUS_VTABLE_PROPERTY_CONST ),
1231- SD_BUS_PROPERTY ("StateDirectory" , "as" , NULL , offsetof(ExecContext , directories [EXEC_DIRECTORY_STATE ].paths ), SD_BUS_VTABLE_PROPERTY_CONST ),
1297+ SD_BUS_PROPERTY ("StateDirectory" , "as" , bus_property_get_exec_dir , offsetof(ExecContext , directories [EXEC_DIRECTORY_STATE ]), SD_BUS_VTABLE_PROPERTY_CONST ),
1298+ SD_BUS_PROPERTY ("CacheDirectorySymlink" , "a(sst)" , bus_property_get_exec_dir_symlink , offsetof(ExecContext , directories [EXEC_DIRECTORY_CACHE ]), SD_BUS_VTABLE_PROPERTY_CONST ),
12321299 SD_BUS_PROPERTY ("CacheDirectoryMode" , "u" , bus_property_get_mode , offsetof(ExecContext , directories [EXEC_DIRECTORY_CACHE ].mode ), SD_BUS_VTABLE_PROPERTY_CONST ),
1233- SD_BUS_PROPERTY ("CacheDirectory" , "as" , NULL , offsetof(ExecContext , directories [EXEC_DIRECTORY_CACHE ].paths ), SD_BUS_VTABLE_PROPERTY_CONST ),
1300+ SD_BUS_PROPERTY ("CacheDirectory" , "as" , bus_property_get_exec_dir , offsetof(ExecContext , directories [EXEC_DIRECTORY_CACHE ]), SD_BUS_VTABLE_PROPERTY_CONST ),
1301+ SD_BUS_PROPERTY ("LogsDirectorySymlink" , "a(sst)" , bus_property_get_exec_dir_symlink , offsetof(ExecContext , directories [EXEC_DIRECTORY_LOGS ]), SD_BUS_VTABLE_PROPERTY_CONST ),
12341302 SD_BUS_PROPERTY ("LogsDirectoryMode" , "u" , bus_property_get_mode , offsetof(ExecContext , directories [EXEC_DIRECTORY_LOGS ].mode ), SD_BUS_VTABLE_PROPERTY_CONST ),
1235- SD_BUS_PROPERTY ("LogsDirectory" , "as" , NULL , offsetof(ExecContext , directories [EXEC_DIRECTORY_LOGS ]. paths ), SD_BUS_VTABLE_PROPERTY_CONST ),
1303+ SD_BUS_PROPERTY ("LogsDirectory" , "as" , bus_property_get_exec_dir , offsetof(ExecContext , directories [EXEC_DIRECTORY_LOGS ]), SD_BUS_VTABLE_PROPERTY_CONST ),
12361304 SD_BUS_PROPERTY ("ConfigurationDirectoryMode" , "u" , bus_property_get_mode , offsetof(ExecContext , directories [EXEC_DIRECTORY_CONFIGURATION ].mode ), SD_BUS_VTABLE_PROPERTY_CONST ),
1237- SD_BUS_PROPERTY ("ConfigurationDirectory" , "as" , NULL , offsetof(ExecContext , directories [EXEC_DIRECTORY_CONFIGURATION ]. paths ), SD_BUS_VTABLE_PROPERTY_CONST ),
1305+ SD_BUS_PROPERTY ("ConfigurationDirectory" , "as" , bus_property_get_exec_dir , offsetof(ExecContext , directories [EXEC_DIRECTORY_CONFIGURATION ]), SD_BUS_VTABLE_PROPERTY_CONST ),
12381306 SD_BUS_PROPERTY ("TimeoutCleanUSec" , "t" , bus_property_get_usec , offsetof(ExecContext , timeout_clean_usec ), SD_BUS_VTABLE_PROPERTY_CONST ),
12391307 SD_BUS_PROPERTY ("MemoryDenyWriteExecute" , "b" , bus_property_get_bool , offsetof(ExecContext , memory_deny_write_execute ), SD_BUS_VTABLE_PROPERTY_CONST ),
12401308 SD_BUS_PROPERTY ("RestrictRealtime" , "b" , bus_property_get_bool , offsetof(ExecContext , restrict_realtime ), SD_BUS_VTABLE_PROPERTY_CONST ),
@@ -3294,14 +3362,17 @@ int bus_exec_context_set_transient_property(
32943362 d = c -> directories + i ;
32953363
32963364 if (strv_isempty (l )) {
3297- d -> paths = strv_free ( d -> paths );
3365+ exec_directory_done ( d );
32983366 unit_write_settingf (u , flags , name , "%s=" , name );
32993367 } else {
33003368 _cleanup_free_ char * joined = NULL ;
3369+ char * * source ;
33013370
3302- r = strv_extend_strv (& d -> paths , l , true);
3303- if (r < 0 )
3304- return r ;
3371+ STRV_FOREACH (source , l ) {
3372+ r = exec_directory_add (& d -> items , & d -> n_items , * source , NULL );
3373+ if (r < 0 )
3374+ return log_oom ();
3375+ }
33053376
33063377 joined = unit_concat_strv (l , UNIT_ESCAPE_SPECIFIERS );
33073378 if (!joined )
@@ -3711,6 +3782,79 @@ int bus_exec_context_set_transient_property(
37113782 extension_images = mount_image_free_many (extension_images , & n_extension_images );
37123783
37133784 return 1 ;
3785+
3786+ } else if (STR_IN_SET (name , "StateDirectorySymlink" , "RuntimeDirectorySymlink" , "CacheDirectorySymlink" , "LogsDirectorySymlink" )) {
3787+ char * source , * destination ;
3788+ ExecDirectory * directory ;
3789+ uint64_t symlink_flags ; /* No flags for now, reserved for future uses. */
3790+ ExecDirectoryType i ;
3791+
3792+ assert_se ((i = exec_directory_type_symlink_from_string (name )) >= 0 );
3793+ directory = c -> directories + i ;
3794+
3795+ r = sd_bus_message_enter_container (message , 'a' , "(sst)" );
3796+ if (r < 0 )
3797+ return r ;
3798+
3799+ while ((r = sd_bus_message_read (message , "(sst)" , & source , & destination , & symlink_flags )) > 0 ) {
3800+ if (!path_is_valid (source ))
3801+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Source path %s is not valid." , source );
3802+ if (path_is_absolute (source ))
3803+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Source path %s is absolute." , source );
3804+ if (!path_is_normalized (source ))
3805+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Source path %s is not normalized." , source );
3806+ if (!path_is_valid (destination ))
3807+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Destination path %s is not valid." , destination );
3808+ if (path_is_absolute (destination ))
3809+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Destination path %s is absolute." , destination );
3810+ if (!path_is_normalized (destination ))
3811+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Destination path %s is not normalized." , destination );
3812+ if (symlink_flags != 0 )
3813+ return sd_bus_error_setf (error , SD_BUS_ERROR_INVALID_ARGS , "Flags must be zero." );
3814+
3815+ if (!UNIT_WRITE_FLAGS_NOOP (flags )) {
3816+ _cleanup_free_ char * destination_escaped = NULL , * source_escaped = NULL ;
3817+ ExecDirectoryItem * item = NULL ;
3818+
3819+ /* Adding new directories is supported from both *DirectorySymlink methods and the
3820+ * older ones, so try to find an existing configuration first and create it if it's
3821+ * not there yet. */
3822+ for (size_t j = 0 ; j < directory -> n_items ; ++ j )
3823+ if (path_equal (source , directory -> items [j ].path )) {
3824+ item = & directory -> items [j ];
3825+ break ;
3826+ }
3827+
3828+ if (item )
3829+ r = strv_extend (& item -> symlinks , destination );
3830+ else
3831+ r = exec_directory_add (& directory -> items , & directory -> n_items , source , STRV_MAKE (destination ));
3832+ if (r < 0 )
3833+ return r ;
3834+
3835+ /* Need to store them in the unit with the escapes, so that they can be parsed again */
3836+ source_escaped = xescape (source , ":" );
3837+ destination_escaped = xescape (destination , ":" );
3838+ if (!source_escaped || !destination_escaped )
3839+ return - ENOMEM ;
3840+
3841+ unit_write_settingf (
3842+ u , flags |UNIT_ESCAPE_SPECIFIERS , exec_directory_type_to_string (i ),
3843+ "%s=%s:%s" ,
3844+ exec_directory_type_to_string (i ),
3845+ source_escaped ,
3846+ destination_escaped );
3847+ }
3848+ }
3849+ if (r < 0 )
3850+ return r ;
3851+
3852+ r = sd_bus_message_exit_container (message );
3853+ if (r < 0 )
3854+ return r ;
3855+
3856+ return 1 ;
3857+
37143858 }
37153859
37163860 return 0 ;
0 commit comments