1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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
;
47 log_debug("Scanning autostart directory \"%s\"…", *path
);
50 log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_WARNING
, errno
,
51 "Opening %s failed, ignoring: %m", *path
);
55 FOREACH_DIRENT(de
, d
, log_warning_errno(errno
, "Failed to enumerate directory %s, ignoring: %m", *path
)) {
57 if (fstatat(dirfd(d
), de
->d_name
, &st
, 0) < 0) {
58 log_warning_errno(errno
, "%s/%s: stat() failed, ignoring: %m", *path
, de
->d_name
);
62 if (!S_ISREG(st
.st_mode
)) {
63 log_debug("%s/%s: not a regular file, ignoring.", *path
, de
->d_name
);
67 _cleanup_free_
char *name
= xdg_autostart_service_translate_name(de
->d_name
);
71 if (hashmap_contains(all_services
, name
)) {
72 log_debug("%s/%s: we have already seen \"%s\", ignoring.",
73 *path
, de
->d_name
, name
);
77 _cleanup_free_
char *fpath
= path_join(*path
, de
->d_name
);
81 _cleanup_(xdg_autostart_service_freep
) XdgAutostartService
*service
=
82 xdg_autostart_service_parse_desktop(fpath
);
85 service
->name
= TAKE_PTR(name
);
87 r
= hashmap_put(all_services
, service
->name
, service
);
97 static int run(const char *dest
, const char *dest_early
, const char *dest_late
) {
98 _cleanup_(hashmap_freep
) Hashmap
*all_services
= NULL
;
99 XdgAutostartService
*service
;
102 assert_se(dest_late
);
104 all_services
= hashmap_new(&xdgautostartservice_hash_ops
);
108 r
= enumerate_xdg_autostart(all_services
);
112 HASHMAP_FOREACH(service
, all_services
)
113 (void) xdg_autostart_service_generate_unit(service
, dest_late
);
118 DEFINE_MAIN_GENERATOR_FUNCTION(run
);