1 /* SPDX-License-Identifier: LGPL-2.1+ */
7 #include "dirent-util.h"
12 #include "main-func.h"
13 #include "nulstr-util.h"
14 #include "path-lookup.h"
15 #include "stat-util.h"
16 #include "string-util.h"
18 #include "xdg-autostart-service.h"
20 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(xdgautostartservice_hash_ops
, char, string_hash_func
, string_compare_func
, XdgAutostartService
, xdg_autostart_service_free
);
22 static int enumerate_xdg_autostart(Hashmap
*all_services
) {
23 _cleanup_strv_free_
char **autostart_dirs
= NULL
;
24 _cleanup_strv_free_
char **config_dirs
= NULL
;
25 _unused_ _cleanup_strv_free_
char **data_dirs
= NULL
;
26 _cleanup_free_
char *user_config_autostart_dir
= NULL
;
30 r
= xdg_user_config_dir(&user_config_autostart_dir
, "/autostart");
33 r
= strv_extend(&autostart_dirs
, user_config_autostart_dir
);
37 r
= xdg_user_dirs(&config_dirs
, &data_dirs
);
40 r
= strv_extend_strv_concat(&autostart_dirs
, config_dirs
, "/autostart");
44 STRV_FOREACH(path
, autostart_dirs
) {
45 _cleanup_closedir_
DIR *d
= NULL
;
51 log_warning_errno(errno
, "Opening %s failed, ignoring: %m", *path
);
55 FOREACH_DIRENT(de
, d
, log_warning_errno(errno
, "Failed to enumerate directory %s, ignoring: %m", *path
)) {
56 _cleanup_free_
char *fpath
= NULL
, *name
= NULL
;
57 _cleanup_(xdg_autostart_service_freep
) XdgAutostartService
*service
= NULL
;
60 if (fstatat(dirfd(d
), de
->d_name
, &st
, 0) < 0) {
61 log_warning_errno(errno
, "stat() failed on %s/%s, ignoring: %m", *path
, de
->d_name
);
65 if (!S_ISREG(st
.st_mode
))
68 name
= xdg_autostart_service_translate_name(de
->d_name
);
72 if (hashmap_contains(all_services
, name
))
75 fpath
= path_join(*path
, de
->d_name
);
79 service
= xdg_autostart_service_parse_desktop(fpath
);
82 service
->name
= TAKE_PTR(name
);
84 r
= hashmap_put(all_services
, service
->name
, service
);
94 static int run(const char *dest
, const char *dest_early
, const char *dest_late
) {
95 _cleanup_(hashmap_freep
) Hashmap
*all_services
= NULL
;
96 XdgAutostartService
*service
;
100 assert_se(dest_late
);
102 all_services
= hashmap_new(&xdgautostartservice_hash_ops
);
106 r
= enumerate_xdg_autostart(all_services
);
110 HASHMAP_FOREACH(service
, all_services
, j
)
111 (void) xdg_autostart_service_generate_unit(service
, dest_late
);
116 DEFINE_MAIN_GENERATOR_FUNCTION(run
);