Compare commits

3 Commits

Author SHA1 Message Date
jane400
20ba9e4131 misc: also check wheter binaries from /{s,}bin are /usr
This should hopefully avoid failing to build the initramfs
when important binaries like /bin/busybox get moved to /usr.

Also complain loudly when there's a path mismatch, so people notice
it.
2025-02-04 15:07:16 +01:00
Clayton Craft
e5f14d70a6 doc: add archive compression formats/levels (MR 50)
fixes #28
2024-03-20 10:08:18 -07:00
Stefan Hansson
dd5cdeace5 misc: Also check for .zst-compressed variants of files (MR 49)
Initially I thought of breaking off the Stat + error check call into its
own function as to reduce repetition, but given that it's only useful in
this situation where it only happens twice anyway, I'm not sure it
actually would reduce complexity.

Additionally, this means that .zst-compressed variants of files will be
searched for in all contexts where this function is used. I'm not sure
this is desirable.

Tested and works with arrow-db820c. I didn't test it on actual hardware,
but I verified that the firmware ended up in the initramfs via
$ pmbootstrap initfs ls. I choose this device because it uses firmware
from linux-firmware and also needs said firmware present in the
initramfs.

Closes https://gitlab.com/postmarketOS/postmarketos-mkinitfs/-/issues/39
2024-03-14 12:01:48 -07:00
2 changed files with 93 additions and 17 deletions

View File

@@ -54,6 +54,36 @@ a bare minimum, and to require only variables that don't hold lists of things.
necessary tools to extract the configured archive format are in the initramfs necessary tools to extract the configured archive format are in the initramfs
archive. archive.
# ARCHIVE COMPRESSION
Archive compression parameters are specified in the
*deviceinfo_initfs_compression* and *deviceinfo_initfs_extra_compression*
deviceinfo variables. Their values do not have to match, but special
consideration should be taken since some formats may require additional kernel
options or tools in the initramfs to support it.
Supported compression *formats* for mkinitfs are:
- gzip
- lz4
- lzma
- none
- zstd
Supported compression *levels* for mkinitfs:
- best
- default
- fast
The value of these variables follows this syntax: *<format>:<level>*. For
example, *zstd* with the *fast* compression level would be:
*deviceinfo_initfs_compression="zstd:fast"*
Defaults to *gzip* and *default* for both archives if format and/or level is
unsupported or omitted.
# DIRECTORIES # DIRECTORIES
The following directories are used by mkinitfs to generate the initramfs and The following directories are used by mkinitfs to generate the initramfs and

View File

@@ -5,6 +5,8 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"log"
"gitlab.com/postmarketOS/postmarketos-mkinitfs/internal/osutil" "gitlab.com/postmarketOS/postmarketos-mkinitfs/internal/osutil"
) )
@@ -22,30 +24,54 @@ func GetFiles(list []string, required bool) (files []string, err error) {
return return
} }
func getFile(file string, required bool) (files []string, err error) { // This function doesn't handle globs, use getFile() instead.
// Expand glob expression func getFileNormalized(file string, required bool) (files []string, err error) {
expanded, err := filepath.Glob(file) fileInfo, err := os.Stat(file)
// Trying some fallbacks...
if err != nil { if err != nil {
return type triedResult struct {
} file string
if len(expanded) > 0 && expanded[0] != file { err error
for _, path := range expanded {
if globFiles, err := getFile(path, required); err != nil {
return files, err
} else {
files = append(files, globFiles...)
}
}
return RemoveDuplicates(files), nil
} }
fileInfo, err := os.Stat(file) triedFiles := make([]triedResult, 0, 1)
if err != nil {
if required { // Temporary fallback until alpine/pmOS usr-merge happened
return files, fmt.Errorf("getFile: failed to stat file %q: %w", file, err) // If a path starts with /bin or /sbin, also try /usr equivalent before giving up
if strings.HasPrefix(file, "/bin/") || strings.HasPrefix(file, "/sbin/") {
fileUsr := filepath.Join("/usr", file)
_, err := os.Stat(fileUsr);
if err == nil {
log.Printf("getFile: failed to find %q, but found it in %q. Please adjust the path.", file, fileUsr)
return getFileNormalized(fileUsr, required)
} else {
triedFiles = append(triedFiles, triedResult{fileUsr, err})
} }
}
{
// Check if there is a Zstd-compressed version of the file
fileZstd := file + ".zst" // .zst is the extension used by linux-firmware
_, err := os.Stat(fileZstd);
if err == nil {
return getFileNormalized(fileZstd, required)
} else {
triedFiles = append(triedFiles, triedResult{fileZstd, err})
}
}
// Failed to find anything
if required {
failStrings := make([]string, 0, 2)
for _, result := range triedFiles {
failStrings = append(failStrings, fmt.Sprintf("\n - also tried %q: %v", result.file, result.err))
}
return files, fmt.Errorf("getFile: failed to stat file %q: %v%q", file, err, strings.Join(failStrings, ""))
} else {
return files, nil return files, nil
} }
}
if fileInfo.IsDir() { if fileInfo.IsDir() {
// Recurse over directory contents // Recurse over directory contents
@@ -83,6 +109,26 @@ func getFile(file string, required bool) (files []string, err error) {
return return
} }
func getFile(file string, required bool) (files []string, err error) {
// Expand glob expression
expanded, err := filepath.Glob(file)
if err != nil {
return
}
if len(expanded) > 0 && expanded[0] != file {
for _, path := range expanded {
if globFiles, err := getFile(path, required); err != nil {
return files, err
} else {
files = append(files, globFiles...)
}
}
return RemoveDuplicates(files), nil
}
return getFileNormalized(file, required)
}
func getDeps(file string, parents map[string]struct{}) (files []string, err error) { func getDeps(file string, parents map[string]struct{}) (files []string, err error) {
if _, found := parents[file]; found { if _, found := parents[file]; found {