]> git.ipfire.org Git - thirdparty/dracut.git/blob - install/dracut-install.c
5d48e9d56f27205dab61e4bbaa1f2bd7eabf28f3
[thirdparty/dracut.git] / install / dracut-install.c
1 /* dracut-install.c -- install files and executables
2
3 Copyright (C) 2012 Harald Hoyer
4 Copyright (C) 2012 Red Hat, Inc. All rights reserved.
5
6 This program is free software: you can redistribute it and/or modify
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this program; If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #define PROGRAM_VERSION_STRING "2"
21
22 #ifndef _GNU_SOURCE
23 #define _GNU_SOURCE
24 #endif
25 #undef _FILE_OFFSET_BITS
26 #include <ctype.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <getopt.h>
30 #include <libgen.h>
31 #include <limits.h>
32 #include <stdbool.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <sys/wait.h>
39 #include <unistd.h>
40 #include <sys/ioctl.h>
41 #include <libkmod.h>
42 #include <fts.h>
43 #include <regex.h>
44 #include <sys/utsname.h>
45
46 #include "log.h"
47 #include "hashmap.h"
48 #include "util.h"
49 #include "strv.h"
50
51 static bool arg_hmac = false;
52 static bool arg_createdir = false;
53 static int arg_loglevel = -1;
54 static bool arg_optional = false;
55 static bool arg_silent = false;
56 static bool arg_all = false;
57 static bool arg_module = false;
58 static bool arg_modalias = false;
59 static bool arg_resolvelazy = false;
60 static bool arg_resolvedeps = false;
61 static bool arg_hostonly = false;
62 static bool no_xattr = false;
63 static char *destrootdir = NULL;
64 static char *sysrootdir = NULL;
65 static size_t sysrootdirlen = 0;
66 static char *kerneldir = NULL;
67 static size_t kerneldirlen = 0;
68 static char **firmwaredirs = NULL;
69 static char **pathdirs;
70 static char *ldd = NULL;
71 static char *logdir = NULL;
72 static char *logfile = NULL;
73 FILE *logfile_f = NULL;
74 static Hashmap *items = NULL;
75 static Hashmap *items_failed = NULL;
76 static Hashmap *modules_loaded = NULL;
77 static regex_t mod_filter_path;
78 static regex_t mod_filter_nopath;
79 static regex_t mod_filter_symbol;
80 static regex_t mod_filter_nosymbol;
81 static regex_t mod_filter_noname;
82 static bool arg_mod_filter_path = false;
83 static bool arg_mod_filter_nopath = false;
84 static bool arg_mod_filter_symbol = false;
85 static bool arg_mod_filter_nosymbol = false;
86 static bool arg_mod_filter_noname = false;
87
88 static int dracut_install(const char *src, const char *dst, bool isdir, bool resolvedeps, bool hashdst);
89
90
91 static inline void kmod_module_unrefp(struct kmod_module **p) {
92 if (*p)
93 kmod_module_unref(*p);
94 }
95 #define _cleanup_kmod_module_unref_ _cleanup_(kmod_module_unrefp)
96
97 static inline void kmod_module_unref_listp(struct kmod_list **p) {
98 if (*p)
99 kmod_module_unref_list(*p);
100 }
101 #define _cleanup_kmod_module_unref_list_ _cleanup_(kmod_module_unref_listp)
102
103 static inline void kmod_module_info_free_listp(struct kmod_list **p) {
104 if (*p)
105 kmod_module_info_free_list(*p);
106 }
107 #define _cleanup_kmod_module_info_free_list_ _cleanup_(kmod_module_info_free_listp)
108
109 static inline void kmod_unrefp(struct kmod_ctx **p) {
110 kmod_unref(*p);
111 }
112 #define _cleanup_kmod_unref_ _cleanup_(kmod_unrefp)
113
114 static inline void kmod_module_dependency_symbols_free_listp(struct kmod_list **p) {
115 if (*p)
116 kmod_module_dependency_symbols_free_list(*p);
117 }
118 #define _cleanup_kmod_module_dependency_symbols_free_list_ _cleanup_(kmod_module_dependency_symbols_free_listp)
119
120 static inline void fts_closep(FTS **p) {
121 if (*p)
122 fts_close(*p);
123 }
124 #define _cleanup_fts_close_ _cleanup_(fts_closep)
125
126
127
128 static size_t dir_len(char const *file)
129 {
130 size_t length;
131
132 if (!file)
133 return 0;
134
135 /* Strip the basename and any redundant slashes before it. */
136 for (length = strlen(file) - 1; 0 < length; length--)
137 if (file[length] == '/' && file[length - 1] != '/')
138 break;
139 return length;
140 }
141
142 static char *convert_abs_rel(const char *from, const char *target)
143 {
144 /* we use the 4*MAXPATHLEN, which should not overrun */
145 char relative_from[MAXPATHLEN * 4];
146 _cleanup_free_ char *realtarget = NULL;
147 _cleanup_free_ char *target_dir_p = NULL, *realpath_p = NULL;
148 const char *realfrom = from;
149 size_t level = 0, fromlevel = 0, targetlevel = 0;
150 int l;
151 size_t i, rl, dirlen;
152 int ret;
153
154 target_dir_p = strdup(target);
155 if (!target_dir_p)
156 return strdup(from);
157
158 dirlen = dir_len(target_dir_p);
159 target_dir_p[dirlen] = '\0';
160 realpath_p = realpath(target_dir_p, NULL);
161
162 if (realpath_p == NULL) {
163 log_warning("convert_abs_rel(): target '%s' directory has no realpath.", target);
164 return strdup(from);
165 }
166
167 /* dir_len() skips double /'s e.g. //lib64, so we can't skip just one
168 * character - need to skip all leading /'s */
169 rl = strlen(target);
170 for (i = dirlen + 1; i < rl; ++i)
171 if (target_dir_p[i] != '/')
172 break;
173 ret = asprintf(&realtarget, "%s/%s", realpath_p, &target_dir_p[i]);
174 if (ret < 0) {
175 log_error("Out of memory!");
176 exit(EXIT_FAILURE);
177 }
178
179 /* now calculate the relative path from <from> to <target> and
180 store it in <relative_from>
181 */
182 relative_from[0] = 0;
183 rl = 0;
184
185 /* count the pathname elements of realtarget */
186 for (targetlevel = 0, i = 0; realtarget[i]; i++)
187 if (realtarget[i] == '/')
188 targetlevel++;
189
190 /* count the pathname elements of realfrom */
191 for (fromlevel = 0, i = 0; realfrom[i]; i++)
192 if (realfrom[i] == '/')
193 fromlevel++;
194
195 /* count the pathname elements, which are common for both paths */
196 for (level = 0, i = 0; realtarget[i] && (realtarget[i] == realfrom[i]); i++)
197 if (realtarget[i] == '/')
198 level++;
199
200 /* add "../" to the relative_from path, until the common pathname is
201 reached */
202 for (i = level; i < targetlevel; i++) {
203 if (i != level)
204 relative_from[rl++] = '/';
205 relative_from[rl++] = '.';
206 relative_from[rl++] = '.';
207 }
208
209 /* set l to the next uncommon pathname element in realfrom */
210 for (l = 1, i = 1; i < level; i++)
211 for (l++; realfrom[l] && realfrom[l] != '/'; l++) ;
212 /* skip next '/' */
213 l++;
214
215 /* append the uncommon rest of realfrom to the relative_from path */
216 for (i = level; i <= fromlevel; i++) {
217 if (rl)
218 relative_from[rl++] = '/';
219 while (realfrom[l] && realfrom[l] != '/')
220 relative_from[rl++] = realfrom[l++];
221 l++;
222 }
223
224 relative_from[rl] = 0;
225 return strdup(relative_from);
226 }
227
228 static int ln_r(const char *src, const char *dst)
229 {
230 int ret;
231 _cleanup_free_ const char *points_to = convert_abs_rel(src, dst);
232
233 log_info("ln -s '%s' '%s'", points_to, dst);
234 ret = symlink(points_to, dst);
235
236 if (ret != 0) {
237 log_error("ERROR: ln -s '%s' '%s': %m", points_to, dst);
238 return 1;
239 }
240
241 return 0;
242 }
243
244 /* Perform the O(1) btrfs clone operation, if possible.
245 Upon success, return 0. Otherwise, return -1 and set errno. */
246 static inline int clone_file(int dest_fd, int src_fd)
247 {
248 #undef BTRFS_IOCTL_MAGIC
249 #define BTRFS_IOCTL_MAGIC 0x94
250 #undef BTRFS_IOC_CLONE
251 #define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int)
252 return ioctl(dest_fd, BTRFS_IOC_CLONE, src_fd);
253 }
254
255 static bool use_clone = true;
256
257 static int cp(const char *src, const char *dst)
258 {
259 int pid;
260 int ret = 0;
261
262 if (use_clone) {
263 struct stat sb;
264 _cleanup_close_ int dest_desc = -1, source_desc = -1;
265
266 if (lstat(src, &sb) != 0)
267 goto normal_copy;
268
269 if (S_ISLNK(sb.st_mode))
270 goto normal_copy;
271
272 source_desc = open(src, O_RDONLY | O_CLOEXEC);
273 if (source_desc < 0)
274 goto normal_copy;
275
276 dest_desc =
277 open(dst, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC,
278 (sb.st_mode) & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO));
279
280 if (dest_desc < 0) {
281 goto normal_copy;
282 }
283
284 ret = clone_file(dest_desc, source_desc);
285
286 if (ret == 0) {
287 struct timeval tv[2];
288 if (fchown(dest_desc, sb.st_uid, sb.st_gid) != 0)
289 if(fchown(dest_desc, (uid_t) - 1, sb.st_gid) != 0) {
290 if (geteuid() == 0)
291 log_error("Failed to chown %s: %m", dst);
292 else
293 log_info("Failed to chown %s: %m", dst);
294 }
295
296 tv[0].tv_sec = sb.st_atime;
297 tv[0].tv_usec = 0;
298 tv[1].tv_sec = sb.st_mtime;
299 tv[1].tv_usec = 0;
300 futimes(dest_desc, tv);
301 return ret;
302 }
303 close(dest_desc);
304 dest_desc = -1;
305 /* clone did not work, remove the file */
306 unlink(dst);
307 /* do not try clone again */
308 use_clone = false;
309 }
310
311 normal_copy:
312 pid = fork();
313 if (pid == 0) {
314 if (geteuid() == 0 && no_xattr == false)
315 execlp("cp", "cp", "--reflink=auto", "--sparse=auto", "--preserve=mode,xattr,timestamps", "-fL", src, dst,
316 NULL);
317 else
318 execlp("cp", "cp", "--reflink=auto", "--sparse=auto", "--preserve=mode,timestamps", "-fL", src, dst,
319 NULL);
320 _exit(EXIT_FAILURE);
321 }
322
323 while (waitpid(pid, &ret, 0) < 0) {
324 if (errno != EINTR) {
325 ret = -1;
326 if (geteuid() == 0 && no_xattr == false)
327 log_error("Failed: cp --reflink=auto --sparse=auto --preserve=mode,xattr,timestamps -fL %s %s", src,
328 dst);
329 else
330 log_error("Failed: cp --reflink=auto --sparse=auto --preserve=mode,timestamps -fL %s %s", src,
331 dst);
332 break;
333 }
334 }
335 log_debug("cp ret = %d", ret);
336 return ret;
337 }
338
339 static int library_install(const char *src, const char *lib)
340 {
341 _cleanup_free_ char *p = NULL;
342 _cleanup_free_ char *pdir = NULL, *ppdir = NULL, *clib = NULL;
343 char *q;
344 int r, ret = 0;
345
346 p = strdup(lib);
347
348 r = dracut_install(p, p, false, false, true);
349 if (r != 0)
350 log_error("ERROR: failed to install '%s' for '%s'", p, src);
351 else
352 log_debug("Lib install: '%s'", p);
353 ret += r;
354
355 /* also install lib.so for lib.so.* files */
356 q = strstr(p, ".so.");
357 if (q) {
358 q[3] = '\0';
359
360 /* ignore errors for base lib symlink */
361 if (dracut_install(p, p, false, false, true) == 0)
362 log_debug("Lib install: '%s'", p);
363 }
364
365 /* Also try to install the same library from one directory above.
366 This fixes the case, where only the HWCAP lib would be installed
367 # ldconfig -p|grep -F libc.so
368 libc.so.6 (libc6,64bit, hwcap: 0x0000001000000000, OS ABI: Linux 2.6.32) => /lib64/power6/libc.so.6
369 libc.so.6 (libc6,64bit, hwcap: 0x0000000000000200, OS ABI: Linux 2.6.32) => /lib64/power6x/libc.so.6
370 libc.so.6 (libc6,64bit, OS ABI: Linux 2.6.32) => /lib64/libc.so.6
371 */
372
373 free(p);
374 p = strdup(lib);
375
376 pdir = dirname(p);
377 if (!pdir)
378 return ret;
379
380 pdir = strdup(pdir);
381 ppdir = dirname(pdir);
382 if (!ppdir)
383 return ret;
384
385 ppdir = strdup(ppdir);
386
387 strcpy(p, lib);
388
389 clib = strjoin(ppdir, "/", basename(p), NULL);
390 if (dracut_install(clib, clib, false, false, true) == 0)
391 log_debug("Lib install: '%s'", clib);
392 /* also install lib.so for lib.so.* files */
393 q = strstr(clib, ".so.");
394 if (q) {
395 q[3] = '\0';
396
397 /* ignore errors for base lib symlink */
398 if (dracut_install(clib, clib, false, false, true) == 0)
399 log_debug("Lib install: '%s'", p);
400 }
401
402 return ret;
403 }
404
405 static char *get_real_file(const char *src, bool fullyresolve)
406 {
407 char linktarget[PATH_MAX + 1];
408 ssize_t linksz;
409 _cleanup_free_ char *fullsrcpath;
410 char *abspath = NULL;
411 struct stat sb;
412
413 if (sysrootdirlen) {
414 if (strncmp(src, sysrootdir, sysrootdirlen) == 0)
415 fullsrcpath = strdup(src);
416 else if (asprintf(&fullsrcpath, "%s/%s", (sysrootdirlen ? sysrootdir : ""), (src[0] == '/' ? src+1 : src)) < 0)
417 _exit(EXIT_FAILURE);
418 } else
419 fullsrcpath = strdup(src);
420
421 log_debug("get_real_file('%s')", fullsrcpath);
422
423 if (lstat(fullsrcpath, &sb) < 0)
424 return NULL;
425
426 switch (sb.st_mode & S_IFMT) {
427 case S_IFDIR:
428 case S_IFREG:
429 return strdup(fullsrcpath);
430 case S_IFLNK:
431 break;
432 default:
433 return NULL;
434 }
435
436 linksz = readlink(fullsrcpath, linktarget, sizeof(linktarget));
437 if (linksz < 0)
438 return NULL;
439 linktarget[linksz] = '\0';
440
441 log_debug("get_real_file: readlink('%s') returns '%s'", fullsrcpath, linktarget);
442
443 if (linktarget[0] == '/') {
444 if (asprintf(&abspath, "%s%s", (sysrootdirlen ? sysrootdir : ""), linktarget) < 0)
445 return NULL;
446 } else {
447 _cleanup_free_ char *fullsrcdir = strdup(fullsrcpath);
448
449 if (!fullsrcdir) {
450 log_error("Out of memory!");
451 return NULL;
452 }
453
454 fullsrcdir[dir_len(fullsrcdir)] = '\0';
455
456 if (asprintf(&abspath, "%s/%s", fullsrcdir, linktarget) < 0)
457 return NULL;
458 }
459
460 if (fullyresolve) {
461 struct stat st;
462 if (lstat(abspath, &st) < 0) {
463 if (errno != ENOENT)
464 return NULL;
465 }
466 if (S_ISLNK(st.st_mode))
467 return get_real_file(abspath, fullyresolve);
468 }
469
470 log_debug("get_real_file('%s') => '%s'", src, abspath);
471 return abspath;
472 }
473
474 static int resolve_deps(const char *src)
475 {
476 int ret = 0;
477
478 _cleanup_free_ char *buf = NULL;
479 size_t linesize = LINE_MAX;
480 _cleanup_pclose_ FILE *fptr = NULL;
481 _cleanup_free_ char *cmd = NULL;
482 _cleanup_free_ char *fullsrcpath = NULL;
483
484 fullsrcpath = get_real_file(src, true);
485 log_debug("resolve_deps('%s') -> get_real_file('%s', true) = '%s'", src, src, fullsrcpath);
486 if (!fullsrcpath)
487 return 0;
488
489 buf = malloc(LINE_MAX);
490 if (buf == NULL)
491 return -errno;
492
493 if (strstr(src, ".so") == 0) {
494 _cleanup_close_ int fd = -1;
495 fd = open(fullsrcpath, O_RDONLY | O_CLOEXEC);
496 if (fd < 0)
497 return -errno;
498
499 ret = read(fd, buf, LINE_MAX);
500 if (ret == -1)
501 return -errno;
502
503 buf[LINE_MAX - 1] = '\0';
504 if (buf[0] == '#' && buf[1] == '!') {
505 /* we have a shebang */
506 char *p, *q;
507 for (p = &buf[2]; *p && isspace(*p); p++) ;
508 for (q = p; *q && (!isspace(*q)); q++) ;
509 *q = '\0';
510 log_debug("Script install: '%s'", p);
511 ret = dracut_install(p, p, false, true, false);
512 if (ret != 0)
513 log_error("ERROR: failed to install '%s'", p);
514 return ret;
515 }
516 }
517
518 /* run ldd */
519 ret = asprintf(&cmd, "%s %s 2>&1", ldd, fullsrcpath);
520 if (ret < 0) {
521 log_error("Out of memory!");
522 exit(EXIT_FAILURE);
523 }
524
525 log_debug("%s", cmd);
526
527 ret = 0;
528
529 fptr = popen(cmd, "r");
530
531 while (!feof(fptr)) {
532 char *p;
533
534 if (getline(&buf, &linesize, fptr) <= 0)
535 continue;
536
537 log_debug("ldd: '%s'", buf);
538
539 if (strstr(buf, "you do not have execution permission")) {
540 log_error("%s", buf);
541 ret += 1;
542 break;
543 }
544
545 /* errors from cross-compiler-ldd */
546 if (strstr(buf, "unable to find sysroot") || strstr(buf, "command not found")) {
547 log_error("%s", buf);
548 ret += 1;
549 break;
550 }
551
552 /* musl ldd */
553 if (strstr(buf, "Not a valid dynamic program"))
554 break;
555
556 /* glibc */
557 if (strstr(buf, "cannot execute binary file"))
558 break;
559
560 if (strstr(buf, "not a dynamic executable"))
561 break;
562
563 if (strstr(buf, "loader cannot load itself"))
564 break;
565
566 if (strstr(buf, "not regular file"))
567 break;
568
569 if (strstr(buf, "cannot read header"))
570 break;
571
572 if (strstr(buf, destrootdir))
573 break;
574
575 p = strchr(buf, '/');
576 if (p) {
577 char *q;
578
579 for (q = p; *q && *q != ' ' && *q != '\n'; q++) ;
580 *q = '\0';
581
582 ret += library_install(src, p);
583
584 }
585 }
586
587 return ret;
588 }
589
590 /* Install ".<filename>.hmac" file for FIPS self-checks */
591 static int hmac_install(const char *src, const char *dst, const char *hmacpath)
592 {
593 _cleanup_free_ char *srcpath = strdup(src);
594 _cleanup_free_ char *dstpath = strdup(dst);
595 _cleanup_free_ char *srchmacname = NULL;
596 _cleanup_free_ char *dsthmacname = NULL;
597 int ret;
598
599 if (!(srcpath && dstpath))
600 return -ENOMEM;
601
602 size_t dlen = dir_len(src);
603
604 if (endswith(src, ".hmac"))
605 return 0;
606
607 if (!hmacpath) {
608 hmac_install(src, dst, "/lib/fipscheck");
609 hmac_install(src, dst, "/lib64/fipscheck");
610 hmac_install(src, dst, "/lib/hmaccalc");
611 hmac_install(src, dst, "/lib64/hmaccalc");
612 }
613
614 srcpath[dlen] = '\0';
615 dstpath[dir_len(dst)] = '\0';
616 if (hmacpath) {
617 ret = asprintf(&srchmacname, "%s/%s.hmac", hmacpath, &src[dlen + 1]);
618 if (ret < 0) {
619 log_error("Out of memory!");
620 exit(EXIT_FAILURE);
621 }
622
623 ret = asprintf(&dsthmacname, "%s/%s.hmac", hmacpath, &src[dlen + 1]);
624 if (ret < 0) {
625 log_error("Out of memory!");
626 exit(EXIT_FAILURE);
627 }
628 } else {
629 ret = asprintf(&srchmacname, "%s/.%s.hmac", srcpath, &src[dlen + 1]);
630 if (ret < 0) {
631 log_error("Out of memory!");
632 exit(EXIT_FAILURE);
633 }
634
635 ret = asprintf(&dsthmacname, "%s/.%s.hmac", dstpath, &src[dlen + 1]);
636 if (ret < 0) {
637 log_error("Out of memory!");
638 exit(EXIT_FAILURE);
639 }
640 }
641 log_debug("hmac cp '%s' '%s')", srchmacname, dsthmacname);
642 dracut_install(srchmacname, dsthmacname, false, false, true);
643 return 0;
644 }
645
646 void mark_hostonly(const char *path)
647 {
648 _cleanup_free_ char *fulldstpath = NULL;
649 _cleanup_fclose_ FILE *f = NULL;
650 int ret;
651
652 ret = asprintf(&fulldstpath, "%s/lib/dracut/hostonly-files", destrootdir);
653 if (ret < 0) {
654 log_error("Out of memory!");
655 exit(EXIT_FAILURE);
656 }
657
658 f = fopen(fulldstpath, "a");
659
660 if (f == NULL) {
661 log_error("Could not open '%s' for writing.", fulldstpath);
662 return;
663 }
664
665 fprintf(f, "%s\n", path);
666 }
667
668 void dracut_log_cp(const char *path)
669 {
670 int ret;
671 ret = fprintf(logfile_f, "%s\n", path);
672 if (ret < 0)
673 log_error("Could not append '%s' to logfile '%s': %m", path, logfile);
674 }
675
676 static bool check_hashmap(Hashmap *hm, const char *item)
677 {
678 char *existing;
679 existing = hashmap_get(hm, item);
680 if (existing) {
681 if (strcmp(existing, item) == 0) {
682 return true;
683 }
684 }
685 return false;
686 }
687
688 static int dracut_mkdir(const char *src) {
689 _cleanup_free_ char *parent = NULL;
690 struct stat sb;
691
692 parent = strdup(src);
693 if (!parent)
694 return 1;
695
696 parent[dir_len(parent)] = '\0';
697
698 if (stat(parent, &sb) == 0) {
699 if (!S_ISDIR(sb.st_mode)) {
700 log_error("%s exists but is not a directory!", parent);
701 return 1;
702 }
703
704 return mkdir(src, 0755);
705 }
706
707 if (errno != ENOENT) {
708 log_error("ERROR: stat '%s': %m", src);
709 return 1;
710 }
711
712 return dracut_mkdir(parent);
713 }
714
715 static int dracut_install(const char *orig_src, const char *orig_dst, bool isdir, bool resolvedeps, bool hashdst)
716 {
717 struct stat sb, db;
718 _cleanup_free_ char *fullsrcpath = NULL;
719 _cleanup_free_ char *fulldstpath = NULL;
720 _cleanup_free_ char *fulldstdir = NULL;
721 int ret;
722 bool src_islink = false;
723 bool src_isdir = false;
724 mode_t src_mode = 0;
725 bool dst_exists = true;
726 char *i = NULL;
727 _cleanup_free_ char *src;
728 _cleanup_free_ char *dst;
729
730 if (sysrootdirlen) {
731 if (strncmp(orig_src, sysrootdir, sysrootdirlen) == 0) {
732 src = strdup(orig_src + sysrootdirlen);
733 fullsrcpath = strdup(orig_src);
734 } else {
735 src = strdup(orig_src);
736 if (asprintf(&fullsrcpath, "%s%s", sysrootdir, src) < 0)
737 _exit(EXIT_FAILURE);
738 }
739 if (strncmp(orig_dst, sysrootdir, sysrootdirlen) == 0)
740 dst = strdup(orig_dst + sysrootdirlen);
741 else
742 dst = strdup(orig_dst);
743 } else {
744 src = strdup(orig_src);
745 fullsrcpath = strdup(src);
746 dst = strdup(orig_dst);
747 }
748
749 log_debug("dracut_install('%s', '%s', %d, %d, %d)", src, dst, isdir, resolvedeps, hashdst);
750
751 if (check_hashmap(items_failed, src)) {
752 log_debug("hash hit items_failed for '%s'", src);
753 return 1;
754 }
755
756 if (hashdst && check_hashmap(items, dst)) {
757 log_debug("hash hit items for '%s'", dst);
758 return 0;
759 }
760
761 if (lstat(fullsrcpath, &sb) < 0) {
762 if (!isdir) {
763 i = strdup(src);
764 hashmap_put(items_failed, i, i);
765 /* src does not exist */
766 return 1;
767 }
768 } else {
769 src_islink = S_ISLNK(sb.st_mode);
770 src_isdir = S_ISDIR(sb.st_mode);
771 src_mode = sb.st_mode;
772 }
773
774 ret = asprintf(&fulldstpath, "%s/%s", destrootdir, (dst[0]=='/' ? (dst+1) : dst));
775 if (ret < 0) {
776 log_error("Out of memory!");
777 exit(EXIT_FAILURE);
778 }
779
780 ret = stat(fulldstpath, &sb);
781
782 if (ret != 0) {
783 dst_exists = false;
784 if (errno != ENOENT) {
785 log_error("ERROR: stat '%s': %m", fulldstpath);
786 return 1;
787 }
788 }
789
790 if (ret == 0) {
791 if (resolvedeps && S_ISREG(sb.st_mode) && (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
792 log_debug("'%s' already exists, but checking for any deps", fulldstpath);
793 ret = resolve_deps(fullsrcpath + sysrootdirlen);
794 } else
795 log_debug("'%s' already exists", fulldstpath);
796
797 /* dst does already exist */
798 return ret;
799 }
800
801 /* check destination directory */
802 fulldstdir = strdup(fulldstpath);
803 if (!fulldstdir) {
804 log_error("Out of memory!");
805 return 1;
806 }
807 fulldstdir[dir_len(fulldstdir)] = '\0';
808
809 ret = stat(fulldstdir, &db);
810
811 if (ret < 0) {
812 _cleanup_free_ char *dname = NULL;
813
814 if (errno != ENOENT) {
815 log_error("ERROR: stat '%s': %m", fulldstdir);
816 return 1;
817 }
818 /* create destination directory */
819 log_debug("dest dir '%s' does not exist", fulldstdir);
820 dname = strdup(dst);
821 if (!dname)
822 return 1;
823
824 dname[dir_len(dname)] = '\0';
825 ret = dracut_install(dname, dname, true, false, true);
826
827 if (ret != 0) {
828 log_error("ERROR: failed to create directory '%s'", fulldstdir);
829 return 1;
830 }
831 }
832
833 if (src_isdir) {
834 if (dst_exists) {
835 if (S_ISDIR(sb.st_mode)) {
836 log_debug("dest dir '%s' already exists", fulldstpath);
837 return 0;
838 }
839 log_error("dest dir '%s' already exists but is not a directory", fulldstpath);
840 return 1;
841 }
842
843 log_info("mkdir '%s'", fulldstpath);
844 ret = dracut_mkdir(fulldstpath);
845 if (ret == 0) {
846 i = strdup(dst);
847 if (!i)
848 return -ENOMEM;
849
850 hashmap_put(items, i, i);
851 }
852 return ret;
853 }
854
855 /* ready to install src */
856
857 if (src_islink) {
858 _cleanup_free_ char *abspath = NULL;
859
860 abspath = get_real_file(src, false);
861
862 if (abspath == NULL)
863 return 1;
864
865 if (dracut_install(abspath, abspath, false, resolvedeps, hashdst)) {
866 log_debug("'%s' install error", abspath);
867 return 1;
868 }
869
870 if (lstat(abspath, &sb) != 0) {
871 log_debug("lstat '%s': %m", abspath);
872 return 1;
873 }
874
875 if (lstat(fulldstpath, &sb) != 0) {
876 _cleanup_free_ char *absdestpath = NULL;
877
878 ret = asprintf(&absdestpath, "%s/%s", destrootdir, (abspath[0]=='/' ? (abspath+1) : abspath) + sysrootdirlen);
879 if (ret < 0) {
880 log_error("Out of memory!");
881 exit(EXIT_FAILURE);
882 }
883
884 ln_r(absdestpath, fulldstpath);
885 }
886
887 if (arg_hmac) {
888 /* copy .hmac files also */
889 hmac_install(src, dst, NULL);
890 }
891
892 return 0;
893 }
894
895 if (src_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
896 if (resolvedeps)
897 ret += resolve_deps(fullsrcpath + sysrootdirlen);
898 if (arg_hmac) {
899 /* copy .hmac files also */
900 hmac_install(src, dst, NULL);
901 }
902 }
903
904 log_debug("dracut_install ret = %d", ret);
905
906 if (arg_hostonly && !arg_module)
907 mark_hostonly(dst);
908
909 if (isdir) {
910 log_info("mkdir '%s'", fulldstpath);
911 ret += dracut_mkdir(fulldstpath);
912 } else {
913 log_info("cp '%s' '%s'", fullsrcpath, fulldstpath);
914 ret += cp(fullsrcpath, fulldstpath);
915 }
916
917 if (ret == 0) {
918 i = strdup(dst);
919 if (!i)
920 return -ENOMEM;
921
922 hashmap_put(items, i, i);
923
924 if (logfile_f)
925 dracut_log_cp(src);
926 }
927
928 log_debug("dracut_install ret = %d", ret);
929
930 return ret;
931 }
932
933 static void item_free(char *i)
934 {
935 assert(i);
936 free(i);
937 }
938
939 static void usage(int status)
940 {
941 /* */
942 printf("Usage: %s -D DESTROOTDIR [-r SYSROOTDIR] [OPTION]... -a SOURCE...\n"
943 "or: %s -D DESTROOTDIR [-r SYSROOTDIR] [OPTION]... SOURCE DEST\n"
944 "or: %s -D DESTROOTDIR [-r SYSROOTDIR] [OPTION]... -m KERNELMODULE [KERNELMODULE …]\n"
945 "\n"
946 "Install SOURCE (from rootfs or SYSROOTDIR) to DEST in DESTROOTDIR with all needed dependencies.\n"
947 "\n"
948 " KERNELMODULE can have the format:\n"
949 " <absolute path> with a leading /\n"
950 " =<kernel subdir>[/<kernel subdir>…] like '=drivers/hid'\n"
951 " <module name>\n"
952 "\n"
953 " -D --destrootdir Install all files to DESTROOTDIR as the root\n"
954 " -r --sysrootdir Install all files from SYSROOTDIR\n"
955 " -a --all Install all SOURCE arguments to DESTROOTDIR\n"
956 " -o --optional If SOURCE does not exist, do not fail\n"
957 " -d --dir SOURCE is a directory\n"
958 " -l --ldd Also install shebang executables and libraries\n"
959 " -L --logdir <DIR> Log files, which were installed from the host to <DIR>\n"
960 " -R --resolvelazy Only install shebang executables and libraries\n"
961 " for all SOURCE files\n"
962 " -H --hostonly Mark all SOURCE files as hostonly\n\n"
963 " -f --fips Also install all '.SOURCE.hmac' files\n"
964 "\n"
965 " --module,-m Install kernel modules, instead of files\n"
966 " --kerneldir Specify the kernel module directory\n"
967 " --firmwaredirs Specify the firmware directory search path with : separation\n"
968 " --silent Don't display error messages for kernel module install\n"
969 " --modalias Only generate module list from /sys/devices modalias list\n"
970 " -o --optional If kernel module does not exist, do not fail\n"
971 " -p --mod-filter-path Filter kernel modules by path regexp\n"
972 " -P --mod-filter-nopath Exclude kernel modules by path regexp\n"
973 " -s --mod-filter-symbol Filter kernel modules by symbol regexp\n"
974 " -S --mod-filter-nosymbol Exclude kernel modules by symbol regexp\n"
975 " -N --mod-filter-noname Exclude kernel modules by name regexp\n"
976 "\n"
977 " -v --verbose Show more output\n"
978 " --debug Show debug output\n"
979 " --version Show package version\n"
980 " -h --help Show this help\n"
981 "\n",
982 program_invocation_short_name, program_invocation_short_name,
983 program_invocation_short_name);
984 exit(status);
985 }
986
987 static int parse_argv(int argc, char *argv[])
988 {
989 int c;
990
991 enum {
992 ARG_VERSION = 0x100,
993 ARG_SILENT,
994 ARG_MODALIAS,
995 ARG_KERNELDIR,
996 ARG_FIRMWAREDIRS,
997 ARG_DEBUG
998 };
999
1000 static struct option const options[] = {
1001 {"help", no_argument, NULL, 'h'},
1002 {"version", no_argument, NULL, ARG_VERSION},
1003 {"dir", no_argument, NULL, 'd'},
1004 {"debug", no_argument, NULL, ARG_DEBUG},
1005 {"verbose", no_argument, NULL, 'v'},
1006 {"ldd", no_argument, NULL, 'l'},
1007 {"resolvelazy", no_argument, NULL, 'R'},
1008 {"optional", no_argument, NULL, 'o'},
1009 {"hostonly", no_argument, NULL, 'H'},
1010 {"all", no_argument, NULL, 'a'},
1011 {"module", no_argument, NULL, 'm'},
1012 {"fips", no_argument, NULL, 'f'},
1013 {"destrootdir", required_argument, NULL, 'D'},
1014 {"sysrootdir", required_argument, NULL, 'r'},
1015 {"logdir", required_argument, NULL, 'L'},
1016 {"mod-filter-path", required_argument, NULL, 'p'},
1017 {"mod-filter-nopath", required_argument, NULL, 'P'},
1018 {"mod-filter-symbol", required_argument, NULL, 's'},
1019 {"mod-filter-nosymbol", required_argument, NULL, 'S'},
1020 {"mod-filter-noname", required_argument, NULL, 'N'},
1021 {"modalias", no_argument, NULL, ARG_MODALIAS},
1022 {"silent", no_argument, NULL, ARG_SILENT},
1023 {"kerneldir", required_argument, NULL, ARG_KERNELDIR},
1024 {"firmwaredirs", required_argument, NULL, ARG_FIRMWAREDIRS},
1025 {NULL, 0, NULL, 0}
1026 };
1027
1028 while ((c = getopt_long(argc, argv, "madfhlL:oD:Hr:Rp:P:s:S:N:v", options, NULL)) != -1) {
1029 switch (c) {
1030 case ARG_VERSION:
1031 puts(PROGRAM_VERSION_STRING);
1032 return 0;
1033 case 'd':
1034 arg_createdir = true;
1035 break;
1036 case ARG_DEBUG:
1037 arg_loglevel = LOG_DEBUG;
1038 break;
1039 case ARG_SILENT:
1040 arg_silent = true;
1041 break;
1042 case ARG_MODALIAS:
1043 arg_modalias = true;
1044 return 1;
1045 break;
1046 case 'v':
1047 arg_loglevel = LOG_INFO;
1048 break;
1049 case 'o':
1050 arg_optional = true;
1051 break;
1052 case 'l':
1053 arg_resolvedeps = true;
1054 break;
1055 case 'R':
1056 arg_resolvelazy = true;
1057 break;
1058 case 'a':
1059 arg_all = true;
1060 break;
1061 case 'm':
1062 arg_module = true;
1063 break;
1064 case 'D':
1065 destrootdir = strdup(optarg);
1066 break;
1067 case 'r':
1068 sysrootdir = strdup(optarg);
1069 sysrootdirlen = strlen(sysrootdir);
1070 break;
1071 case 'p':
1072 if (regcomp(&mod_filter_path, optarg, REG_NOSUB|REG_EXTENDED) != 0) {
1073 log_error("Module path filter %s is not a regular expression", optarg);
1074 exit(EXIT_FAILURE);
1075 }
1076 arg_mod_filter_path = true;
1077 break;
1078 case 'P':
1079 if (regcomp(&mod_filter_nopath, optarg, REG_NOSUB|REG_EXTENDED) != 0) {
1080 log_error("Module path filter %s is not a regular expression", optarg);
1081 exit(EXIT_FAILURE);
1082 }
1083 arg_mod_filter_nopath = true;
1084 break;
1085 case 's':
1086 if (regcomp(&mod_filter_symbol, optarg, REG_NOSUB|REG_EXTENDED) != 0) {
1087 log_error("Module symbol filter %s is not a regular expression", optarg);
1088 exit(EXIT_FAILURE);
1089 }
1090 arg_mod_filter_symbol = true;
1091 break;
1092 case 'S':
1093 if (regcomp(&mod_filter_nosymbol, optarg, REG_NOSUB|REG_EXTENDED) != 0) {
1094 log_error("Module symbol filter %s is not a regular expression", optarg);
1095 exit(EXIT_FAILURE);
1096 }
1097 arg_mod_filter_nosymbol = true;
1098 break;
1099 case 'N':
1100 if (regcomp(&mod_filter_noname, optarg, REG_NOSUB|REG_EXTENDED) != 0) {
1101 log_error("Module symbol filter %s is not a regular expression", optarg);
1102 exit(EXIT_FAILURE);
1103 }
1104 arg_mod_filter_noname = true;
1105 break;
1106 case 'L':
1107 logdir = strdup(optarg);
1108 break;
1109 case ARG_KERNELDIR:
1110 kerneldir = strdup(optarg);
1111 break;
1112 case ARG_FIRMWAREDIRS:
1113 firmwaredirs = strv_split(optarg, ":");
1114 break;
1115 case 'f':
1116 arg_hmac = true;
1117 break;
1118 case 'H':
1119 arg_hostonly = true;
1120 break;
1121 case 'h':
1122 usage(EXIT_SUCCESS);
1123 break;
1124 default:
1125 usage(EXIT_FAILURE);
1126 }
1127 }
1128
1129 if (!kerneldir) {
1130 struct utsname buf;
1131 uname(&buf);
1132 kerneldir = strdup(buf.version);
1133 }
1134
1135 if (arg_modalias) {
1136 return 1;
1137 }
1138
1139 if (arg_module) {
1140 if (!firmwaredirs) {
1141 char *path = NULL;
1142
1143 path = getenv("DRACUT_FIRMWARE_PATH");
1144
1145 if (path == NULL) {
1146 log_error("Environment variable DRACUT_FIRMWARE_PATH is not set");
1147 exit(EXIT_FAILURE);
1148 }
1149
1150 log_debug("DRACUT_FIRMWARE_PATH=%s", path);
1151
1152 firmwaredirs = strv_split(path, ":");
1153 }
1154 }
1155
1156 if (!optind || optind == argc) {
1157 log_error("No SOURCE argument given");
1158 usage(EXIT_FAILURE);
1159 }
1160
1161 return 1;
1162 }
1163
1164 static int resolve_lazy(int argc, char **argv)
1165 {
1166 int i;
1167 size_t destrootdirlen = strlen(destrootdir);
1168 int ret = 0;
1169 char *item;
1170 for (i = 0; i < argc; i++) {
1171 const char *src = argv[i];
1172 char *p = argv[i];
1173 char *existing;
1174
1175 log_debug("resolve_deps('%s')", src);
1176
1177 if (strstr(src, destrootdir)) {
1178 p = &argv[i][destrootdirlen];
1179 }
1180
1181 existing = hashmap_get(items, p);
1182 if (existing) {
1183 if (strcmp(existing, p) == 0)
1184 continue;
1185 }
1186
1187 item = strdup(p);
1188 hashmap_put(items, item, item);
1189
1190 ret += resolve_deps(src);
1191 }
1192 return ret;
1193 }
1194
1195 static char **find_binary(const char *src)
1196 {
1197 char **ret = NULL;
1198 char **q;
1199 char *fullsrcpath;
1200 char *newsrc = NULL;
1201
1202 STRV_FOREACH(q, pathdirs) {
1203 struct stat sb;
1204 int r;
1205
1206 r = asprintf(&newsrc, "%s/%s", *q, src);
1207 if (r < 0) {
1208 log_error("Out of memory!");
1209 exit(EXIT_FAILURE);
1210 }
1211
1212 fullsrcpath = get_real_file(newsrc, false);
1213
1214 if (!fullsrcpath) {
1215 log_debug("get_real_file(%s) not found", newsrc);
1216 free(newsrc);
1217 newsrc = NULL;
1218 continue;
1219 }
1220
1221 if (lstat(fullsrcpath, &sb) != 0) {
1222 log_debug("stat(%s) != 0", fullsrcpath);
1223 free(newsrc);
1224 newsrc = NULL;
1225 free(fullsrcpath);
1226 fullsrcpath = NULL;
1227 continue;
1228 }
1229
1230 strv_push(&ret, newsrc);
1231
1232 free(fullsrcpath);
1233 fullsrcpath = NULL;
1234 };
1235
1236 if (ret) {
1237 STRV_FOREACH(q, ret) {
1238 log_debug("find_binary(%s) == %s", src, *q);
1239 }
1240 }
1241
1242 return ret;
1243 }
1244
1245 static int install_one(const char *src, const char *dst)
1246 {
1247 int r = EXIT_SUCCESS;
1248 int ret = 0;
1249
1250 if (strchr(src, '/') == NULL) {
1251 char **p = find_binary(src);
1252 if (p) {
1253 char **q = NULL;
1254 STRV_FOREACH(q, p) {
1255 char *newsrc = *q;
1256 log_debug("dracut_install '%s' '%s'", newsrc, dst);
1257 ret = dracut_install(newsrc, dst, arg_createdir, arg_resolvedeps, true);
1258 if (ret == 0) {
1259 log_debug("dracut_install '%s' '%s' OK", newsrc, dst);
1260 }
1261 }
1262 strv_free(p);
1263 } else {
1264 ret = -1;
1265 }
1266 } else {
1267 ret = dracut_install(src, dst, arg_createdir, arg_resolvedeps, true);
1268 }
1269
1270 if ((ret != 0) && (!arg_optional)) {
1271 log_error("ERROR: installing '%s' to '%s'", src, dst);
1272 r = EXIT_FAILURE;
1273 }
1274
1275 return r;
1276 }
1277
1278 static int install_all(int argc, char **argv)
1279 {
1280 int r = EXIT_SUCCESS;
1281 int i;
1282 for (i = 0; i < argc; i++) {
1283 int ret = 0;
1284 log_debug("Handle '%s'", argv[i]);
1285
1286 if (strchr(argv[i], '/') == NULL) {
1287 char **p = find_binary(argv[i]);
1288 if (p) {
1289 char **q = NULL;
1290 STRV_FOREACH(q, p) {
1291 char *newsrc = *q;
1292 log_debug("dracut_install '%s'", newsrc);
1293 ret = dracut_install(newsrc, newsrc, arg_createdir, arg_resolvedeps, true);
1294 if (ret == 0) {
1295 log_debug("dracut_install '%s' OK", newsrc);
1296 }
1297 }
1298 strv_free(p);
1299 } else {
1300 ret = -1;
1301 }
1302
1303 } else {
1304 _cleanup_free_ char *dest = strdup(argv[i]);
1305 ret = dracut_install(argv[i], dest, arg_createdir, arg_resolvedeps, true);
1306 }
1307
1308 if ((ret != 0) && (!arg_optional)) {
1309 log_error("ERROR: installing '%s'", argv[i]);
1310 r = EXIT_FAILURE;
1311 }
1312 }
1313 return r;
1314 }
1315
1316 static int install_firmware(struct kmod_module *mod)
1317 {
1318 struct kmod_list *l;
1319 _cleanup_kmod_module_info_free_list_ struct kmod_list *list = NULL;
1320 int ret;
1321
1322 char **q;
1323
1324 ret = kmod_module_get_info(mod, &list);
1325 if (ret < 0) {
1326 log_error("could not get modinfo from '%s': %s\n",
1327 kmod_module_get_name(mod), strerror(-ret));
1328 return ret;
1329 }
1330 kmod_list_foreach(l, list) {
1331 const char *key = kmod_module_info_get_key(l);
1332 const char *value = NULL;
1333
1334 if (!streq("firmware", key))
1335 continue;
1336
1337 value = kmod_module_info_get_value(l);
1338 log_debug("Firmware %s", value);
1339 ret = -1;
1340 STRV_FOREACH(q, firmwaredirs) {
1341 _cleanup_free_ char *fwpath = NULL;
1342 _cleanup_free_ char *fwpath_xz = NULL;
1343 const char *fw;
1344 struct stat sb;
1345 int r;
1346
1347 r = asprintf(&fwpath, "%s/%s", *q, value);
1348 if (r < 0) {
1349 log_error("Out of memory!");
1350 exit(EXIT_FAILURE);
1351 }
1352
1353 fw = fwpath;
1354 if (stat(fwpath, &sb) != 0) {
1355 r = asprintf(&fwpath_xz, "%s.xz", fwpath);
1356 if (r < 0) {
1357 log_error("Out of memory!");
1358 exit(EXIT_FAILURE);
1359 }
1360 if (stat(fwpath_xz, &sb) != 0) {
1361 log_debug("stat(%s) != 0", fwpath);
1362 continue;
1363 }
1364 fw = fwpath_xz;
1365 }
1366
1367 ret = dracut_install(fw, fw, false, false, true);
1368 if (ret == 0)
1369 log_debug("dracut_install '%s' OK", fwpath);
1370 }
1371
1372 if (ret != 0) {
1373 log_info("Possible missing firmware %s for kernel module %s", value, kmod_module_get_name(mod));
1374 }
1375 }
1376 return 0;
1377 }
1378
1379 static bool check_module_symbols(struct kmod_module *mod)
1380 {
1381 struct kmod_list *itr;
1382 _cleanup_kmod_module_dependency_symbols_free_list_ struct kmod_list *deplist = NULL;
1383
1384 if (!arg_mod_filter_symbol && !arg_mod_filter_nosymbol)
1385 return true;
1386
1387 if (kmod_module_get_dependency_symbols(mod, &deplist) < 0) {
1388 log_debug("kmod_module_get_dependency_symbols failed");
1389 if (arg_mod_filter_symbol)
1390 return false;
1391 return true;
1392 }
1393
1394 if (arg_mod_filter_nosymbol) {
1395 kmod_list_foreach(itr, deplist) {
1396 const char *symbol = kmod_module_symbol_get_symbol(itr);
1397 // log_debug("Checking symbol %s", symbol);
1398 if (regexec(&mod_filter_nosymbol, symbol, 0, NULL, 0) == 0) {
1399 log_debug("Module %s: symbol %s matched exclusion filter", kmod_module_get_name(mod), symbol);
1400 return false;
1401 }
1402 }
1403 }
1404
1405 if (arg_mod_filter_symbol) {
1406 kmod_list_foreach(itr, deplist) {
1407 const char *symbol = kmod_module_dependency_symbol_get_symbol(itr);
1408 // log_debug("Checking symbol %s", symbol);
1409 if (regexec(&mod_filter_symbol, symbol, 0, NULL, 0) == 0) {
1410 log_debug("Module %s: symbol %s matched inclusion filter", kmod_module_get_name(mod), symbol);
1411 return true;
1412 }
1413 }
1414 return false;
1415 }
1416
1417 return true;
1418 }
1419
1420 static bool check_module_path(const char *path)
1421 {
1422 if (arg_mod_filter_nopath && (regexec(&mod_filter_nopath, path, 0, NULL, 0) == 0)) {
1423 log_debug("Path %s matched exclusion filter", path);
1424 return false;
1425 }
1426
1427 if (arg_mod_filter_path && (regexec(&mod_filter_path, path, 0, NULL, 0) != 0)) {
1428 log_debug("Path %s matched inclusion filter", path);
1429 return false;
1430 }
1431 return true;
1432 }
1433
1434 static int install_dependent_modules(struct kmod_list *modlist)
1435 {
1436 struct kmod_list *itr;
1437 const char *path = NULL;
1438 const char *name = NULL;
1439 int ret = 0;
1440
1441 kmod_list_foreach(itr, modlist) {
1442 _cleanup_kmod_module_unref_ struct kmod_module *mod = NULL;
1443 mod = kmod_module_get_module(itr);
1444 path = kmod_module_get_path(mod);
1445
1446 if (path == NULL)
1447 continue;
1448
1449 if (check_hashmap(items_failed, path))
1450 return -1;
1451
1452 if (check_hashmap(items, path)) {
1453 continue;
1454 }
1455
1456 name = kmod_module_get_name(mod);
1457
1458 if (arg_mod_filter_noname && (regexec(&mod_filter_noname, name, 0, NULL, 0) == 0)) {
1459 continue;
1460 }
1461
1462 ret = dracut_install(path, &path[kerneldirlen], false, false, true);
1463 if (ret == 0) {
1464 _cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;
1465 _cleanup_kmod_module_unref_list_ struct kmod_list *modpre = NULL;
1466 _cleanup_kmod_module_unref_list_ struct kmod_list *modpost = NULL;
1467 log_debug("dracut_install '%s' '%s' OK", path, &path[kerneldirlen]);
1468 install_firmware(mod);
1469 modlist = kmod_module_get_dependencies(mod);
1470 ret = install_dependent_modules(modlist);
1471 if (ret == 0) {
1472 ret = kmod_module_get_softdeps(mod, &modpre, &modpost);
1473 if (ret == 0)
1474 ret = install_dependent_modules(modpre);
1475 }
1476 } else {
1477 log_error("dracut_install '%s' '%s' ERROR", path, &path[kerneldirlen]);
1478 }
1479 }
1480
1481 return ret;
1482 }
1483
1484 static int install_module(struct kmod_module *mod)
1485 {
1486 int ret = 0;
1487 _cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;
1488 _cleanup_kmod_module_unref_list_ struct kmod_list *modpre = NULL;
1489 _cleanup_kmod_module_unref_list_ struct kmod_list *modpost = NULL;
1490 const char *path = NULL;
1491 const char *name = NULL;
1492
1493 name = kmod_module_get_name(mod);
1494 if (arg_mod_filter_noname && (regexec(&mod_filter_noname, name, 0, NULL, 0) == 0)) {
1495 log_debug("dracut_install '%s' is excluded", name);
1496 return 0;
1497 }
1498
1499 if (arg_hostonly && !check_hashmap(modules_loaded, name)) {
1500 log_debug("dracut_install '%s' not hostonly", name);
1501 return 0;
1502 }
1503
1504 path = kmod_module_get_path(mod);
1505 if (!path)
1506 return -ENOENT;
1507
1508 if (check_hashmap(items_failed, path))
1509 return -1;
1510
1511 if (check_hashmap(items, path))
1512 return 0;
1513
1514 if (!check_module_path(path) || !check_module_symbols(mod)) {
1515 log_debug("No symbol or path match for '%s'", path);
1516 return 1;
1517 }
1518
1519 log_debug("dracut_install '%s' '%s'", path, &path[kerneldirlen]);
1520
1521 ret = dracut_install(path, &path[kerneldirlen], false, false, true);
1522 if (ret == 0) {
1523 log_debug("dracut_install '%s' OK", kmod_module_get_name(mod));
1524 } else if (!arg_optional) {
1525 if (!arg_silent)
1526 log_error("dracut_install '%s' ERROR", kmod_module_get_name(mod));
1527 return ret;
1528 }
1529 install_firmware(mod);
1530
1531 modlist = kmod_module_get_dependencies(mod);
1532 ret = install_dependent_modules(modlist);
1533
1534 if (ret == 0) {
1535 ret = kmod_module_get_softdeps(mod, &modpre, &modpost);
1536 if (ret == 0)
1537 ret = install_dependent_modules(modpre);
1538 }
1539
1540 return ret;
1541 }
1542
1543 static int modalias_list(struct kmod_ctx *ctx)
1544 {
1545 int err;
1546 struct kmod_list *loaded_list = NULL;
1547 struct kmod_list *itr, *l;
1548 _cleanup_fts_close_ FTS *fts = NULL;
1549
1550 {
1551 char *paths[] = { "/sys/devices", NULL };
1552 fts = fts_open(paths, FTS_NOCHDIR|FTS_NOSTAT, NULL);
1553 }
1554 for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
1555 _cleanup_fclose_ FILE *f = NULL;
1556 _cleanup_kmod_module_unref_list_ struct kmod_list *list = NULL;
1557 struct kmod_list *l;
1558
1559 int err;
1560
1561 char alias[2048];
1562 size_t len;
1563
1564 if (strncmp("modalias", ftsent->fts_name, 8) != 0)
1565 continue;
1566 if (!(f = fopen(ftsent->fts_accpath, "r")))
1567 continue;
1568
1569 if(!fgets(alias, sizeof(alias), f))
1570 continue;
1571
1572 len = strlen(alias);
1573
1574 if (len == 0)
1575 continue;
1576
1577 if (alias[len-1] == '\n')
1578 alias[len-1] = 0;
1579
1580 err = kmod_module_new_from_lookup(ctx, alias, &list);
1581 if (err < 0)
1582 continue;
1583
1584 kmod_list_foreach(l, list) {
1585 struct kmod_module *mod = kmod_module_get_module(l);
1586 char *name = strdup(kmod_module_get_name(mod));
1587 kmod_module_unref(mod);
1588 hashmap_put(modules_loaded, name, name);
1589 }
1590 }
1591
1592 err = kmod_module_new_from_loaded(ctx, &loaded_list);
1593 if (err < 0) {
1594 errno = err;
1595 log_error("Could not get list of loaded modules: %m. Switching to non-hostonly mode.");
1596 arg_hostonly = false;
1597 } else {
1598 kmod_list_foreach(itr, loaded_list) {
1599 _cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;
1600
1601 struct kmod_module *mod = kmod_module_get_module(itr);
1602 char *name = strdup(kmod_module_get_name(mod));
1603 hashmap_put(modules_loaded, name, name);
1604 kmod_module_unref(mod);
1605
1606 /* also put the modules from the new kernel in the hashmap,
1607 * which resolve the name as an alias, in case a kernel module is
1608 * renamed.
1609 */
1610 err = kmod_module_new_from_lookup(ctx, name, &modlist);
1611 if (err < 0)
1612 continue;
1613 if (!modlist)
1614 continue;
1615 kmod_list_foreach(l, modlist) {
1616 mod = kmod_module_get_module(l);
1617 char *name = strdup(kmod_module_get_name(mod));
1618 hashmap_put(modules_loaded, name, name);
1619 kmod_module_unref(mod);
1620 }
1621 }
1622 kmod_module_unref_list(loaded_list);
1623 }
1624 return 0;
1625 }
1626
1627 static int install_modules(int argc, char **argv)
1628 {
1629 _cleanup_kmod_unref_ struct kmod_ctx *ctx = NULL;
1630 struct kmod_list *itr;
1631
1632 struct kmod_module *mod = NULL, *mod_o = NULL;
1633
1634 const char *abskpath = NULL;
1635 char *p;
1636 int i;
1637 int modinst = 0;
1638
1639 ctx = kmod_new(kerneldir, NULL);
1640 abskpath = kmod_get_dirname(ctx);
1641
1642 p = strstr(abskpath, "/lib/modules/");
1643 if (p != NULL)
1644 kerneldirlen = p - abskpath;
1645
1646 if (arg_hostonly) {
1647 char *modalias_file;
1648 modalias_file = getenv("DRACUT_KERNEL_MODALIASES");
1649
1650 if (modalias_file == NULL) {
1651 modalias_list(ctx);
1652 } else {
1653 _cleanup_fclose_ FILE *f = NULL;
1654 if ((f = fopen(modalias_file, "r"))) {
1655 char name[2048];
1656
1657 while (!feof(f)) {
1658 size_t len;
1659 char *dupname = NULL;
1660
1661 if(!(fgets(name, sizeof(name), f)))
1662 continue;
1663 len = strlen(name);
1664
1665 if (len == 0)
1666 continue;
1667
1668 if (name[len-1] == '\n')
1669 name[len-1] = 0;
1670
1671 log_debug("Adding module '%s' to hostonly module list", name);
1672 dupname = strdup(name);
1673 hashmap_put(modules_loaded, dupname, dupname);
1674 }
1675 }
1676 }
1677
1678 }
1679
1680 for (i = 0; i < argc; i++) {
1681 int r = 0;
1682 int ret = -1;
1683 log_debug("Handle module '%s'", argv[i]);
1684
1685 if (argv[i][0] == '/') {
1686 _cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;
1687 _cleanup_free_ const char *modname = NULL;
1688
1689 r = kmod_module_new_from_path(ctx, argv[i], &mod_o);
1690 if (r < 0) {
1691 log_debug("Failed to lookup modules path '%s': %m", argv[i]);
1692 if (!arg_optional)
1693 return -ENOENT;
1694 continue;
1695 }
1696 /* Check, if we have to load another module with that name instead */
1697 modname = strdup(kmod_module_get_name(mod_o));
1698
1699 if (!modname) {
1700 if (!arg_optional) {
1701 if (!arg_silent)
1702 log_error("Failed to get name for module '%s'", argv[i]);
1703 return -ENOENT;
1704 }
1705 log_info("Failed to get name for module '%s'", argv[i]);
1706 continue;
1707 }
1708
1709 r = kmod_module_new_from_lookup(ctx, modname, &modlist);
1710 kmod_module_unref(mod_o);
1711 mod_o = NULL;
1712
1713 if (r < 0) {
1714 if (!arg_optional) {
1715 if (!arg_silent)
1716 log_error("3 Failed to lookup alias '%s': %d", modname, r);
1717 return -ENOENT;
1718 }
1719 log_info("3 Failed to lookup alias '%s': %d", modname, r);
1720 continue;
1721 }
1722 if (!modlist) {
1723 if (!arg_optional) {
1724 if (!arg_silent)
1725 log_error("Failed to find module '%s' %s", modname, argv[i]);
1726 return -ENOENT;
1727 }
1728 log_info("Failed to find module '%s' %s", modname, argv[i]);
1729 continue;
1730 }
1731 kmod_list_foreach(itr, modlist) {
1732 mod = kmod_module_get_module(itr);
1733 r = install_module(mod);
1734 kmod_module_unref(mod);
1735 if ((r < 0) && !arg_optional) {
1736 if (!arg_silent)
1737 log_error("ERROR: installing module '%s'", modname);
1738 return -ENOENT;
1739 };
1740 ret = ( ret == 0 ? 0 : r );
1741 modinst = 1;
1742 }
1743 } else if (argv[i][0] == '=') {
1744 _cleanup_free_ char *path1 = NULL, *path2 = NULL, *path3 = NULL;
1745 _cleanup_fts_close_ FTS *fts = NULL;
1746
1747 log_debug("Handling =%s", &argv[i][1]);
1748 /* FIXME and add more paths*/
1749 r = asprintf(&path2, "%s/kernel/%s", kerneldir, &argv[i][1]);
1750 if (r < 0) {
1751 log_error("Out of memory!");
1752 exit(EXIT_FAILURE);
1753 }
1754
1755 r = asprintf(&path1, "%s/extra/%s", kerneldir, &argv[i][1]);
1756 if (r < 0) {
1757 log_error("Out of memory!");
1758 exit(EXIT_FAILURE);
1759 }
1760
1761 r = asprintf(&path3, "%s/updates/%s", kerneldir, &argv[i][1]);
1762 if (r < 0) {
1763 log_error("Out of memory!");
1764 exit(EXIT_FAILURE);
1765 }
1766
1767 {
1768 char *paths[] = { path1, path2, path3, NULL };
1769 fts = fts_open(paths, FTS_COMFOLLOW|FTS_NOCHDIR|FTS_NOSTAT|FTS_LOGICAL, NULL);
1770 }
1771
1772 for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
1773 _cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;
1774 _cleanup_free_ const char *modname = NULL;
1775
1776 if((ftsent->fts_info == FTS_D) && !check_module_path(ftsent->fts_accpath)) {
1777 fts_set(fts, ftsent, FTS_SKIP);
1778 log_debug("Skipping %s", ftsent->fts_accpath);
1779 continue;
1780 }
1781 if((ftsent->fts_info != FTS_F) && (ftsent->fts_info != FTS_SL)) {
1782 log_debug("Ignoring %s", ftsent->fts_accpath);
1783 continue;
1784 }
1785 log_debug("Handling %s", ftsent->fts_accpath);
1786 r = kmod_module_new_from_path(ctx, ftsent->fts_accpath, &mod_o);
1787 if (r < 0) {
1788 log_debug("Failed to lookup modules path '%s': %m",
1789 ftsent->fts_accpath);
1790 if (!arg_optional) {
1791 return -ENOENT;
1792 }
1793 continue;
1794 }
1795
1796 /* Check, if we have to load another module with that name instead */
1797 modname = strdup(kmod_module_get_name(mod_o));
1798
1799 if (!modname) {
1800 log_error("Failed to get name for module '%s'", ftsent->fts_accpath);
1801 if (!arg_optional) {
1802 return -ENOENT;
1803 }
1804 continue;
1805 }
1806 r = kmod_module_new_from_lookup(ctx, modname, &modlist);
1807 kmod_module_unref(mod_o);
1808 mod_o = NULL;
1809
1810 if (r < 0) {
1811 log_error("Failed to lookup alias '%s': %m", modname);
1812 if (!arg_optional) {
1813 return -ENOENT;
1814 }
1815 continue;
1816 }
1817
1818 if (!modlist) {
1819 log_error("Failed to find module '%s' %s", modname,
1820 ftsent->fts_accpath);
1821 if (!arg_optional) {
1822 return -ENOENT;
1823 }
1824 continue;
1825 }
1826 kmod_list_foreach(itr, modlist) {
1827 mod = kmod_module_get_module(itr);
1828 r = install_module(mod);
1829 kmod_module_unref(mod);
1830 if ((r < 0) && !arg_optional) {
1831 if (!arg_silent)
1832 log_error("ERROR: installing module '%s'", modname);
1833 return -ENOENT;
1834 };
1835 ret = ( ret == 0 ? 0 : r );
1836 modinst = 1;
1837 }
1838 }
1839 if (errno) {
1840 log_error("FTS ERROR: %m");
1841 }
1842 } else {
1843 _cleanup_kmod_module_unref_list_ struct kmod_list *modlist = NULL;
1844 char *modname = argv[i];
1845
1846 if (endswith(modname, ".ko")) {
1847 int len = strlen(modname);
1848 modname[len-3]=0;
1849 }
1850 if (endswith(modname, ".ko.xz") || endswith(modname, ".ko.gz")) {
1851 int len = strlen(modname);
1852 modname[len-6]=0;
1853 }
1854 r = kmod_module_new_from_lookup(ctx, modname, &modlist);
1855 if (r < 0) {
1856 if (!arg_optional) {
1857 if (!arg_silent)
1858 log_error("Failed to lookup alias '%s': %m", modname);
1859 return -ENOENT;
1860 }
1861 log_info("Failed to lookup alias '%s': %m", modname);
1862 continue;
1863 }
1864 if (!modlist) {
1865 if (!arg_optional) {
1866 if (!arg_silent)
1867 log_error("Failed to find module '%s'", modname);
1868 return -ENOENT;
1869 }
1870 log_info("Failed to find module '%s'", modname);
1871 continue;
1872 }
1873 kmod_list_foreach(itr, modlist) {
1874 mod = kmod_module_get_module(itr);
1875 r = install_module(mod);
1876 kmod_module_unref(mod);
1877 if ((r < 0) && !arg_optional) {
1878 if (!arg_silent)
1879 log_error("ERROR: installing '%s'", argv[i]);
1880 return -ENOENT;
1881 };
1882 ret = ( ret == 0 ? 0 : r );
1883 modinst = 1;
1884 }
1885 }
1886
1887 if ((modinst != 0) && (ret != 0) && (!arg_optional)) {
1888 if (!arg_silent)
1889 log_error("ERROR: installing '%s'", argv[i]);
1890 return EXIT_FAILURE;
1891 }
1892 }
1893
1894 return EXIT_SUCCESS;
1895 }
1896
1897 int main(int argc, char **argv)
1898 {
1899 int r;
1900 char *i;
1901 char *path = NULL;
1902 char *env_no_xattr = NULL;
1903
1904 r = parse_argv(argc, argv);
1905 if (r <= 0)
1906 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1907
1908 log_set_target(LOG_TARGET_CONSOLE);
1909 log_parse_environment();
1910
1911 if (arg_loglevel >= 0)
1912 log_set_max_level(arg_loglevel);
1913
1914 log_open();
1915
1916 modules_loaded = hashmap_new(string_hash_func, string_compare_func);
1917 if (arg_modalias) {
1918 Iterator i;
1919 char *name;
1920 _cleanup_kmod_unref_ struct kmod_ctx *ctx = NULL;
1921 ctx = kmod_new(kerneldir, NULL);
1922
1923 modalias_list(ctx);
1924 HASHMAP_FOREACH(name, modules_loaded, i) {
1925 printf("%s\n", name);
1926 }
1927 exit(0);
1928 }
1929
1930 log_debug("Program arguments:");
1931 for (r = 0; r < argc; r++)
1932 log_debug("%s", argv[r]);
1933
1934 path = getenv("DRACUT_INSTALL_PATH");
1935 if (path == NULL)
1936 path = getenv("PATH");
1937
1938 if (path == NULL) {
1939 log_error("PATH is not set");
1940 exit(EXIT_FAILURE);
1941 }
1942
1943 log_debug("PATH=%s", path);
1944
1945 ldd = getenv("DRACUT_LDD");
1946 if (ldd == NULL)
1947 ldd = "ldd";
1948 log_debug("LDD=%s", ldd);
1949
1950 env_no_xattr = getenv("DRACUT_NO_XATTR");
1951 if (env_no_xattr != NULL)
1952 no_xattr = true;
1953
1954 pathdirs = strv_split(path, ":");
1955
1956 umask(0022);
1957
1958 if (destrootdir == NULL || strlen(destrootdir) == 0) {
1959 destrootdir = getenv("DESTROOTDIR");
1960 if (destrootdir == NULL || strlen(destrootdir) == 0) {
1961 log_error("Environment DESTROOTDIR or argument -D is not set!");
1962 usage(EXIT_FAILURE);
1963 }
1964 destrootdir = strdup(destrootdir);
1965 }
1966
1967 if (strcmp(destrootdir, "/") == 0) {
1968 log_error("Environment DESTROOTDIR or argument -D is set to '/'!");
1969 usage(EXIT_FAILURE);
1970 }
1971
1972 i = destrootdir;
1973 destrootdir = realpath(destrootdir, NULL);
1974 if (!destrootdir) {
1975 log_error("Environment DESTROOTDIR or argument -D is set to '%s': %m", i);
1976 r = EXIT_FAILURE;
1977 goto finish;
1978 }
1979 free(i);
1980
1981 items = hashmap_new(string_hash_func, string_compare_func);
1982 items_failed = hashmap_new(string_hash_func, string_compare_func);
1983
1984 if (!items || !items_failed || !modules_loaded) {
1985 log_error("Out of memory");
1986 r = EXIT_FAILURE;
1987 goto finish;
1988 }
1989
1990 if (logdir) {
1991 int ret;
1992
1993 ret = asprintf(&logfile, "%s/%d.log", logdir, getpid());
1994 if (ret < 0) {
1995 log_error("Out of memory!");
1996 exit(EXIT_FAILURE);
1997 }
1998
1999 logfile_f = fopen(logfile, "a");
2000 if (logfile_f == NULL) {
2001 log_error("Could not open %s for logging: %m", logfile);
2002 r = EXIT_FAILURE;
2003 goto finish;
2004 }
2005 }
2006
2007 r = EXIT_SUCCESS;
2008
2009 if (((optind + 1) < argc) && (strcmp(argv[optind + 1], destrootdir) == 0)) {
2010 /* ugly hack for compat mode "inst src $destrootdir" */
2011 if ((optind + 2) == argc) {
2012 argc--;
2013 } else {
2014 /* ugly hack for compat mode "inst src $destrootdir dst" */
2015 if ((optind + 3) == argc) {
2016 argc--;
2017 argv[optind + 1] = argv[optind + 2];
2018 }
2019 }
2020 }
2021
2022 if (arg_module) {
2023 r = install_modules(argc - optind, &argv[optind]);
2024 } else if (arg_resolvelazy) {
2025 r = resolve_lazy(argc - optind, &argv[optind]);
2026 } else if (arg_all || (argc - optind > 2) || ((argc - optind) == 1)) {
2027 r = install_all(argc - optind, &argv[optind]);
2028 } else {
2029 /* simple "inst src dst" */
2030 r = install_one(argv[optind], argv[optind + 1]);
2031 }
2032
2033 if (arg_optional)
2034 r = EXIT_SUCCESS;
2035
2036 finish:
2037 if (logfile_f)
2038 fclose(logfile_f);
2039
2040 while ((i = hashmap_steal_first(modules_loaded)))
2041 item_free(i);
2042
2043 while ((i = hashmap_steal_first(items)))
2044 item_free(i);
2045
2046 while ((i = hashmap_steal_first(items_failed)))
2047 item_free(i);
2048
2049 hashmap_free(items);
2050 hashmap_free(items_failed);
2051 hashmap_free(modules_loaded);
2052
2053 free(destrootdir);
2054 strv_free(firmwaredirs);
2055 strv_free(pathdirs);
2056 return r;
2057 }