Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <getopt.h>
4 : :
5 : : #include "fd-util.h"
6 : : #include "generator.h"
7 : : #include "macro.h"
8 : : #include "main-func.h"
9 : : #include "mkdir.h"
10 : : #include "network-generator.h"
11 : : #include "path-util.h"
12 : : #include "proc-cmdline.h"
13 : :
14 : : #define NETWORKD_UNIT_DIRECTORY "/run/systemd/network"
15 : :
16 : : static const char *arg_root = NULL;
17 : :
18 : 0 : static int network_save(Network *network, const char *dest_dir) {
19 : 0 : _cleanup_free_ char *filename = NULL;
20 : 0 : _cleanup_fclose_ FILE *f = NULL;
21 : : int r;
22 : :
23 [ # # ]: 0 : assert(network);
24 : :
25 [ # # # # ]: 0 : r = asprintf(&filename, "%s-%s.network",
26 : 0 : isempty(network->ifname) ? "91" : "90",
27 : 0 : isempty(network->ifname) ? "default" : network->ifname);
28 [ # # ]: 0 : if (r < 0)
29 : 0 : return log_oom();
30 : :
31 : 0 : r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f);
32 [ # # ]: 0 : if (r < 0)
33 : 0 : return r;
34 : :
35 : 0 : network_dump(network, f);
36 : :
37 : 0 : return 0;
38 : : }
39 : :
40 : 0 : static int netdev_save(NetDev *netdev, const char *dest_dir) {
41 : 0 : _cleanup_free_ char *filename = NULL;
42 : 0 : _cleanup_fclose_ FILE *f = NULL;
43 : : int r;
44 : :
45 [ # # ]: 0 : assert(netdev);
46 : :
47 : 0 : r = asprintf(&filename, "90-%s.netdev",
48 : : netdev->ifname);
49 [ # # ]: 0 : if (r < 0)
50 : 0 : return log_oom();
51 : :
52 : 0 : r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f);
53 [ # # ]: 0 : if (r < 0)
54 : 0 : return r;
55 : :
56 : 0 : netdev_dump(netdev, f);
57 : :
58 : 0 : return 0;
59 : : }
60 : :
61 : 0 : static int link_save(Link *link, const char *dest_dir) {
62 : 0 : _cleanup_free_ char *filename = NULL;
63 : 0 : _cleanup_fclose_ FILE *f = NULL;
64 : : int r;
65 : :
66 [ # # ]: 0 : assert(link);
67 : :
68 : 0 : r = asprintf(&filename, "90-%s.link",
69 : : link->ifname);
70 [ # # ]: 0 : if (r < 0)
71 : 0 : return log_oom();
72 : :
73 : 0 : r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f);
74 [ # # ]: 0 : if (r < 0)
75 : 0 : return r;
76 : :
77 : 0 : link_dump(link, f);
78 : :
79 : 0 : return 0;
80 : : }
81 : :
82 : 0 : static int context_save(Context *context) {
83 : : Network *network;
84 : : NetDev *netdev;
85 : : Link *link;
86 : : Iterator i;
87 : 0 : int k, r = 0;
88 : : const char *p;
89 : :
90 [ # # # # : 0 : p = prefix_roota(arg_root, NETWORKD_UNIT_DIRECTORY);
# # # # #
# # # # #
# # ]
91 : :
92 : 0 : r = mkdir_p(p, 0755);
93 [ # # ]: 0 : if (r < 0)
94 [ # # ]: 0 : return log_error_errno(r, "Failed to create directory " NETWORKD_UNIT_DIRECTORY ": %m");
95 : :
96 [ # # ]: 0 : HASHMAP_FOREACH(network, context->networks_by_name, i) {
97 : 0 : k = network_save(network, p);
98 [ # # # # ]: 0 : if (k < 0 && r >= 0)
99 : 0 : r = k;
100 : : }
101 : :
102 [ # # ]: 0 : HASHMAP_FOREACH(netdev, context->netdevs_by_name, i) {
103 : 0 : k = netdev_save(netdev, p);
104 [ # # # # ]: 0 : if (k < 0 && r >= 0)
105 : 0 : r = k;
106 : : }
107 : :
108 [ # # ]: 0 : HASHMAP_FOREACH(link, context->links_by_name, i) {
109 : 0 : k = link_save(link, p);
110 [ # # # # ]: 0 : if (k < 0 && r >= 0)
111 : 0 : r = k;
112 : : }
113 : :
114 : 0 : return r;
115 : : }
116 : :
117 : 0 : static int help(void) {
118 : 0 : printf("%s [OPTIONS...] [-- KERNEL_CMDLINE]\n"
119 : : " -h --help Show this help\n"
120 : : " --version Show package version\n"
121 : : , program_invocation_short_name
122 : : );
123 : :
124 : 0 : return 0;
125 : : }
126 : :
127 : 0 : static int parse_argv(int argc, char *argv[]) {
128 : : enum {
129 : : ARG_VERSION = 0x100,
130 : : ARG_ROOT,
131 : : };
132 : : static const struct option options[] = {
133 : : { "help", no_argument, NULL, 'h' },
134 : : { "version", no_argument, NULL, ARG_VERSION },
135 : : { "root", required_argument, NULL, ARG_ROOT },
136 : : {},
137 : : };
138 : : int c;
139 : :
140 [ # # ]: 0 : assert(argc >= 0);
141 [ # # ]: 0 : assert(argv);
142 : :
143 [ # # ]: 0 : while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
144 : :
145 [ # # # # : 0 : switch (c) {
# ]
146 : :
147 : 0 : case 'h':
148 : 0 : return help();
149 : :
150 : 0 : case ARG_VERSION:
151 : 0 : return version();
152 : :
153 : 0 : case ARG_ROOT:
154 : 0 : arg_root = optarg;
155 : 0 : break;
156 : :
157 : 0 : case '?':
158 : 0 : return -EINVAL;
159 : :
160 : 0 : default:
161 : 0 : assert_not_reached("Unhandled option");
162 : : }
163 : :
164 : 0 : return 1;
165 : : }
166 : :
167 : 0 : static int run(int argc, char *argv[]) {
168 : 0 : _cleanup_(context_clear) Context context = {};
169 : : int i, r;
170 : :
171 : 0 : r = parse_argv(argc, argv);
172 [ # # ]: 0 : if (r <= 0)
173 : 0 : return r;
174 : :
175 [ # # ]: 0 : if (optind >= argc) {
176 : 0 : r = proc_cmdline_parse(parse_cmdline_item, &context, 0);
177 [ # # ]: 0 : if (r < 0)
178 [ # # ]: 0 : return log_warning_errno(r, "Failed to parse kernel command line: %m");
179 : : } else {
180 [ # # ]: 0 : for (i = optind; i < argc; i++) {
181 [ # # ]: 0 : _cleanup_free_ char *word = NULL;
182 : : char *value;
183 : :
184 : 0 : word = strdup(argv[i]);
185 [ # # ]: 0 : if (!word)
186 : 0 : return log_oom();
187 : :
188 : 0 : value = strchr(word, '=');
189 [ # # ]: 0 : if (value)
190 : 0 : *(value++) = 0;
191 : :
192 : 0 : r = parse_cmdline_item(word, value, &context);
193 [ # # ]: 0 : if (r < 0)
194 [ # # # # ]: 0 : return log_warning_errno(r, "Failed to parse command line \"%s%s%s\": %m",
195 : : word, value ? "=" : "", strempty(value));
196 : : }
197 : : }
198 : :
199 : 0 : r = context_merge_networks(&context);
200 [ # # ]: 0 : if (r < 0)
201 [ # # ]: 0 : return log_warning_errno(r, "Failed to merge multiple command line options: %m");
202 : :
203 : 0 : return context_save(&context);
204 : : }
205 : :
206 : 0 : DEFINE_MAIN_FUNCTION(run);
|