1 /* dracut-install.c -- install files and executables
3 Copyright (C) 2012 Harald Hoyer
4 Copyright (C) 2012 Red Hat, Inc. All rights reserved.
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.
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.
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/>.
20 #define PROGRAM_VERSION_STRING "2"
25 #undef _FILE_OFFSET_BITS
37 #include <sys/types.h>
40 #include <sys/ioctl.h>
44 #include <sys/utsname.h>
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;
88 static int dracut_install(const char *src
, const char *dst
, bool isdir
, bool resolvedeps
, bool hashdst
);
91 static inline void kmod_module_unrefp(struct kmod_module
**p
) {
93 kmod_module_unref(*p
);
95 #define _cleanup_kmod_module_unref_ _cleanup_(kmod_module_unrefp)
97 static inline void kmod_module_unref_listp(struct kmod_list
**p
) {
99 kmod_module_unref_list(*p
);
101 #define _cleanup_kmod_module_unref_list_ _cleanup_(kmod_module_unref_listp)
103 static inline void kmod_module_info_free_listp(struct kmod_list
**p
) {
105 kmod_module_info_free_list(*p
);
107 #define _cleanup_kmod_module_info_free_list_ _cleanup_(kmod_module_info_free_listp)
109 static inline void kmod_unrefp(struct kmod_ctx
**p
) {
112 #define _cleanup_kmod_unref_ _cleanup_(kmod_unrefp)
114 static inline void kmod_module_dependency_symbols_free_listp(struct kmod_list
**p
) {
116 kmod_module_dependency_symbols_free_list(*p
);
118 #define _cleanup_kmod_module_dependency_symbols_free_list_ _cleanup_(kmod_module_dependency_symbols_free_listp)
120 static inline void fts_closep(FTS
**p
) {
124 #define _cleanup_fts_close_ _cleanup_(fts_closep)
128 static size_t dir_len(char const *file
)
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] != '/')
142 static char *convert_abs_rel(const char *from
, const char *target
)
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;
151 size_t i
, rl
, dirlen
;
154 target_dir_p
= strdup(target
);
158 dirlen
= dir_len(target_dir_p
);
159 target_dir_p
[dirlen
] = '\0';
160 realpath_p
= realpath(target_dir_p
, NULL
);
162 if (realpath_p
== NULL
) {
163 log_warning("convert_abs_rel(): target '%s' directory has no realpath.", target
);
167 /* dir_len() skips double /'s e.g. //lib64, so we can't skip just one
168 * character - need to skip all leading /'s */
170 for (i
= dirlen
+ 1; i
< rl
; ++i
)
171 if (target_dir_p
[i
] != '/')
173 ret
= asprintf(&realtarget
, "%s/%s", realpath_p
, &target_dir_p
[i
]);
175 log_error("Out of memory!");
179 /* now calculate the relative path from <from> to <target> and
180 store it in <relative_from>
182 relative_from
[0] = 0;
185 /* count the pathname elements of realtarget */
186 for (targetlevel
= 0, i
= 0; realtarget
[i
]; i
++)
187 if (realtarget
[i
] == '/')
190 /* count the pathname elements of realfrom */
191 for (fromlevel
= 0, i
= 0; realfrom
[i
]; i
++)
192 if (realfrom
[i
] == '/')
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
] == '/')
200 /* add "../" to the relative_from path, until the common pathname is
202 for (i
= level
; i
< targetlevel
; i
++) {
204 relative_from
[rl
++] = '/';
205 relative_from
[rl
++] = '.';
206 relative_from
[rl
++] = '.';
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
++) ;
215 /* append the uncommon rest of realfrom to the relative_from path */
216 for (i
= level
; i
<= fromlevel
; i
++) {
218 relative_from
[rl
++] = '/';
219 while (realfrom
[l
] && realfrom
[l
] != '/')
220 relative_from
[rl
++] = realfrom
[l
++];
224 relative_from
[rl
] = 0;
225 return strdup(relative_from
);
228 static int ln_r(const char *src
, const char *dst
)
231 _cleanup_free_
const char *points_to
= convert_abs_rel(src
, dst
);
233 log_info("ln -s '%s' '%s'", points_to
, dst
);
234 ret
= symlink(points_to
, dst
);
237 log_error("ERROR: ln -s '%s' '%s': %m", points_to
, dst
);
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
)
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
);
255 static bool use_clone
= true;
257 static int cp(const char *src
, const char *dst
)
264 _cleanup_close_
int dest_desc
= -1, source_desc
= -1;
266 if (lstat(src
, &sb
) != 0)
269 if (S_ISLNK(sb
.st_mode
))
272 source_desc
= open(src
, O_RDONLY
| O_CLOEXEC
);
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
));
284 ret
= clone_file(dest_desc
, source_desc
);
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) {
291 log_error("Failed to chown %s: %m", dst
);
293 log_info("Failed to chown %s: %m", dst
);
296 tv
[0].tv_sec
= sb
.st_atime
;
298 tv
[1].tv_sec
= sb
.st_mtime
;
300 futimes(dest_desc
, tv
);
305 /* clone did not work, remove the file */
307 /* do not try clone again */
314 if (geteuid() == 0 && no_xattr
== false)
315 execlp("cp", "cp", "--reflink=auto", "--sparse=auto", "--preserve=mode,xattr,timestamps", "-fL", src
, dst
,
318 execlp("cp", "cp", "--reflink=auto", "--sparse=auto", "--preserve=mode,timestamps", "-fL", src
, dst
,
323 while (waitpid(pid
, &ret
, 0) < 0) {
324 if (errno
!= EINTR
) {
326 if (geteuid() == 0 && no_xattr
== false)
327 log_error("Failed: cp --reflink=auto --sparse=auto --preserve=mode,xattr,timestamps -fL %s %s", src
,
330 log_error("Failed: cp --reflink=auto --sparse=auto --preserve=mode,timestamps -fL %s %s", src
,
335 log_debug("cp ret = %d", ret
);
339 static int library_install(const char *src
, const char *lib
)
341 _cleanup_free_
char *p
= NULL
;
342 _cleanup_free_
char *pdir
= NULL
, *ppdir
= NULL
, *clib
= NULL
;
348 r
= dracut_install(p
, p
, false, false, true);
350 log_error("ERROR: failed to install '%s' for '%s'", p
, src
);
352 log_debug("Lib install: '%s'", p
);
355 /* also install lib.so for lib.so.* files */
356 q
= strstr(p
, ".so.");
360 /* ignore errors for base lib symlink */
361 if (dracut_install(p
, p
, false, false, true) == 0)
362 log_debug("Lib install: '%s'", p
);
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
381 ppdir
= dirname(pdir
);
385 ppdir
= strdup(ppdir
);
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.");
397 /* ignore errors for base lib symlink */
398 if (dracut_install(clib
, clib
, false, false, true) == 0)
399 log_debug("Lib install: '%s'", p
);
405 static char *get_real_file(const char *src
, bool fullyresolve
)
407 char linktarget
[PATH_MAX
+ 1];
409 _cleanup_free_
char *fullsrcpath
;
410 char *abspath
= NULL
;
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)
419 fullsrcpath
= strdup(src
);
421 log_debug("get_real_file('%s')", fullsrcpath
);
423 if (lstat(fullsrcpath
, &sb
) < 0)
426 switch (sb
.st_mode
& S_IFMT
) {
429 return strdup(fullsrcpath
);
436 linksz
= readlink(fullsrcpath
, linktarget
, sizeof(linktarget
));
439 linktarget
[linksz
] = '\0';
441 log_debug("get_real_file: readlink('%s') returns '%s'", fullsrcpath
, linktarget
);
443 if (linktarget
[0] == '/') {
444 if (asprintf(&abspath
, "%s%s", (sysrootdirlen
? sysrootdir
: ""), linktarget
) < 0)
447 _cleanup_free_
char *fullsrcdir
= strdup(fullsrcpath
);
450 log_error("Out of memory!");
454 fullsrcdir
[dir_len(fullsrcdir
)] = '\0';
456 if (asprintf(&abspath
, "%s/%s", fullsrcdir
, linktarget
) < 0)
462 if (lstat(abspath
, &st
) < 0) {
466 if (S_ISLNK(st
.st_mode
))
467 return get_real_file(abspath
, fullyresolve
);
470 log_debug("get_real_file('%s') => '%s'", src
, abspath
);
474 static int resolve_deps(const char *src
)
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
;
484 fullsrcpath
= get_real_file(src
, true);
485 log_debug("resolve_deps('%s') -> get_real_file('%s', true) = '%s'", src
, src
, fullsrcpath
);
489 buf
= malloc(LINE_MAX
);
493 if (strstr(src
, ".so") == 0) {
494 _cleanup_close_
int fd
= -1;
495 fd
= open(fullsrcpath
, O_RDONLY
| O_CLOEXEC
);
499 ret
= read(fd
, buf
, LINE_MAX
);
503 buf
[LINE_MAX
- 1] = '\0';
504 if (buf
[0] == '#' && buf
[1] == '!') {
505 /* we have a shebang */
507 for (p
= &buf
[2]; *p
&& isspace(*p
); p
++) ;
508 for (q
= p
; *q
&& (!isspace(*q
)); q
++) ;
510 log_debug("Script install: '%s'", p
);
511 ret
= dracut_install(p
, p
, false, true, false);
513 log_error("ERROR: failed to install '%s'", p
);
519 ret
= asprintf(&cmd
, "%s %s 2>&1", ldd
, fullsrcpath
);
521 log_error("Out of memory!");
525 log_debug("%s", cmd
);
529 fptr
= popen(cmd
, "r");
531 while (!feof(fptr
)) {
534 if (getline(&buf
, &linesize
, fptr
) <= 0)
537 log_debug("ldd: '%s'", buf
);
539 if (strstr(buf
, "you do not have execution permission")) {
540 log_error("%s", buf
);
545 /* errors from cross-compiler-ldd */
546 if (strstr(buf
, "unable to find sysroot") || strstr(buf
, "command not found")) {
547 log_error("%s", buf
);
553 if (strstr(buf
, "Not a valid dynamic program"))
557 if (strstr(buf
, "cannot execute binary file"))
560 if (strstr(buf
, "not a dynamic executable"))
563 if (strstr(buf
, "loader cannot load itself"))
566 if (strstr(buf
, "not regular file"))
569 if (strstr(buf
, "cannot read header"))
572 if (strstr(buf
, destrootdir
))
575 p
= strchr(buf
, '/');
579 for (q
= p
; *q
&& *q
!= ' ' && *q
!= '\n'; q
++) ;
582 ret
+= library_install(src
, p
);
590 /* Install ".<filename>.hmac" file for FIPS self-checks */
591 static int hmac_install(const char *src
, const char *dst
, const char *hmacpath
)
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
;
599 if (!(srcpath
&& dstpath
))
602 size_t dlen
= dir_len(src
);
604 if (endswith(src
, ".hmac"))
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");
614 srcpath
[dlen
] = '\0';
615 dstpath
[dir_len(dst
)] = '\0';
617 ret
= asprintf(&srchmacname
, "%s/%s.hmac", hmacpath
, &src
[dlen
+ 1]);
619 log_error("Out of memory!");
623 ret
= asprintf(&dsthmacname
, "%s/%s.hmac", hmacpath
, &src
[dlen
+ 1]);
625 log_error("Out of memory!");
629 ret
= asprintf(&srchmacname
, "%s/.%s.hmac", srcpath
, &src
[dlen
+ 1]);
631 log_error("Out of memory!");
635 ret
= asprintf(&dsthmacname
, "%s/.%s.hmac", dstpath
, &src
[dlen
+ 1]);
637 log_error("Out of memory!");
641 log_debug("hmac cp '%s' '%s')", srchmacname
, dsthmacname
);
642 dracut_install(srchmacname
, dsthmacname
, false, false, true);
646 void mark_hostonly(const char *path
)
648 _cleanup_free_
char *fulldstpath
= NULL
;
649 _cleanup_fclose_
FILE *f
= NULL
;
652 ret
= asprintf(&fulldstpath
, "%s/lib/dracut/hostonly-files", destrootdir
);
654 log_error("Out of memory!");
658 f
= fopen(fulldstpath
, "a");
661 log_error("Could not open '%s' for writing.", fulldstpath
);
665 fprintf(f
, "%s\n", path
);
668 void dracut_log_cp(const char *path
)
671 ret
= fprintf(logfile_f
, "%s\n", path
);
673 log_error("Could not append '%s' to logfile '%s': %m", path
, logfile
);
676 static bool check_hashmap(Hashmap
*hm
, const char *item
)
679 existing
= hashmap_get(hm
, item
);
681 if (strcmp(existing
, item
) == 0) {
688 static int dracut_mkdir(const char *src
) {
689 _cleanup_free_
char *parent
= NULL
;
693 parent
= strdup(src
);
697 path
= parent
[0] == '/' ? parent
+1 : parent
;
699 path
= strstr(path
, "/");
703 if (stat(parent
, &sb
) == 0) {
704 if (!S_ISDIR(sb
.st_mode
)) {
705 log_error("%s exists but is not a directory!", parent
);
708 } else if (errno
!= ENOENT
) {
709 log_error("ERROR: stat '%s': %s", parent
, strerror(errno
));
712 if (mkdir(parent
, 0755) < 0) {
713 log_error("ERROR: mkdir '%s': %s", parent
, strerror(errno
));
727 static int dracut_install(const char *orig_src
, const char *orig_dst
, bool isdir
, bool resolvedeps
, bool hashdst
)
730 _cleanup_free_
char *fullsrcpath
= NULL
;
731 _cleanup_free_
char *fulldstpath
= NULL
;
732 _cleanup_free_
char *fulldstdir
= NULL
;
734 bool src_islink
= false;
735 bool src_isdir
= false;
737 bool dst_exists
= true;
739 _cleanup_free_
char *src
;
740 _cleanup_free_
char *dst
;
743 if (strncmp(orig_src
, sysrootdir
, sysrootdirlen
) == 0) {
744 src
= strdup(orig_src
+ sysrootdirlen
);
745 fullsrcpath
= strdup(orig_src
);
747 src
= strdup(orig_src
);
748 if (asprintf(&fullsrcpath
, "%s%s", sysrootdir
, src
) < 0)
751 if (strncmp(orig_dst
, sysrootdir
, sysrootdirlen
) == 0)
752 dst
= strdup(orig_dst
+ sysrootdirlen
);
754 dst
= strdup(orig_dst
);
756 src
= strdup(orig_src
);
757 fullsrcpath
= strdup(src
);
758 dst
= strdup(orig_dst
);
761 log_debug("dracut_install('%s', '%s', %d, %d, %d)", src
, dst
, isdir
, resolvedeps
, hashdst
);
763 if (check_hashmap(items_failed
, src
)) {
764 log_debug("hash hit items_failed for '%s'", src
);
768 if (hashdst
&& check_hashmap(items
, dst
)) {
769 log_debug("hash hit items for '%s'", dst
);
773 if (lstat(fullsrcpath
, &sb
) < 0) {
776 hashmap_put(items_failed
, i
, i
);
777 /* src does not exist */
781 src_islink
= S_ISLNK(sb
.st_mode
);
782 src_isdir
= S_ISDIR(sb
.st_mode
);
783 src_mode
= sb
.st_mode
;
786 ret
= asprintf(&fulldstpath
, "%s/%s", destrootdir
, (dst
[0]=='/' ? (dst
+1) : dst
));
788 log_error("Out of memory!");
792 ret
= stat(fulldstpath
, &sb
);
796 if (errno
!= ENOENT
) {
797 log_error("ERROR: stat '%s': %m", fulldstpath
);
803 if (resolvedeps
&& S_ISREG(sb
.st_mode
) && (sb
.st_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
))) {
804 log_debug("'%s' already exists, but checking for any deps", fulldstpath
);
805 ret
= resolve_deps(fullsrcpath
+ sysrootdirlen
);
807 log_debug("'%s' already exists", fulldstpath
);
809 /* dst does already exist */
813 /* check destination directory */
814 fulldstdir
= strdup(fulldstpath
);
816 log_error("Out of memory!");
819 fulldstdir
[dir_len(fulldstdir
)] = '\0';
821 ret
= stat(fulldstdir
, &db
);
824 _cleanup_free_
char *dname
= NULL
;
826 if (errno
!= ENOENT
) {
827 log_error("ERROR: stat '%s': %m", fulldstdir
);
830 /* create destination directory */
831 log_debug("dest dir '%s' does not exist", fulldstdir
);
836 dname
[dir_len(dname
)] = '\0';
837 ret
= dracut_install(dname
, dname
, true, false, true);
840 log_error("ERROR: failed to create directory '%s'", fulldstdir
);
847 if (S_ISDIR(sb
.st_mode
)) {
848 log_debug("dest dir '%s' already exists", fulldstpath
);
851 log_error("dest dir '%s' already exists but is not a directory", fulldstpath
);
855 log_info("mkdir '%s'", fulldstpath
);
856 ret
= dracut_mkdir(fulldstpath
);
862 hashmap_put(items
, i
, i
);
867 /* ready to install src */
870 _cleanup_free_
char *abspath
= NULL
;
872 abspath
= get_real_file(src
, false);
877 if (dracut_install(abspath
, abspath
, false, resolvedeps
, hashdst
)) {
878 log_debug("'%s' install error", abspath
);
882 if (lstat(abspath
, &sb
) != 0) {
883 log_debug("lstat '%s': %m", abspath
);
887 if (lstat(fulldstpath
, &sb
) != 0) {
888 _cleanup_free_
char *absdestpath
= NULL
;
890 ret
= asprintf(&absdestpath
, "%s/%s", destrootdir
, (abspath
[0]=='/' ? (abspath
+1) : abspath
) + sysrootdirlen
);
892 log_error("Out of memory!");
896 ln_r(absdestpath
, fulldstpath
);
900 /* copy .hmac files also */
901 hmac_install(src
, dst
, NULL
);
907 if (src_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
909 ret
+= resolve_deps(fullsrcpath
+ sysrootdirlen
);
911 /* copy .hmac files also */
912 hmac_install(src
, dst
, NULL
);
916 log_debug("dracut_install ret = %d", ret
);
918 if (arg_hostonly
&& !arg_module
)
922 log_info("mkdir '%s'", fulldstpath
);
923 ret
+= dracut_mkdir(fulldstpath
);
925 log_info("cp '%s' '%s'", fullsrcpath
, fulldstpath
);
926 ret
+= cp(fullsrcpath
, fulldstpath
);
934 hashmap_put(items
, i
, i
);
940 log_debug("dracut_install ret = %d", ret
);
945 static void item_free(char *i
)
951 static void usage(int status
)
954 printf("Usage: %s -D DESTROOTDIR [-r SYSROOTDIR] [OPTION]... -a SOURCE...\n"
955 "or: %s -D DESTROOTDIR [-r SYSROOTDIR] [OPTION]... SOURCE DEST\n"
956 "or: %s -D DESTROOTDIR [-r SYSROOTDIR] [OPTION]... -m KERNELMODULE [KERNELMODULE …]\n"
958 "Install SOURCE (from rootfs or SYSROOTDIR) to DEST in DESTROOTDIR with all needed dependencies.\n"
960 " KERNELMODULE can have the format:\n"
961 " <absolute path> with a leading /\n"
962 " =<kernel subdir>[/<kernel subdir>…] like '=drivers/hid'\n"
965 " -D --destrootdir Install all files to DESTROOTDIR as the root\n"
966 " -r --sysrootdir Install all files from SYSROOTDIR\n"
967 " -a --all Install all SOURCE arguments to DESTROOTDIR\n"
968 " -o --optional If SOURCE does not exist, do not fail\n"
969 " -d --dir SOURCE is a directory\n"
970 " -l --ldd Also install shebang executables and libraries\n"
971 " -L --logdir <DIR> Log files, which were installed from the host to <DIR>\n"
972 " -R --resolvelazy Only install shebang executables and libraries\n"
973 " for all SOURCE files\n"
974 " -H --hostonly Mark all SOURCE files as hostonly\n\n"
975 " -f --fips Also install all '.SOURCE.hmac' files\n"
977 " --module,-m Install kernel modules, instead of files\n"
978 " --kerneldir Specify the kernel module directory\n"
979 " --firmwaredirs Specify the firmware directory search path with : separation\n"
980 " --silent Don't display error messages for kernel module install\n"
981 " --modalias Only generate module list from /sys/devices modalias list\n"
982 " -o --optional If kernel module does not exist, do not fail\n"
983 " -p --mod-filter-path Filter kernel modules by path regexp\n"
984 " -P --mod-filter-nopath Exclude kernel modules by path regexp\n"
985 " -s --mod-filter-symbol Filter kernel modules by symbol regexp\n"
986 " -S --mod-filter-nosymbol Exclude kernel modules by symbol regexp\n"
987 " -N --mod-filter-noname Exclude kernel modules by name regexp\n"
989 " -v --verbose Show more output\n"
990 " --debug Show debug output\n"
991 " --version Show package version\n"
992 " -h --help Show this help\n"
994 program_invocation_short_name
, program_invocation_short_name
,
995 program_invocation_short_name
);
999 static int parse_argv(int argc
, char *argv
[])
1004 ARG_VERSION
= 0x100,
1012 static struct option
const options
[] = {
1013 {"help", no_argument
, NULL
, 'h'},
1014 {"version", no_argument
, NULL
, ARG_VERSION
},
1015 {"dir", no_argument
, NULL
, 'd'},
1016 {"debug", no_argument
, NULL
, ARG_DEBUG
},
1017 {"verbose", no_argument
, NULL
, 'v'},
1018 {"ldd", no_argument
, NULL
, 'l'},
1019 {"resolvelazy", no_argument
, NULL
, 'R'},
1020 {"optional", no_argument
, NULL
, 'o'},
1021 {"hostonly", no_argument
, NULL
, 'H'},
1022 {"all", no_argument
, NULL
, 'a'},
1023 {"module", no_argument
, NULL
, 'm'},
1024 {"fips", no_argument
, NULL
, 'f'},
1025 {"destrootdir", required_argument
, NULL
, 'D'},
1026 {"sysrootdir", required_argument
, NULL
, 'r'},
1027 {"logdir", required_argument
, NULL
, 'L'},
1028 {"mod-filter-path", required_argument
, NULL
, 'p'},
1029 {"mod-filter-nopath", required_argument
, NULL
, 'P'},
1030 {"mod-filter-symbol", required_argument
, NULL
, 's'},
1031 {"mod-filter-nosymbol", required_argument
, NULL
, 'S'},
1032 {"mod-filter-noname", required_argument
, NULL
, 'N'},
1033 {"modalias", no_argument
, NULL
, ARG_MODALIAS
},
1034 {"silent", no_argument
, NULL
, ARG_SILENT
},
1035 {"kerneldir", required_argument
, NULL
, ARG_KERNELDIR
},
1036 {"firmwaredirs", required_argument
, NULL
, ARG_FIRMWAREDIRS
},
1040 while ((c
= getopt_long(argc
, argv
, "madfhlL:oD:Hr:Rp:P:s:S:N:v", options
, NULL
)) != -1) {
1043 puts(PROGRAM_VERSION_STRING
);
1046 arg_createdir
= true;
1049 arg_loglevel
= LOG_DEBUG
;
1055 arg_modalias
= true;
1059 arg_loglevel
= LOG_INFO
;
1062 arg_optional
= true;
1065 arg_resolvedeps
= true;
1068 arg_resolvelazy
= true;
1077 destrootdir
= strdup(optarg
);
1080 sysrootdir
= strdup(optarg
);
1081 sysrootdirlen
= strlen(sysrootdir
);
1084 if (regcomp(&mod_filter_path
, optarg
, REG_NOSUB
|REG_EXTENDED
) != 0) {
1085 log_error("Module path filter %s is not a regular expression", optarg
);
1088 arg_mod_filter_path
= true;
1091 if (regcomp(&mod_filter_nopath
, optarg
, REG_NOSUB
|REG_EXTENDED
) != 0) {
1092 log_error("Module path filter %s is not a regular expression", optarg
);
1095 arg_mod_filter_nopath
= true;
1098 if (regcomp(&mod_filter_symbol
, optarg
, REG_NOSUB
|REG_EXTENDED
) != 0) {
1099 log_error("Module symbol filter %s is not a regular expression", optarg
);
1102 arg_mod_filter_symbol
= true;
1105 if (regcomp(&mod_filter_nosymbol
, optarg
, REG_NOSUB
|REG_EXTENDED
) != 0) {
1106 log_error("Module symbol filter %s is not a regular expression", optarg
);
1109 arg_mod_filter_nosymbol
= true;
1112 if (regcomp(&mod_filter_noname
, optarg
, REG_NOSUB
|REG_EXTENDED
) != 0) {
1113 log_error("Module symbol filter %s is not a regular expression", optarg
);
1116 arg_mod_filter_noname
= true;
1119 logdir
= strdup(optarg
);
1122 kerneldir
= strdup(optarg
);
1124 case ARG_FIRMWAREDIRS
:
1125 firmwaredirs
= strv_split(optarg
, ":");
1131 arg_hostonly
= true;
1134 usage(EXIT_SUCCESS
);
1137 usage(EXIT_FAILURE
);
1144 kerneldir
= strdup(buf
.version
);
1152 if (!firmwaredirs
) {
1155 path
= getenv("DRACUT_FIRMWARE_PATH");
1158 log_error("Environment variable DRACUT_FIRMWARE_PATH is not set");
1162 log_debug("DRACUT_FIRMWARE_PATH=%s", path
);
1164 firmwaredirs
= strv_split(path
, ":");
1168 if (!optind
|| optind
== argc
) {
1169 log_error("No SOURCE argument given");
1170 usage(EXIT_FAILURE
);
1176 static int resolve_lazy(int argc
, char **argv
)
1179 size_t destrootdirlen
= strlen(destrootdir
);
1182 for (i
= 0; i
< argc
; i
++) {
1183 const char *src
= argv
[i
];
1187 log_debug("resolve_deps('%s')", src
);
1189 if (strstr(src
, destrootdir
)) {
1190 p
= &argv
[i
][destrootdirlen
];
1193 existing
= hashmap_get(items
, p
);
1195 if (strcmp(existing
, p
) == 0)
1200 hashmap_put(items
, item
, item
);
1202 ret
+= resolve_deps(src
);
1207 static char **find_binary(const char *src
)
1212 char *newsrc
= NULL
;
1214 STRV_FOREACH(q
, pathdirs
) {
1218 r
= asprintf(&newsrc
, "%s/%s", *q
, src
);
1220 log_error("Out of memory!");
1224 fullsrcpath
= get_real_file(newsrc
, false);
1227 log_debug("get_real_file(%s) not found", newsrc
);
1233 if (lstat(fullsrcpath
, &sb
) != 0) {
1234 log_debug("stat(%s) != 0", fullsrcpath
);
1242 strv_push(&ret
, newsrc
);
1249 STRV_FOREACH(q
, ret
) {
1250 log_debug("find_binary(%s) == %s", src
, *q
);
1257 static int install_one(const char *src
, const char *dst
)
1259 int r
= EXIT_SUCCESS
;
1262 if (strchr(src
, '/') == NULL
) {
1263 char **p
= find_binary(src
);
1266 STRV_FOREACH(q
, p
) {
1268 log_debug("dracut_install '%s' '%s'", newsrc
, dst
);
1269 ret
= dracut_install(newsrc
, dst
, arg_createdir
, arg_resolvedeps
, true);
1271 log_debug("dracut_install '%s' '%s' OK", newsrc
, dst
);
1279 ret
= dracut_install(src
, dst
, arg_createdir
, arg_resolvedeps
, true);
1282 if ((ret
!= 0) && (!arg_optional
)) {
1283 log_error("ERROR: installing '%s' to '%s'", src
, dst
);
1290 static int install_all(int argc
, char **argv
)
1292 int r
= EXIT_SUCCESS
;
1294 for (i
= 0; i
< argc
; i
++) {
1296 log_debug("Handle '%s'", argv
[i
]);
1298 if (strchr(argv
[i
], '/') == NULL
) {
1299 char **p
= find_binary(argv
[i
]);
1302 STRV_FOREACH(q
, p
) {
1304 log_debug("dracut_install '%s'", newsrc
);
1305 ret
= dracut_install(newsrc
, newsrc
, arg_createdir
, arg_resolvedeps
, true);
1307 log_debug("dracut_install '%s' OK", newsrc
);
1316 _cleanup_free_
char *dest
= strdup(argv
[i
]);
1317 ret
= dracut_install(argv
[i
], dest
, arg_createdir
, arg_resolvedeps
, true);
1320 if ((ret
!= 0) && (!arg_optional
)) {
1321 log_error("ERROR: installing '%s'", argv
[i
]);
1328 static int install_firmware(struct kmod_module
*mod
)
1330 struct kmod_list
*l
;
1331 _cleanup_kmod_module_info_free_list_
struct kmod_list
*list
= NULL
;
1336 ret
= kmod_module_get_info(mod
, &list
);
1338 log_error("could not get modinfo from '%s': %s\n",
1339 kmod_module_get_name(mod
), strerror(-ret
));
1342 kmod_list_foreach(l
, list
) {
1343 const char *key
= kmod_module_info_get_key(l
);
1344 const char *value
= NULL
;
1346 if (!streq("firmware", key
))
1349 value
= kmod_module_info_get_value(l
);
1350 log_debug("Firmware %s", value
);
1352 STRV_FOREACH(q
, firmwaredirs
) {
1353 _cleanup_free_
char *fwpath
= NULL
;
1354 _cleanup_free_
char *fwpath_xz
= NULL
;
1359 r
= asprintf(&fwpath
, "%s/%s", *q
, value
);
1361 log_error("Out of memory!");
1366 if (stat(fwpath
, &sb
) != 0) {
1367 r
= asprintf(&fwpath_xz
, "%s.xz", fwpath
);
1369 log_error("Out of memory!");
1372 if (stat(fwpath_xz
, &sb
) != 0) {
1373 log_debug("stat(%s) != 0", fwpath
);
1379 ret
= dracut_install(fw
, fw
, false, false, true);
1381 log_debug("dracut_install '%s' OK", fwpath
);
1385 log_info("Possible missing firmware %s for kernel module %s", value
, kmod_module_get_name(mod
));
1391 static bool check_module_symbols(struct kmod_module
*mod
)
1393 struct kmod_list
*itr
;
1394 _cleanup_kmod_module_dependency_symbols_free_list_
struct kmod_list
*deplist
= NULL
;
1396 if (!arg_mod_filter_symbol
&& !arg_mod_filter_nosymbol
)
1399 if (kmod_module_get_dependency_symbols(mod
, &deplist
) < 0) {
1400 log_debug("kmod_module_get_dependency_symbols failed");
1401 if (arg_mod_filter_symbol
)
1406 if (arg_mod_filter_nosymbol
) {
1407 kmod_list_foreach(itr
, deplist
) {
1408 const char *symbol
= kmod_module_symbol_get_symbol(itr
);
1409 // log_debug("Checking symbol %s", symbol);
1410 if (regexec(&mod_filter_nosymbol
, symbol
, 0, NULL
, 0) == 0) {
1411 log_debug("Module %s: symbol %s matched exclusion filter", kmod_module_get_name(mod
), symbol
);
1417 if (arg_mod_filter_symbol
) {
1418 kmod_list_foreach(itr
, deplist
) {
1419 const char *symbol
= kmod_module_dependency_symbol_get_symbol(itr
);
1420 // log_debug("Checking symbol %s", symbol);
1421 if (regexec(&mod_filter_symbol
, symbol
, 0, NULL
, 0) == 0) {
1422 log_debug("Module %s: symbol %s matched inclusion filter", kmod_module_get_name(mod
), symbol
);
1432 static bool check_module_path(const char *path
)
1434 if (arg_mod_filter_nopath
&& (regexec(&mod_filter_nopath
, path
, 0, NULL
, 0) == 0)) {
1435 log_debug("Path %s matched exclusion filter", path
);
1439 if (arg_mod_filter_path
&& (regexec(&mod_filter_path
, path
, 0, NULL
, 0) != 0)) {
1440 log_debug("Path %s matched inclusion filter", path
);
1446 static int install_dependent_modules(struct kmod_list
*modlist
)
1448 struct kmod_list
*itr
;
1449 const char *path
= NULL
;
1450 const char *name
= NULL
;
1453 kmod_list_foreach(itr
, modlist
) {
1454 _cleanup_kmod_module_unref_
struct kmod_module
*mod
= NULL
;
1455 mod
= kmod_module_get_module(itr
);
1456 path
= kmod_module_get_path(mod
);
1461 if (check_hashmap(items_failed
, path
))
1464 if (check_hashmap(items
, path
)) {
1468 name
= kmod_module_get_name(mod
);
1470 if (arg_mod_filter_noname
&& (regexec(&mod_filter_noname
, name
, 0, NULL
, 0) == 0)) {
1474 ret
= dracut_install(path
, &path
[kerneldirlen
], false, false, true);
1476 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1477 _cleanup_kmod_module_unref_list_
struct kmod_list
*modpre
= NULL
;
1478 _cleanup_kmod_module_unref_list_
struct kmod_list
*modpost
= NULL
;
1479 log_debug("dracut_install '%s' '%s' OK", path
, &path
[kerneldirlen
]);
1480 install_firmware(mod
);
1481 modlist
= kmod_module_get_dependencies(mod
);
1482 ret
= install_dependent_modules(modlist
);
1484 ret
= kmod_module_get_softdeps(mod
, &modpre
, &modpost
);
1486 ret
= install_dependent_modules(modpre
);
1489 log_error("dracut_install '%s' '%s' ERROR", path
, &path
[kerneldirlen
]);
1496 static int install_module(struct kmod_module
*mod
)
1499 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1500 _cleanup_kmod_module_unref_list_
struct kmod_list
*modpre
= NULL
;
1501 _cleanup_kmod_module_unref_list_
struct kmod_list
*modpost
= NULL
;
1502 const char *path
= NULL
;
1503 const char *name
= NULL
;
1505 name
= kmod_module_get_name(mod
);
1506 if (arg_mod_filter_noname
&& (regexec(&mod_filter_noname
, name
, 0, NULL
, 0) == 0)) {
1507 log_debug("dracut_install '%s' is excluded", name
);
1511 if (arg_hostonly
&& !check_hashmap(modules_loaded
, name
)) {
1512 log_debug("dracut_install '%s' not hostonly", name
);
1516 path
= kmod_module_get_path(mod
);
1520 if (check_hashmap(items_failed
, path
))
1523 if (check_hashmap(items
, path
))
1526 if (!check_module_path(path
) || !check_module_symbols(mod
)) {
1527 log_debug("No symbol or path match for '%s'", path
);
1531 log_debug("dracut_install '%s' '%s'", path
, &path
[kerneldirlen
]);
1533 ret
= dracut_install(path
, &path
[kerneldirlen
], false, false, true);
1535 log_debug("dracut_install '%s' OK", kmod_module_get_name(mod
));
1536 } else if (!arg_optional
) {
1538 log_error("dracut_install '%s' ERROR", kmod_module_get_name(mod
));
1541 install_firmware(mod
);
1543 modlist
= kmod_module_get_dependencies(mod
);
1544 ret
= install_dependent_modules(modlist
);
1547 ret
= kmod_module_get_softdeps(mod
, &modpre
, &modpost
);
1549 ret
= install_dependent_modules(modpre
);
1555 static int modalias_list(struct kmod_ctx
*ctx
)
1558 struct kmod_list
*loaded_list
= NULL
;
1559 struct kmod_list
*itr
, *l
;
1560 _cleanup_fts_close_ FTS
*fts
= NULL
;
1563 char *paths
[] = { "/sys/devices", NULL
};
1564 fts
= fts_open(paths
, FTS_NOCHDIR
|FTS_NOSTAT
, NULL
);
1566 for (FTSENT
*ftsent
= fts_read(fts
); ftsent
!= NULL
; ftsent
= fts_read(fts
)) {
1567 _cleanup_fclose_
FILE *f
= NULL
;
1568 _cleanup_kmod_module_unref_list_
struct kmod_list
*list
= NULL
;
1569 struct kmod_list
*l
;
1576 if (strncmp("modalias", ftsent
->fts_name
, 8) != 0)
1578 if (!(f
= fopen(ftsent
->fts_accpath
, "r")))
1581 if(!fgets(alias
, sizeof(alias
), f
))
1584 len
= strlen(alias
);
1589 if (alias
[len
-1] == '\n')
1592 err
= kmod_module_new_from_lookup(ctx
, alias
, &list
);
1596 kmod_list_foreach(l
, list
) {
1597 struct kmod_module
*mod
= kmod_module_get_module(l
);
1598 char *name
= strdup(kmod_module_get_name(mod
));
1599 kmod_module_unref(mod
);
1600 hashmap_put(modules_loaded
, name
, name
);
1604 err
= kmod_module_new_from_loaded(ctx
, &loaded_list
);
1607 log_error("Could not get list of loaded modules: %m. Switching to non-hostonly mode.");
1608 arg_hostonly
= false;
1610 kmod_list_foreach(itr
, loaded_list
) {
1611 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1613 struct kmod_module
*mod
= kmod_module_get_module(itr
);
1614 char *name
= strdup(kmod_module_get_name(mod
));
1615 hashmap_put(modules_loaded
, name
, name
);
1616 kmod_module_unref(mod
);
1618 /* also put the modules from the new kernel in the hashmap,
1619 * which resolve the name as an alias, in case a kernel module is
1622 err
= kmod_module_new_from_lookup(ctx
, name
, &modlist
);
1627 kmod_list_foreach(l
, modlist
) {
1628 mod
= kmod_module_get_module(l
);
1629 char *name
= strdup(kmod_module_get_name(mod
));
1630 hashmap_put(modules_loaded
, name
, name
);
1631 kmod_module_unref(mod
);
1634 kmod_module_unref_list(loaded_list
);
1639 static int install_modules(int argc
, char **argv
)
1641 _cleanup_kmod_unref_
struct kmod_ctx
*ctx
= NULL
;
1642 struct kmod_list
*itr
;
1644 struct kmod_module
*mod
= NULL
, *mod_o
= NULL
;
1646 const char *abskpath
= NULL
;
1651 ctx
= kmod_new(kerneldir
, NULL
);
1652 abskpath
= kmod_get_dirname(ctx
);
1654 p
= strstr(abskpath
, "/lib/modules/");
1656 kerneldirlen
= p
- abskpath
;
1659 char *modalias_file
;
1660 modalias_file
= getenv("DRACUT_KERNEL_MODALIASES");
1662 if (modalias_file
== NULL
) {
1665 _cleanup_fclose_
FILE *f
= NULL
;
1666 if ((f
= fopen(modalias_file
, "r"))) {
1671 char *dupname
= NULL
;
1673 if(!(fgets(name
, sizeof(name
), f
)))
1680 if (name
[len
-1] == '\n')
1683 log_debug("Adding module '%s' to hostonly module list", name
);
1684 dupname
= strdup(name
);
1685 hashmap_put(modules_loaded
, dupname
, dupname
);
1692 for (i
= 0; i
< argc
; i
++) {
1695 log_debug("Handle module '%s'", argv
[i
]);
1697 if (argv
[i
][0] == '/') {
1698 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1699 _cleanup_free_
const char *modname
= NULL
;
1701 r
= kmod_module_new_from_path(ctx
, argv
[i
], &mod_o
);
1703 log_debug("Failed to lookup modules path '%s': %m", argv
[i
]);
1708 /* Check, if we have to load another module with that name instead */
1709 modname
= strdup(kmod_module_get_name(mod_o
));
1712 if (!arg_optional
) {
1714 log_error("Failed to get name for module '%s'", argv
[i
]);
1717 log_info("Failed to get name for module '%s'", argv
[i
]);
1721 r
= kmod_module_new_from_lookup(ctx
, modname
, &modlist
);
1722 kmod_module_unref(mod_o
);
1726 if (!arg_optional
) {
1728 log_error("3 Failed to lookup alias '%s': %d", modname
, r
);
1731 log_info("3 Failed to lookup alias '%s': %d", modname
, r
);
1735 if (!arg_optional
) {
1737 log_error("Failed to find module '%s' %s", modname
, argv
[i
]);
1740 log_info("Failed to find module '%s' %s", modname
, argv
[i
]);
1743 kmod_list_foreach(itr
, modlist
) {
1744 mod
= kmod_module_get_module(itr
);
1745 r
= install_module(mod
);
1746 kmod_module_unref(mod
);
1747 if ((r
< 0) && !arg_optional
) {
1749 log_error("ERROR: installing module '%s'", modname
);
1752 ret
= ( ret
== 0 ? 0 : r
);
1755 } else if (argv
[i
][0] == '=') {
1756 _cleanup_free_
char *path1
= NULL
, *path2
= NULL
, *path3
= NULL
;
1757 _cleanup_fts_close_ FTS
*fts
= NULL
;
1759 log_debug("Handling =%s", &argv
[i
][1]);
1760 /* FIXME and add more paths*/
1761 r
= asprintf(&path2
, "%s/kernel/%s", kerneldir
, &argv
[i
][1]);
1763 log_error("Out of memory!");
1767 r
= asprintf(&path1
, "%s/extra/%s", kerneldir
, &argv
[i
][1]);
1769 log_error("Out of memory!");
1773 r
= asprintf(&path3
, "%s/updates/%s", kerneldir
, &argv
[i
][1]);
1775 log_error("Out of memory!");
1780 char *paths
[] = { path1
, path2
, path3
, NULL
};
1781 fts
= fts_open(paths
, FTS_COMFOLLOW
|FTS_NOCHDIR
|FTS_NOSTAT
|FTS_LOGICAL
, NULL
);
1784 for (FTSENT
*ftsent
= fts_read(fts
); ftsent
!= NULL
; ftsent
= fts_read(fts
)) {
1785 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1786 _cleanup_free_
const char *modname
= NULL
;
1788 if((ftsent
->fts_info
== FTS_D
) && !check_module_path(ftsent
->fts_accpath
)) {
1789 fts_set(fts
, ftsent
, FTS_SKIP
);
1790 log_debug("Skipping %s", ftsent
->fts_accpath
);
1793 if((ftsent
->fts_info
!= FTS_F
) && (ftsent
->fts_info
!= FTS_SL
)) {
1794 log_debug("Ignoring %s", ftsent
->fts_accpath
);
1797 log_debug("Handling %s", ftsent
->fts_accpath
);
1798 r
= kmod_module_new_from_path(ctx
, ftsent
->fts_accpath
, &mod_o
);
1800 log_debug("Failed to lookup modules path '%s': %m",
1801 ftsent
->fts_accpath
);
1802 if (!arg_optional
) {
1808 /* Check, if we have to load another module with that name instead */
1809 modname
= strdup(kmod_module_get_name(mod_o
));
1812 log_error("Failed to get name for module '%s'", ftsent
->fts_accpath
);
1813 if (!arg_optional
) {
1818 r
= kmod_module_new_from_lookup(ctx
, modname
, &modlist
);
1819 kmod_module_unref(mod_o
);
1823 log_error("Failed to lookup alias '%s': %m", modname
);
1824 if (!arg_optional
) {
1831 log_error("Failed to find module '%s' %s", modname
,
1832 ftsent
->fts_accpath
);
1833 if (!arg_optional
) {
1838 kmod_list_foreach(itr
, modlist
) {
1839 mod
= kmod_module_get_module(itr
);
1840 r
= install_module(mod
);
1841 kmod_module_unref(mod
);
1842 if ((r
< 0) && !arg_optional
) {
1844 log_error("ERROR: installing module '%s'", modname
);
1847 ret
= ( ret
== 0 ? 0 : r
);
1852 log_error("FTS ERROR: %m");
1855 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1856 char *modname
= argv
[i
];
1858 if (endswith(modname
, ".ko")) {
1859 int len
= strlen(modname
);
1862 if (endswith(modname
, ".ko.xz") || endswith(modname
, ".ko.gz")) {
1863 int len
= strlen(modname
);
1866 r
= kmod_module_new_from_lookup(ctx
, modname
, &modlist
);
1868 if (!arg_optional
) {
1870 log_error("Failed to lookup alias '%s': %m", modname
);
1873 log_info("Failed to lookup alias '%s': %m", modname
);
1877 if (!arg_optional
) {
1879 log_error("Failed to find module '%s'", modname
);
1882 log_info("Failed to find module '%s'", modname
);
1885 kmod_list_foreach(itr
, modlist
) {
1886 mod
= kmod_module_get_module(itr
);
1887 r
= install_module(mod
);
1888 kmod_module_unref(mod
);
1889 if ((r
< 0) && !arg_optional
) {
1891 log_error("ERROR: installing '%s'", argv
[i
]);
1894 ret
= ( ret
== 0 ? 0 : r
);
1899 if ((modinst
!= 0) && (ret
!= 0) && (!arg_optional
)) {
1901 log_error("ERROR: installing '%s'", argv
[i
]);
1902 return EXIT_FAILURE
;
1906 return EXIT_SUCCESS
;
1909 int main(int argc
, char **argv
)
1914 char *env_no_xattr
= NULL
;
1916 r
= parse_argv(argc
, argv
);
1918 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;
1920 log_set_target(LOG_TARGET_CONSOLE
);
1921 log_parse_environment();
1923 if (arg_loglevel
>= 0)
1924 log_set_max_level(arg_loglevel
);
1928 modules_loaded
= hashmap_new(string_hash_func
, string_compare_func
);
1932 _cleanup_kmod_unref_
struct kmod_ctx
*ctx
= NULL
;
1933 ctx
= kmod_new(kerneldir
, NULL
);
1936 HASHMAP_FOREACH(name
, modules_loaded
, i
) {
1937 printf("%s\n", name
);
1942 log_debug("Program arguments:");
1943 for (r
= 0; r
< argc
; r
++)
1944 log_debug("%s", argv
[r
]);
1946 path
= getenv("DRACUT_INSTALL_PATH");
1948 path
= getenv("PATH");
1951 log_error("PATH is not set");
1955 log_debug("PATH=%s", path
);
1957 ldd
= getenv("DRACUT_LDD");
1960 log_debug("LDD=%s", ldd
);
1962 env_no_xattr
= getenv("DRACUT_NO_XATTR");
1963 if (env_no_xattr
!= NULL
)
1966 pathdirs
= strv_split(path
, ":");
1970 if (destrootdir
== NULL
|| strlen(destrootdir
) == 0) {
1971 destrootdir
= getenv("DESTROOTDIR");
1972 if (destrootdir
== NULL
|| strlen(destrootdir
) == 0) {
1973 log_error("Environment DESTROOTDIR or argument -D is not set!");
1974 usage(EXIT_FAILURE
);
1976 destrootdir
= strdup(destrootdir
);
1979 if (strcmp(destrootdir
, "/") == 0) {
1980 log_error("Environment DESTROOTDIR or argument -D is set to '/'!");
1981 usage(EXIT_FAILURE
);
1985 destrootdir
= realpath(destrootdir
, NULL
);
1987 log_error("Environment DESTROOTDIR or argument -D is set to '%s': %m", i
);
1993 items
= hashmap_new(string_hash_func
, string_compare_func
);
1994 items_failed
= hashmap_new(string_hash_func
, string_compare_func
);
1996 if (!items
|| !items_failed
|| !modules_loaded
) {
1997 log_error("Out of memory");
2005 ret
= asprintf(&logfile
, "%s/%d.log", logdir
, getpid());
2007 log_error("Out of memory!");
2011 logfile_f
= fopen(logfile
, "a");
2012 if (logfile_f
== NULL
) {
2013 log_error("Could not open %s for logging: %m", logfile
);
2021 if (((optind
+ 1) < argc
) && (strcmp(argv
[optind
+ 1], destrootdir
) == 0)) {
2022 /* ugly hack for compat mode "inst src $destrootdir" */
2023 if ((optind
+ 2) == argc
) {
2026 /* ugly hack for compat mode "inst src $destrootdir dst" */
2027 if ((optind
+ 3) == argc
) {
2029 argv
[optind
+ 1] = argv
[optind
+ 2];
2035 r
= install_modules(argc
- optind
, &argv
[optind
]);
2036 } else if (arg_resolvelazy
) {
2037 r
= resolve_lazy(argc
- optind
, &argv
[optind
]);
2038 } else if (arg_all
|| (argc
- optind
> 2) || ((argc
- optind
) == 1)) {
2039 r
= install_all(argc
- optind
, &argv
[optind
]);
2041 /* simple "inst src dst" */
2042 r
= install_one(argv
[optind
], argv
[optind
+ 1]);
2052 while ((i
= hashmap_steal_first(modules_loaded
)))
2055 while ((i
= hashmap_steal_first(items
)))
2058 while ((i
= hashmap_steal_first(items_failed
)))
2061 hashmap_free(items
);
2062 hashmap_free(items_failed
);
2063 hashmap_free(modules_loaded
);
2066 strv_free(firmwaredirs
);
2067 strv_free(pathdirs
);