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
;
692 parent
= strdup(src
);
696 parent
[dir_len(parent
)] = '\0';
698 if (stat(parent
, &sb
) == 0) {
699 if (!S_ISDIR(sb
.st_mode
)) {
700 log_error("%s exists but is not a directory!", parent
);
704 return mkdir(src
, 0755);
707 if (errno
!= ENOENT
) {
708 log_error("ERROR: stat '%s': %m", src
);
712 return dracut_mkdir(parent
);
715 static int dracut_install(const char *orig_src
, const char *orig_dst
, bool isdir
, bool resolvedeps
, bool hashdst
)
718 _cleanup_free_
char *fullsrcpath
= NULL
;
719 _cleanup_free_
char *fulldstpath
= NULL
;
720 _cleanup_free_
char *fulldstdir
= NULL
;
722 bool src_islink
= false;
723 bool src_isdir
= false;
725 bool dst_exists
= true;
727 _cleanup_free_
char *src
;
728 _cleanup_free_
char *dst
;
731 if (strncmp(orig_src
, sysrootdir
, sysrootdirlen
) == 0) {
732 src
= strdup(orig_src
+ sysrootdirlen
);
733 fullsrcpath
= strdup(orig_src
);
735 src
= strdup(orig_src
);
736 if (asprintf(&fullsrcpath
, "%s%s", sysrootdir
, src
) < 0)
739 if (strncmp(orig_dst
, sysrootdir
, sysrootdirlen
) == 0)
740 dst
= strdup(orig_dst
+ sysrootdirlen
);
742 dst
= strdup(orig_dst
);
744 src
= strdup(orig_src
);
745 fullsrcpath
= strdup(src
);
746 dst
= strdup(orig_dst
);
749 log_debug("dracut_install('%s', '%s', %d, %d, %d)", src
, dst
, isdir
, resolvedeps
, hashdst
);
751 if (check_hashmap(items_failed
, src
)) {
752 log_debug("hash hit items_failed for '%s'", src
);
756 if (hashdst
&& check_hashmap(items
, dst
)) {
757 log_debug("hash hit items for '%s'", dst
);
761 if (lstat(fullsrcpath
, &sb
) < 0) {
764 hashmap_put(items_failed
, i
, i
);
765 /* src does not exist */
769 src_islink
= S_ISLNK(sb
.st_mode
);
770 src_isdir
= S_ISDIR(sb
.st_mode
);
771 src_mode
= sb
.st_mode
;
774 ret
= asprintf(&fulldstpath
, "%s/%s", destrootdir
, (dst
[0]=='/' ? (dst
+1) : dst
));
776 log_error("Out of memory!");
780 ret
= stat(fulldstpath
, &sb
);
784 if (errno
!= ENOENT
) {
785 log_error("ERROR: stat '%s': %m", fulldstpath
);
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
);
795 log_debug("'%s' already exists", fulldstpath
);
797 /* dst does already exist */
801 /* check destination directory */
802 fulldstdir
= strdup(fulldstpath
);
804 log_error("Out of memory!");
807 fulldstdir
[dir_len(fulldstdir
)] = '\0';
809 ret
= stat(fulldstdir
, &db
);
812 _cleanup_free_
char *dname
= NULL
;
814 if (errno
!= ENOENT
) {
815 log_error("ERROR: stat '%s': %m", fulldstdir
);
818 /* create destination directory */
819 log_debug("dest dir '%s' does not exist", fulldstdir
);
824 dname
[dir_len(dname
)] = '\0';
825 ret
= dracut_install(dname
, dname
, true, false, true);
828 log_error("ERROR: failed to create directory '%s'", fulldstdir
);
835 if (S_ISDIR(sb
.st_mode
)) {
836 log_debug("dest dir '%s' already exists", fulldstpath
);
839 log_error("dest dir '%s' already exists but is not a directory", fulldstpath
);
843 log_info("mkdir '%s'", fulldstpath
);
844 ret
= dracut_mkdir(fulldstpath
);
850 hashmap_put(items
, i
, i
);
855 /* ready to install src */
858 _cleanup_free_
char *abspath
= NULL
;
860 abspath
= get_real_file(src
, false);
865 if (dracut_install(abspath
, abspath
, false, resolvedeps
, hashdst
)) {
866 log_debug("'%s' install error", abspath
);
870 if (lstat(abspath
, &sb
) != 0) {
871 log_debug("lstat '%s': %m", abspath
);
875 if (lstat(fulldstpath
, &sb
) != 0) {
876 _cleanup_free_
char *absdestpath
= NULL
;
878 ret
= asprintf(&absdestpath
, "%s/%s", destrootdir
, (abspath
[0]=='/' ? (abspath
+1) : abspath
) + sysrootdirlen
);
880 log_error("Out of memory!");
884 ln_r(absdestpath
, fulldstpath
);
888 /* copy .hmac files also */
889 hmac_install(src
, dst
, NULL
);
895 if (src_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
897 ret
+= resolve_deps(fullsrcpath
+ sysrootdirlen
);
899 /* copy .hmac files also */
900 hmac_install(src
, dst
, NULL
);
904 log_debug("dracut_install ret = %d", ret
);
906 if (arg_hostonly
&& !arg_module
)
910 log_info("mkdir '%s'", fulldstpath
);
911 ret
+= dracut_mkdir(fulldstpath
);
913 log_info("cp '%s' '%s'", fullsrcpath
, fulldstpath
);
914 ret
+= cp(fullsrcpath
, fulldstpath
);
922 hashmap_put(items
, i
, i
);
928 log_debug("dracut_install ret = %d", ret
);
933 static void item_free(char *i
)
939 static void usage(int status
)
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"
946 "Install SOURCE (from rootfs or SYSROOTDIR) to DEST in DESTROOTDIR with all needed dependencies.\n"
948 " KERNELMODULE can have the format:\n"
949 " <absolute path> with a leading /\n"
950 " =<kernel subdir>[/<kernel subdir>…] like '=drivers/hid'\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"
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"
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"
982 program_invocation_short_name
, program_invocation_short_name
,
983 program_invocation_short_name
);
987 static int parse_argv(int argc
, char *argv
[])
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
},
1028 while ((c
= getopt_long(argc
, argv
, "madfhlL:oD:Hr:Rp:P:s:S:N:v", options
, NULL
)) != -1) {
1031 puts(PROGRAM_VERSION_STRING
);
1034 arg_createdir
= true;
1037 arg_loglevel
= LOG_DEBUG
;
1043 arg_modalias
= true;
1047 arg_loglevel
= LOG_INFO
;
1050 arg_optional
= true;
1053 arg_resolvedeps
= true;
1056 arg_resolvelazy
= true;
1065 destrootdir
= strdup(optarg
);
1068 sysrootdir
= strdup(optarg
);
1069 sysrootdirlen
= strlen(sysrootdir
);
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
);
1076 arg_mod_filter_path
= true;
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
);
1083 arg_mod_filter_nopath
= true;
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
);
1090 arg_mod_filter_symbol
= true;
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
);
1097 arg_mod_filter_nosymbol
= true;
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
);
1104 arg_mod_filter_noname
= true;
1107 logdir
= strdup(optarg
);
1110 kerneldir
= strdup(optarg
);
1112 case ARG_FIRMWAREDIRS
:
1113 firmwaredirs
= strv_split(optarg
, ":");
1119 arg_hostonly
= true;
1122 usage(EXIT_SUCCESS
);
1125 usage(EXIT_FAILURE
);
1132 kerneldir
= strdup(buf
.version
);
1140 if (!firmwaredirs
) {
1143 path
= getenv("DRACUT_FIRMWARE_PATH");
1146 log_error("Environment variable DRACUT_FIRMWARE_PATH is not set");
1150 log_debug("DRACUT_FIRMWARE_PATH=%s", path
);
1152 firmwaredirs
= strv_split(path
, ":");
1156 if (!optind
|| optind
== argc
) {
1157 log_error("No SOURCE argument given");
1158 usage(EXIT_FAILURE
);
1164 static int resolve_lazy(int argc
, char **argv
)
1167 size_t destrootdirlen
= strlen(destrootdir
);
1170 for (i
= 0; i
< argc
; i
++) {
1171 const char *src
= argv
[i
];
1175 log_debug("resolve_deps('%s')", src
);
1177 if (strstr(src
, destrootdir
)) {
1178 p
= &argv
[i
][destrootdirlen
];
1181 existing
= hashmap_get(items
, p
);
1183 if (strcmp(existing
, p
) == 0)
1188 hashmap_put(items
, item
, item
);
1190 ret
+= resolve_deps(src
);
1195 static char **find_binary(const char *src
)
1200 char *newsrc
= NULL
;
1202 STRV_FOREACH(q
, pathdirs
) {
1206 r
= asprintf(&newsrc
, "%s/%s", *q
, src
);
1208 log_error("Out of memory!");
1212 fullsrcpath
= get_real_file(newsrc
, false);
1215 log_debug("get_real_file(%s) not found", newsrc
);
1221 if (lstat(fullsrcpath
, &sb
) != 0) {
1222 log_debug("stat(%s) != 0", fullsrcpath
);
1230 strv_push(&ret
, newsrc
);
1237 STRV_FOREACH(q
, ret
) {
1238 log_debug("find_binary(%s) == %s", src
, *q
);
1245 static int install_one(const char *src
, const char *dst
)
1247 int r
= EXIT_SUCCESS
;
1250 if (strchr(src
, '/') == NULL
) {
1251 char **p
= find_binary(src
);
1254 STRV_FOREACH(q
, p
) {
1256 log_debug("dracut_install '%s' '%s'", newsrc
, dst
);
1257 ret
= dracut_install(newsrc
, dst
, arg_createdir
, arg_resolvedeps
, true);
1259 log_debug("dracut_install '%s' '%s' OK", newsrc
, dst
);
1267 ret
= dracut_install(src
, dst
, arg_createdir
, arg_resolvedeps
, true);
1270 if ((ret
!= 0) && (!arg_optional
)) {
1271 log_error("ERROR: installing '%s' to '%s'", src
, dst
);
1278 static int install_all(int argc
, char **argv
)
1280 int r
= EXIT_SUCCESS
;
1282 for (i
= 0; i
< argc
; i
++) {
1284 log_debug("Handle '%s'", argv
[i
]);
1286 if (strchr(argv
[i
], '/') == NULL
) {
1287 char **p
= find_binary(argv
[i
]);
1290 STRV_FOREACH(q
, p
) {
1292 log_debug("dracut_install '%s'", newsrc
);
1293 ret
= dracut_install(newsrc
, newsrc
, arg_createdir
, arg_resolvedeps
, true);
1295 log_debug("dracut_install '%s' OK", newsrc
);
1304 _cleanup_free_
char *dest
= strdup(argv
[i
]);
1305 ret
= dracut_install(argv
[i
], dest
, arg_createdir
, arg_resolvedeps
, true);
1308 if ((ret
!= 0) && (!arg_optional
)) {
1309 log_error("ERROR: installing '%s'", argv
[i
]);
1316 static int install_firmware(struct kmod_module
*mod
)
1318 struct kmod_list
*l
;
1319 _cleanup_kmod_module_info_free_list_
struct kmod_list
*list
= NULL
;
1324 ret
= kmod_module_get_info(mod
, &list
);
1326 log_error("could not get modinfo from '%s': %s\n",
1327 kmod_module_get_name(mod
), strerror(-ret
));
1330 kmod_list_foreach(l
, list
) {
1331 const char *key
= kmod_module_info_get_key(l
);
1332 const char *value
= NULL
;
1334 if (!streq("firmware", key
))
1337 value
= kmod_module_info_get_value(l
);
1338 log_debug("Firmware %s", value
);
1340 STRV_FOREACH(q
, firmwaredirs
) {
1341 _cleanup_free_
char *fwpath
= NULL
;
1342 _cleanup_free_
char *fwpath_xz
= NULL
;
1347 r
= asprintf(&fwpath
, "%s/%s", *q
, value
);
1349 log_error("Out of memory!");
1354 if (stat(fwpath
, &sb
) != 0) {
1355 r
= asprintf(&fwpath_xz
, "%s.xz", fwpath
);
1357 log_error("Out of memory!");
1360 if (stat(fwpath_xz
, &sb
) != 0) {
1361 log_debug("stat(%s) != 0", fwpath
);
1367 ret
= dracut_install(fw
, fw
, false, false, true);
1369 log_debug("dracut_install '%s' OK", fwpath
);
1373 log_info("Possible missing firmware %s for kernel module %s", value
, kmod_module_get_name(mod
));
1379 static bool check_module_symbols(struct kmod_module
*mod
)
1381 struct kmod_list
*itr
;
1382 _cleanup_kmod_module_dependency_symbols_free_list_
struct kmod_list
*deplist
= NULL
;
1384 if (!arg_mod_filter_symbol
&& !arg_mod_filter_nosymbol
)
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
)
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
);
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
);
1420 static bool check_module_path(const char *path
)
1422 if (arg_mod_filter_nopath
&& (regexec(&mod_filter_nopath
, path
, 0, NULL
, 0) == 0)) {
1423 log_debug("Path %s matched exclusion filter", path
);
1427 if (arg_mod_filter_path
&& (regexec(&mod_filter_path
, path
, 0, NULL
, 0) != 0)) {
1428 log_debug("Path %s matched inclusion filter", path
);
1434 static int install_dependent_modules(struct kmod_list
*modlist
)
1436 struct kmod_list
*itr
;
1437 const char *path
= NULL
;
1438 const char *name
= NULL
;
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
);
1449 if (check_hashmap(items_failed
, path
))
1452 if (check_hashmap(items
, path
)) {
1456 name
= kmod_module_get_name(mod
);
1458 if (arg_mod_filter_noname
&& (regexec(&mod_filter_noname
, name
, 0, NULL
, 0) == 0)) {
1462 ret
= dracut_install(path
, &path
[kerneldirlen
], false, false, true);
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
);
1472 ret
= kmod_module_get_softdeps(mod
, &modpre
, &modpost
);
1474 ret
= install_dependent_modules(modpre
);
1477 log_error("dracut_install '%s' '%s' ERROR", path
, &path
[kerneldirlen
]);
1484 static int install_module(struct kmod_module
*mod
)
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
;
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
);
1499 if (arg_hostonly
&& !check_hashmap(modules_loaded
, name
)) {
1500 log_debug("dracut_install '%s' not hostonly", name
);
1504 path
= kmod_module_get_path(mod
);
1508 if (check_hashmap(items_failed
, path
))
1511 if (check_hashmap(items
, path
))
1514 if (!check_module_path(path
) || !check_module_symbols(mod
)) {
1515 log_debug("No symbol or path match for '%s'", path
);
1519 log_debug("dracut_install '%s' '%s'", path
, &path
[kerneldirlen
]);
1521 ret
= dracut_install(path
, &path
[kerneldirlen
], false, false, true);
1523 log_debug("dracut_install '%s' OK", kmod_module_get_name(mod
));
1524 } else if (!arg_optional
) {
1526 log_error("dracut_install '%s' ERROR", kmod_module_get_name(mod
));
1529 install_firmware(mod
);
1531 modlist
= kmod_module_get_dependencies(mod
);
1532 ret
= install_dependent_modules(modlist
);
1535 ret
= kmod_module_get_softdeps(mod
, &modpre
, &modpost
);
1537 ret
= install_dependent_modules(modpre
);
1543 static int modalias_list(struct kmod_ctx
*ctx
)
1546 struct kmod_list
*loaded_list
= NULL
;
1547 struct kmod_list
*itr
, *l
;
1548 _cleanup_fts_close_ FTS
*fts
= NULL
;
1551 char *paths
[] = { "/sys/devices", NULL
};
1552 fts
= fts_open(paths
, FTS_NOCHDIR
|FTS_NOSTAT
, NULL
);
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
;
1564 if (strncmp("modalias", ftsent
->fts_name
, 8) != 0)
1566 if (!(f
= fopen(ftsent
->fts_accpath
, "r")))
1569 if(!fgets(alias
, sizeof(alias
), f
))
1572 len
= strlen(alias
);
1577 if (alias
[len
-1] == '\n')
1580 err
= kmod_module_new_from_lookup(ctx
, alias
, &list
);
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
);
1592 err
= kmod_module_new_from_loaded(ctx
, &loaded_list
);
1595 log_error("Could not get list of loaded modules: %m. Switching to non-hostonly mode.");
1596 arg_hostonly
= false;
1598 kmod_list_foreach(itr
, loaded_list
) {
1599 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
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
);
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
1610 err
= kmod_module_new_from_lookup(ctx
, name
, &modlist
);
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
);
1622 kmod_module_unref_list(loaded_list
);
1627 static int install_modules(int argc
, char **argv
)
1629 _cleanup_kmod_unref_
struct kmod_ctx
*ctx
= NULL
;
1630 struct kmod_list
*itr
;
1632 struct kmod_module
*mod
= NULL
, *mod_o
= NULL
;
1634 const char *abskpath
= NULL
;
1639 ctx
= kmod_new(kerneldir
, NULL
);
1640 abskpath
= kmod_get_dirname(ctx
);
1642 p
= strstr(abskpath
, "/lib/modules/");
1644 kerneldirlen
= p
- abskpath
;
1647 char *modalias_file
;
1648 modalias_file
= getenv("DRACUT_KERNEL_MODALIASES");
1650 if (modalias_file
== NULL
) {
1653 _cleanup_fclose_
FILE *f
= NULL
;
1654 if ((f
= fopen(modalias_file
, "r"))) {
1659 char *dupname
= NULL
;
1661 if(!(fgets(name
, sizeof(name
), f
)))
1668 if (name
[len
-1] == '\n')
1671 log_debug("Adding module '%s' to hostonly module list", name
);
1672 dupname
= strdup(name
);
1673 hashmap_put(modules_loaded
, dupname
, dupname
);
1680 for (i
= 0; i
< argc
; i
++) {
1683 log_debug("Handle module '%s'", argv
[i
]);
1685 if (argv
[i
][0] == '/') {
1686 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1687 _cleanup_free_
const char *modname
= NULL
;
1689 r
= kmod_module_new_from_path(ctx
, argv
[i
], &mod_o
);
1691 log_debug("Failed to lookup modules path '%s': %m", argv
[i
]);
1696 /* Check, if we have to load another module with that name instead */
1697 modname
= strdup(kmod_module_get_name(mod_o
));
1700 if (!arg_optional
) {
1702 log_error("Failed to get name for module '%s'", argv
[i
]);
1705 log_info("Failed to get name for module '%s'", argv
[i
]);
1709 r
= kmod_module_new_from_lookup(ctx
, modname
, &modlist
);
1710 kmod_module_unref(mod_o
);
1714 if (!arg_optional
) {
1716 log_error("3 Failed to lookup alias '%s': %d", modname
, r
);
1719 log_info("3 Failed to lookup alias '%s': %d", modname
, r
);
1723 if (!arg_optional
) {
1725 log_error("Failed to find module '%s' %s", modname
, argv
[i
]);
1728 log_info("Failed to find module '%s' %s", modname
, argv
[i
]);
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
) {
1737 log_error("ERROR: installing module '%s'", modname
);
1740 ret
= ( ret
== 0 ? 0 : r
);
1743 } else if (argv
[i
][0] == '=') {
1744 _cleanup_free_
char *path1
= NULL
, *path2
= NULL
, *path3
= NULL
;
1745 _cleanup_fts_close_ FTS
*fts
= NULL
;
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]);
1751 log_error("Out of memory!");
1755 r
= asprintf(&path1
, "%s/extra/%s", kerneldir
, &argv
[i
][1]);
1757 log_error("Out of memory!");
1761 r
= asprintf(&path3
, "%s/updates/%s", kerneldir
, &argv
[i
][1]);
1763 log_error("Out of memory!");
1768 char *paths
[] = { path1
, path2
, path3
, NULL
};
1769 fts
= fts_open(paths
, FTS_COMFOLLOW
|FTS_NOCHDIR
|FTS_NOSTAT
|FTS_LOGICAL
, NULL
);
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
;
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
);
1781 if((ftsent
->fts_info
!= FTS_F
) && (ftsent
->fts_info
!= FTS_SL
)) {
1782 log_debug("Ignoring %s", ftsent
->fts_accpath
);
1785 log_debug("Handling %s", ftsent
->fts_accpath
);
1786 r
= kmod_module_new_from_path(ctx
, ftsent
->fts_accpath
, &mod_o
);
1788 log_debug("Failed to lookup modules path '%s': %m",
1789 ftsent
->fts_accpath
);
1790 if (!arg_optional
) {
1796 /* Check, if we have to load another module with that name instead */
1797 modname
= strdup(kmod_module_get_name(mod_o
));
1800 log_error("Failed to get name for module '%s'", ftsent
->fts_accpath
);
1801 if (!arg_optional
) {
1806 r
= kmod_module_new_from_lookup(ctx
, modname
, &modlist
);
1807 kmod_module_unref(mod_o
);
1811 log_error("Failed to lookup alias '%s': %m", modname
);
1812 if (!arg_optional
) {
1819 log_error("Failed to find module '%s' %s", modname
,
1820 ftsent
->fts_accpath
);
1821 if (!arg_optional
) {
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
) {
1832 log_error("ERROR: installing module '%s'", modname
);
1835 ret
= ( ret
== 0 ? 0 : r
);
1840 log_error("FTS ERROR: %m");
1843 _cleanup_kmod_module_unref_list_
struct kmod_list
*modlist
= NULL
;
1844 char *modname
= argv
[i
];
1846 if (endswith(modname
, ".ko")) {
1847 int len
= strlen(modname
);
1850 if (endswith(modname
, ".ko.xz") || endswith(modname
, ".ko.gz")) {
1851 int len
= strlen(modname
);
1854 r
= kmod_module_new_from_lookup(ctx
, modname
, &modlist
);
1856 if (!arg_optional
) {
1858 log_error("Failed to lookup alias '%s': %m", modname
);
1861 log_info("Failed to lookup alias '%s': %m", modname
);
1865 if (!arg_optional
) {
1867 log_error("Failed to find module '%s'", modname
);
1870 log_info("Failed to find module '%s'", modname
);
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
) {
1879 log_error("ERROR: installing '%s'", argv
[i
]);
1882 ret
= ( ret
== 0 ? 0 : r
);
1887 if ((modinst
!= 0) && (ret
!= 0) && (!arg_optional
)) {
1889 log_error("ERROR: installing '%s'", argv
[i
]);
1890 return EXIT_FAILURE
;
1894 return EXIT_SUCCESS
;
1897 int main(int argc
, char **argv
)
1902 char *env_no_xattr
= NULL
;
1904 r
= parse_argv(argc
, argv
);
1906 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;
1908 log_set_target(LOG_TARGET_CONSOLE
);
1909 log_parse_environment();
1911 if (arg_loglevel
>= 0)
1912 log_set_max_level(arg_loglevel
);
1916 modules_loaded
= hashmap_new(string_hash_func
, string_compare_func
);
1920 _cleanup_kmod_unref_
struct kmod_ctx
*ctx
= NULL
;
1921 ctx
= kmod_new(kerneldir
, NULL
);
1924 HASHMAP_FOREACH(name
, modules_loaded
, i
) {
1925 printf("%s\n", name
);
1930 log_debug("Program arguments:");
1931 for (r
= 0; r
< argc
; r
++)
1932 log_debug("%s", argv
[r
]);
1934 path
= getenv("DRACUT_INSTALL_PATH");
1936 path
= getenv("PATH");
1939 log_error("PATH is not set");
1943 log_debug("PATH=%s", path
);
1945 ldd
= getenv("DRACUT_LDD");
1948 log_debug("LDD=%s", ldd
);
1950 env_no_xattr
= getenv("DRACUT_NO_XATTR");
1951 if (env_no_xattr
!= NULL
)
1954 pathdirs
= strv_split(path
, ":");
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
);
1964 destrootdir
= strdup(destrootdir
);
1967 if (strcmp(destrootdir
, "/") == 0) {
1968 log_error("Environment DESTROOTDIR or argument -D is set to '/'!");
1969 usage(EXIT_FAILURE
);
1973 destrootdir
= realpath(destrootdir
, NULL
);
1975 log_error("Environment DESTROOTDIR or argument -D is set to '%s': %m", i
);
1981 items
= hashmap_new(string_hash_func
, string_compare_func
);
1982 items_failed
= hashmap_new(string_hash_func
, string_compare_func
);
1984 if (!items
|| !items_failed
|| !modules_loaded
) {
1985 log_error("Out of memory");
1993 ret
= asprintf(&logfile
, "%s/%d.log", logdir
, getpid());
1995 log_error("Out of memory!");
1999 logfile_f
= fopen(logfile
, "a");
2000 if (logfile_f
== NULL
) {
2001 log_error("Could not open %s for logging: %m", logfile
);
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
) {
2014 /* ugly hack for compat mode "inst src $destrootdir dst" */
2015 if ((optind
+ 3) == argc
) {
2017 argv
[optind
+ 1] = argv
[optind
+ 2];
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
]);
2029 /* simple "inst src dst" */
2030 r
= install_one(argv
[optind
], argv
[optind
+ 1]);
2040 while ((i
= hashmap_steal_first(modules_loaded
)))
2043 while ((i
= hashmap_steal_first(items
)))
2046 while ((i
= hashmap_steal_first(items_failed
)))
2049 hashmap_free(items
);
2050 hashmap_free(items_failed
);
2051 hashmap_free(modules_loaded
);
2054 strv_free(firmwaredirs
);
2055 strv_free(pathdirs
);