]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
8feca247 BB |
2 | |
3 | #include <errno.h> | |
4 | #include <stdio.h> | |
5 | #include <unistd.h> | |
6 | ||
7 | #include "dirent-util.h" | |
8 | #include "fd-util.h" | |
9 | #include "generator.h" | |
28e5e1e9 | 10 | #include "glyph-util.h" |
8feca247 BB |
11 | #include "hashmap.h" |
12 | #include "log.h" | |
13 | #include "main-func.h" | |
14 | #include "nulstr-util.h" | |
15 | #include "path-lookup.h" | |
16 | #include "stat-util.h" | |
17 | #include "string-util.h" | |
18 | #include "strv.h" | |
19 | #include "xdg-autostart-service.h" | |
20 | ||
21 | DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(xdgautostartservice_hash_ops, char, string_hash_func, string_compare_func, XdgAutostartService, xdg_autostart_service_free); | |
22 | ||
23 | static int enumerate_xdg_autostart(Hashmap *all_services) { | |
24 | _cleanup_strv_free_ char **autostart_dirs = NULL; | |
25 | _cleanup_strv_free_ char **config_dirs = NULL; | |
26 | _unused_ _cleanup_strv_free_ char **data_dirs = NULL; | |
27 | _cleanup_free_ char *user_config_autostart_dir = NULL; | |
8feca247 BB |
28 | int r; |
29 | ||
30 | r = xdg_user_config_dir(&user_config_autostart_dir, "/autostart"); | |
31 | if (r < 0) | |
32 | return r; | |
33 | r = strv_extend(&autostart_dirs, user_config_autostart_dir); | |
34 | if (r < 0) | |
35 | return r; | |
36 | ||
37 | r = xdg_user_dirs(&config_dirs, &data_dirs); | |
38 | if (r < 0) | |
39 | return r; | |
40 | r = strv_extend_strv_concat(&autostart_dirs, config_dirs, "/autostart"); | |
41 | if (r < 0) | |
42 | return r; | |
43 | ||
44 | STRV_FOREACH(path, autostart_dirs) { | |
45 | _cleanup_closedir_ DIR *d = NULL; | |
8feca247 | 46 | |
28e5e1e9 | 47 | log_debug("Scanning autostart directory \"%s\"%s", *path, special_glyph(SPECIAL_GLYPH_ELLIPSIS)); |
8feca247 BB |
48 | d = opendir(*path); |
49 | if (!d) { | |
0d1610c9 ZJS |
50 | log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno, |
51 | "Opening %s failed, ignoring: %m", *path); | |
8feca247 BB |
52 | continue; |
53 | } | |
54 | ||
55 | FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to enumerate directory %s, ignoring: %m", *path)) { | |
8feca247 | 56 | struct stat st; |
8feca247 | 57 | if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { |
0d1610c9 | 58 | log_warning_errno(errno, "%s/%s: stat() failed, ignoring: %m", *path, de->d_name); |
8feca247 BB |
59 | continue; |
60 | } | |
61 | ||
0d1610c9 ZJS |
62 | if (!S_ISREG(st.st_mode)) { |
63 | log_debug("%s/%s: not a regular file, ignoring.", *path, de->d_name); | |
8feca247 | 64 | continue; |
0d1610c9 | 65 | } |
8feca247 | 66 | |
0d1610c9 | 67 | _cleanup_free_ char *name = xdg_autostart_service_translate_name(de->d_name); |
8feca247 BB |
68 | if (!name) |
69 | return log_oom(); | |
70 | ||
0d1610c9 ZJS |
71 | if (hashmap_contains(all_services, name)) { |
72 | log_debug("%s/%s: we have already seen \"%s\", ignoring.", | |
73 | *path, de->d_name, name); | |
8feca247 | 74 | continue; |
0d1610c9 | 75 | } |
8feca247 | 76 | |
0d1610c9 | 77 | _cleanup_free_ char *fpath = path_join(*path, de->d_name); |
8feca247 BB |
78 | if (!fpath) |
79 | return log_oom(); | |
80 | ||
0d1610c9 ZJS |
81 | _cleanup_(xdg_autostart_service_freep) XdgAutostartService *service = |
82 | xdg_autostart_service_parse_desktop(fpath); | |
8feca247 BB |
83 | if (!service) |
84 | return log_oom(); | |
85 | service->name = TAKE_PTR(name); | |
86 | ||
87 | r = hashmap_put(all_services, service->name, service); | |
88 | if (r < 0) | |
89 | return log_oom(); | |
90 | TAKE_PTR(service); | |
91 | } | |
92 | } | |
93 | ||
94 | return 0; | |
95 | } | |
96 | ||
97 | static int run(const char *dest, const char *dest_early, const char *dest_late) { | |
5d2a48da | 98 | _cleanup_hashmap_free_ Hashmap *all_services = NULL; |
8feca247 | 99 | XdgAutostartService *service; |
8feca247 BB |
100 | int r; |
101 | ||
102 | assert_se(dest_late); | |
103 | ||
104 | all_services = hashmap_new(&xdgautostartservice_hash_ops); | |
105 | if (!all_services) | |
106 | return log_oom(); | |
107 | ||
108 | r = enumerate_xdg_autostart(all_services); | |
109 | if (r < 0) | |
110 | return r; | |
111 | ||
90e74a66 | 112 | HASHMAP_FOREACH(service, all_services) |
8feca247 BB |
113 | (void) xdg_autostart_service_generate_unit(service, dest_late); |
114 | ||
115 | return 0; | |
116 | } | |
117 | ||
118 | DEFINE_MAIN_GENERATOR_FUNCTION(run); |