14 Commits

Author SHA1 Message Date
Caleb Connolly
b54044a605 hookscripts: glob hook directories 2023-04-18 17:53:37 +01:00
Caleb Connolly
f0544999db filelist/hookfiles: encapsulate dir searching out of slurpFiles
Move the directory searching / globbing code out of slurpFiles and into
the filelist module so it can be used elsewhere.
2023-04-07 02:56:38 +01:00
Clayton Craft
8fac3004a6 archive: fix up documentation for AddItems 2023-03-19 23:14:18 -07:00
Clayton Craft
a15a3ad781 filelist/modules: don't print "skipping..." when dir not found
I think this was still causing some confusion, since it *might* look
like a failure when in reality it's not. I think it's important that
mkinitfs prints when it is adding something, and doesn't print when it
is *not* adding something, so that it should be clear if something
expected is missing and when something unexpected is included... without
having to sort out which is which every time the output is read.
2023-03-19 23:06:09 -07:00
Clayton Craft
1e8580a0a1 archive: New() can't fail, so don't return an error type
It could fail if the system can't allocate memory or something
undeterministic like that, but in that case it's best to just let the
runtime panic.
2023-03-19 22:05:55 -07:00
Clayton Craft
e6ee43826d doc/mkinitfs: add section on boot-deploy 2023-03-19 16:36:11 -07:00
Clayton Craft
7bdd68800d doc/mkinitfs.1: add design goals 2023-03-19 16:35:51 -07:00
Clayton Craft
80098d29c6 misc:TimeFunc: reduce printed time precision
Now:
        10:57:41.737665 initramfs-extra completed in: 0.33s
        ...
        10:57:42.008587 boot-deploy completed in: 0.27s
        10:57:42.012973 mkinitfs completed in: 0.90s

Times is just truncated, not rounding, since it's simpler (no dependency
on the math module), and I'm not sure if anyone cares for what this
function prints. If there is a desire to return to higher precision
later, it could be enabled by a new flag.

fixes https://gitlab.com/postmarketOS/postmarketos-mkinitfs/-/issues/25
2023-03-13 11:03:48 -07:00
Clayton Craft
67f1839ddc filelist/modules: fix order of struct items to reduce memory
Another one found by fieldalignment:
        modules.go:18:14: struct with 32 pointer bytes could be 24

Probably not going to matter much... but let's just get rid of the
warning.
2023-03-12 20:39:01 -07:00
Clayton Craft
baf76ed614 archive: fix order of struct items to reduce memory usage
Found by fieldalignment:
        archive.go:46:14: struct with 88 pointer bytes could be 56
        archive.go:66:18: struct with 24 pointer bytes could be 16

The first one probably doesn't matter that much, there's only like 2 of
those objects that are instantiated at runtime. However, there are many
ArchiveItems (hundreds or more depending on the archives compositions)
2023-03-12 20:37:10 -07:00
Clayton Craft
27e271b904 filelist/modules: print a message when including modules from deviceinfo
fixes https://gitlab.com/postmarketOS/postmarketos-mkinitfs/-/issues/24
2023-03-12 20:36:29 -07:00
Clayton Craft
1ac85b12fe filelist/modules: print search dir before searching dir
This will allow printing status for deviceinfo modules earlier in the
function, in a way that makes more sense.
2023-03-12 20:36:24 -07:00
Clayton Craft
f7f42bc2d4 filelist/modules: handle errors from filepath.Walk 2023-03-12 20:18:51 -07:00
Clayton Craft
c62a1f9ddb filelist/modules: remove outdated reference in error message 2023-03-12 20:05:55 -07:00
8 changed files with 100 additions and 43 deletions

View File

@@ -152,10 +152,7 @@ func generateArchive(name string, format archive.CompressFormat, level archive.C
log.Printf("- Using compression format %s with level %q\n", format, level) log.Printf("- Using compression format %s with level %q\n", format, level)
defer misc.TimeFunc(time.Now(), name) defer misc.TimeFunc(time.Now(), name)
a, err := archive.New(format, level) a := archive.New(format, level)
if err != nil {
return err
}
fs := initramfs.New(features) fs := initramfs.New(features)
if err := a.AddItems(fs); err != nil { if err := a.AddItems(fs); err != nil {

View File

@@ -24,6 +24,15 @@ is purely to generate the archive(s). mkinitfs does call *boot-deploy* after
creating the archive(s), in order to install/deploy them and any other relevant creating the archive(s), in order to install/deploy them and any other relevant
boot-related items onto the system. boot-related items onto the system.
Design goals of this project are:
- Support as many distros as possible
- Simplify configuration, while still giving multiple opportunities to set or override defaults
- Execute an external app to do any boot install/setup finalization
- One such app is here: https://gitlab.com/postmarketOS/boot-deploy
- But implementation can be anything, see the section on *BOOT-DEPLOY*
for more info
# DEVICEINFO # DEVICEINFO
The canonical deviceinfo "specification" is at The canonical deviceinfo "specification" is at
@@ -117,6 +126,30 @@ create/manage. mkinitfs reads configuration from */usr/share/mkinitfs* first, an
directories to create within the initramfs. There is no *-extra* variant, directories to create within the initramfs. There is no *-extra* variant,
since directories are of negligible size. since directories are of negligible size.
# BOOT-DEPLOY
After generating archives, mkinitfs will execute *boot-deploy*, using *$PATH* to
search for the app. The following commandline options are passed to it:
*-i* <initramfs filename>
Currently this is hardcoded to be "initramfs"
*-k* <kernel filename>
*-d* <work directory>
Path to the directory containing the build artifacts from mkinitfs.
*-o* <destination directory>
Path to the directory that boot-deploy should use as its root when
installing files.
*initramfs-extra*
This string is the filename of the initramfs-extra archive.
# AUTHORS # AUTHORS
*Clayton Craft* <clayton@craftyguy.net> *Clayton Craft* <clayton@craftyguy.net>

View File

@@ -44,14 +44,14 @@ const (
) )
type Archive struct { type Archive struct {
items archiveItems
cpioWriter *cpio.Writer cpioWriter *cpio.Writer
buf *bytes.Buffer buf *bytes.Buffer
compress_format CompressFormat compress_format CompressFormat
compress_level CompressLevel compress_level CompressLevel
items archiveItems
} }
func New(format CompressFormat, level CompressLevel) (*Archive, error) { func New(format CompressFormat, level CompressLevel) *Archive {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
archive := &Archive{ archive := &Archive{
cpioWriter: cpio.NewWriter(buf), cpioWriter: cpio.NewWriter(buf),
@@ -60,12 +60,12 @@ func New(format CompressFormat, level CompressLevel) (*Archive, error) {
compress_level: level, compress_level: level,
} }
return archive, nil return archive
} }
type archiveItem struct { type archiveItem struct {
sourcePath string
header *cpio.Header header *cpio.Header
sourcePath string
} }
type archiveItems struct { type archiveItems struct {
@@ -184,10 +184,11 @@ func (archive *Archive) Write(path string, mode os.FileMode) error {
return nil return nil
} }
// Adds the given items in the map to the archive. The map format is {source path:dest path}. // AddItems adds the given items in the map to the archive. The map format is
// Internally this just calls AddItem on each key,value pair in the map. // {source path:dest path}. Internally this just calls AddItem on each
func (archive *Archive) AddItems(f filelist.FileLister) error { // key,value pair in the map.
list, err := f.List() func (archive *Archive) AddItems(flister filelist.FileLister) error {
list, err := flister.List()
if err != nil { if err != nil {
return err return err
} }

View File

@@ -1,6 +1,12 @@
package filelist package filelist
import "sync" import (
"fmt"
"path/filepath"
"sync"
"gitlab.com/postmarketOS/postmarketos-mkinitfs/internal/misc"
)
type FileLister interface { type FileLister interface {
List() (*FileList, error) List() (*FileList, error)
@@ -45,6 +51,26 @@ func (f *FileList) Import(src *FileList) {
} }
} }
func (f *FileList) AddGlobbed(src string, dest string) error {
fFiles, err := misc.GetFiles([]string{src}, true)
if err != nil {
return fmt.Errorf("unable to add %q: %w", src, err)
}
// loop over all returned files from GetFile
for _, file := range fFiles {
if len(fFiles) > 1 {
// Glob with arbitrary subdirectories, so we need to
// remove the src path and prepend the dest path
f.Add(file, filepath.Join(dest, file[len(src):]))
} else {
// dest path specified, and only 1 file
f.Add(file, dest)
}
}
return nil
}
// iterate through the list and and send each one as a new File over the // iterate through the list and and send each one as a new File over the
// returned channel // returned channel
func (f *FileList) IterItems() <-chan File { func (f *FileList) IterItems() <-chan File {

View File

@@ -10,7 +10,6 @@ import (
"strings" "strings"
"gitlab.com/postmarketOS/postmarketos-mkinitfs/internal/filelist" "gitlab.com/postmarketOS/postmarketos-mkinitfs/internal/filelist"
"gitlab.com/postmarketOS/postmarketos-mkinitfs/internal/misc"
) )
type HookFiles struct { type HookFiles struct {
@@ -60,22 +59,13 @@ func slurpFiles(fd io.Reader) (*filelist.FileList, error) {
for s.Scan() { for s.Scan() {
src, dest, has_dest := strings.Cut(s.Text(), ":") src, dest, has_dest := strings.Cut(s.Text(), ":")
fFiles, err := misc.GetFiles([]string{src}, true)
if err != nil {
return nil, fmt.Errorf("unable to add %q: %w", src, err)
}
// loop over all returned files from GetFile
for _, file := range fFiles {
if !has_dest { if !has_dest {
files.Add(file, file) dest = src
} else if len(fFiles) > 1 {
// Don't support specifying dest if src was a glob
// NOTE: this could support this later...
files.Add(file, file)
} else {
// dest path specified, and only 1 file
files.Add(file, dest)
} }
err := files.AddGlobbed(src, dest)
if err != nil {
return nil, err
} }
} }

View File

@@ -35,8 +35,13 @@ func (h *HookScripts) List() (*filelist.FileList, error) {
} }
for _, file := range fileInfo { for _, file := range fileInfo {
path := filepath.Join(h.scriptsDir, file.Name()) path := filepath.Join(h.scriptsDir, file.Name())
if file.IsDir() {
log.Printf("-- Including dir %s\n", path)
files.AddGlobbed(filepath.Join(path, "*"), filepath.Join(h.destPath, file.Name()))
} else {
log.Printf("-- Including script: %s\n", path) log.Printf("-- Including script: %s\n", path)
files.Add(path, filepath.Join(h.destPath, file.Name())) files.Add(path, filepath.Join(h.destPath, file.Name()))
} }
}
return files, nil return files, nil
} }

View File

@@ -16,8 +16,8 @@ import (
) )
type Modules struct { type Modules struct {
modulesList []string
modulesListPath string modulesListPath string
modulesList []string
} }
// New returns a new Modules that will use the given moduleto provide a list // New returns a new Modules that will use the given moduleto provide a list
@@ -30,8 +30,6 @@ func New(modulesList []string, modulesListPath string) *Modules {
} }
func (m *Modules) List() (*filelist.FileList, error) { func (m *Modules) List() (*filelist.FileList, error) {
log.Printf("- Searching for kernel modules from %s", m.modulesListPath)
kernVer, err := osutil.GetKernelVersion() kernVer, err := osutil.GetKernelVersion()
if err != nil { if err != nil {
return nil, err return nil, err
@@ -55,20 +53,23 @@ func (m *Modules) List() (*filelist.FileList, error) {
} }
// slurp up given list of modules // slurp up given list of modules
if len(m.modulesList) > 0 {
log.Printf("-- Including kernel modules from deviceinfo")
for _, module := range m.modulesList { for _, module := range m.modulesList {
if modFilelist, err := getModule(module, modDir); err != nil { if modFilelist, err := getModule(module, modDir); err != nil {
return nil, fmt.Errorf("getInitfsModules: unable to get modules from deviceinfo: %w", err) return nil, fmt.Errorf("unable to get modules from deviceinfo: %w", err)
} else { } else {
for _, file := range modFilelist { for _, file := range modFilelist {
files.Add(file, file) files.Add(file, file)
} }
} }
} }
}
// slurp up modules from lists in modulesListPath // slurp up modules from lists in modulesListPath
log.Printf("- Searching for kernel modules from %s", m.modulesListPath)
fileInfo, err := os.ReadDir(m.modulesListPath) fileInfo, err := os.ReadDir(m.modulesListPath)
if err != nil { if err != nil {
log.Println("-- Unable to find dir, skipping...")
return files, nil return files, nil
} }
for _, file := range fileInfo { for _, file := range fileInfo {
@@ -126,7 +127,11 @@ func slurpModules(fd io.Reader, modDir string) (*filelist.FileList, error) {
} }
func getModulesInDir(modPath string) (files []string, err error) { func getModulesInDir(modPath string) (files []string, err error) {
err = filepath.Walk(modPath, func(path string, f os.FileInfo, err error) error { err = filepath.Walk(modPath, func(path string, _ os.FileInfo, err error) error {
if err != nil {
// Unable to walk path
return err
}
if filepath.Ext(path) != ".ko" && filepath.Ext(path) != ".xz" { if filepath.Ext(path) != ".ko" && filepath.Ext(path) != ".xz" {
return nil return nil
} }

View File

@@ -45,7 +45,7 @@ func RemoveDuplicates(in []string) (out []string) {
// defer misc.TimeFunc(time.Now(), "foo") // defer misc.TimeFunc(time.Now(), "foo")
func TimeFunc(start time.Time, name string) { func TimeFunc(start time.Time, name string) {
elapsed := time.Since(start) elapsed := time.Since(start)
log.Printf("%s completed in: %s", name, elapsed) log.Printf("%s completed in: %.2fs", name, elapsed.Seconds())
} }
// Exists tests if the given file/dir exists or not. Returns any errors related // Exists tests if the given file/dir exists or not. Returns any errors related