Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uimage API: add arbitrary CPIO records #19

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions uimage/initramfs/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ type Opts struct {
// If this is false, the "init" file in BaseArchive will be renamed
// "inito" (for init-original) in the output archive.
UseExistingInit bool

// Records are additional CPIO records to include in the initramfs.
Records []cpio.Record
}

// Write uses the given options to determine which files to write to the output
Expand Down Expand Up @@ -99,6 +102,12 @@ func Write(opts *Opts) error {
}
}

for _, r := range opts.Records {
if err := opts.Files.AddRecord(r); err != nil {
return err
}
}

out, err := opts.OutputFile.OpenWriter()
if err != nil {
return err
Expand Down
42 changes: 42 additions & 0 deletions uimage/initramfs/files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,48 @@
cpio.Trailer: cpio.TrailerRecord,
},
},
{
desc: "base archive with init and extra records conflict",
opts: &Opts{
Files: &Files{
Records: map[string]cpio.Record{
"init": cpio.StaticFile("init", "huh", 0o111),
},
},
BaseArchive: &Archive{Archive: archive(t,
cpio.StaticFile("init", "boo", 0o555),
)},
Records: []cpio.Record{
cpio.StaticFile("init", "huh", 0o111),
},
UseExistingInit: true,
},
errs: []error{os.ErrExist},

Check failure on line 655 in uimage/initramfs/files_test.go

View workflow job for this annotation

GitHub Actions / Build and test (1.21.x, ubuntu-latest)

unknown field errs in struct literal of type struct{desc string; opts *Opts; output *cpio.Archive; want Records; err error}

Check failure on line 655 in uimage/initramfs/files_test.go

View workflow job for this annotation

GitHub Actions / Race test (1.21.x, ubuntu-latest)

unknown field errs in struct literal of type struct{desc string; opts *Opts; output *cpio.Archive; want Records; err error}

Check failure on line 655 in uimage/initramfs/files_test.go

View workflow job for this annotation

GitHub Actions / Build and test (1.22.x, ubuntu-latest)

unknown field errs in struct literal of type struct{desc string; opts *Opts; output *cpio.Archive; want Records; err error}

Check failure on line 655 in uimage/initramfs/files_test.go

View workflow job for this annotation

GitHub Actions / Race test (1.22.x, ubuntu-latest)

unknown field errs in struct literal of type struct{desc string; opts *Opts; output *cpio.Archive; want Records; err error}
output: &cpio.Archive{
Files: make(map[string]cpio.Record),
},
},
{
desc: "extra records",
opts: &Opts{
Files: &Files{
Records: map[string]cpio.Record{
"init": cpio.StaticFile("init", "huh", 0o111),
},
},
Records: []cpio.Record{
cpio.StaticFile("etc/foo", "huh", 0o111),
},
},
output: &cpio.Archive{
Files: make(map[string]cpio.Record),
},
want: Records{
"init": cpio.StaticFile("init", "boo", 0o555),
"etc/foo": cpio.StaticFile("etc/foo", "huh", 0o111),
cpio.Trailer: cpio.TrailerRecord,
},
},
} {
t.Run(fmt.Sprintf("Test %02d (%s)", i, tt.desc), func(t *testing.T) {
tt.opts.OutputFile = &Archive{tt.output}
Expand Down
12 changes: 12 additions & 0 deletions uimage/uimage.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ type Opts struct {
//
// This must be specified to have a default shell.
DefaultShell string

// Records are additional CPIO records to include in the initramfs.
Records []cpio.Record
}

// Modifier modifies uimage options.
Expand Down Expand Up @@ -503,6 +506,14 @@ func WithTempDir(dir string) Modifier {
}
}

// WithRecord adds CPIO records to include in the initramfs.
func WithRecord(r ...cpio.Record) Modifier {
return func(o *Opts) error {
o.Records = append(o.Records, r...)
return nil
}
}

// Create creates an initramfs from mods specifications.
func Create(l *llog.Logger, mods ...Modifier) error {
o, err := OptionsFor(mods...)
Expand Down Expand Up @@ -571,6 +582,7 @@ func CreateInitramfs(l *llog.Logger, opts Opts) error {
OutputFile: opts.OutputFile,
BaseArchive: opts.BaseArchive,
UseExistingInit: opts.UseExistingInit,
Records: opts.Records,
}
if err := ParseExtraFiles(l, archive.Files, opts.ExtraFiles, !opts.SkipLDD); err != nil {
return err
Expand Down
76 changes: 76 additions & 0 deletions uimage/uimage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,46 @@ func TestCreateInitramfs(t *testing.T) {
itest.IsEmpty{},
},
},
{
name: "extra records conflict",
opts: Opts{
Env: golang.Default(golang.DisableCGO()),
TempDir: dir,
InitCmd: "init",
DefaultShell: "ls",
Records: []cpio.Record{
cpio.StaticFile("bbin/ls", "foo", 0o111),
},
Commands: BusyboxCmds(
"github.com/u-root/u-root/cmds/core/init",
"github.com/u-root/u-root/cmds/core/ls",
),
},
errs: []error{os.ErrExist},
validators: []itest.ArchiveValidator{
itest.IsEmpty{},
},
},
{
name: "extra records",
opts: Opts{
Env: golang.Default(golang.DisableCGO()),
TempDir: dir,
InitCmd: "init",
DefaultShell: "ls",
Records: []cpio.Record{
cpio.StaticFile("etc/foo", "foo", 0o111),
},
Commands: BusyboxCmds(
"github.com/u-root/u-root/cmds/core/init",
"github.com/u-root/u-root/cmds/core/ls",
),
},
validators: []itest.ArchiveValidator{
itest.HasFile{Path: "bbin/bb"},
itest.HasRecord{R: cpio.StaticFile("etc/foo", "foo", 0o111)},
},
},
} {
t.Run(fmt.Sprintf("Test %d [%s]", i, tt.name), func(t *testing.T) {
archive := cpio.InMemArchive()
Expand Down Expand Up @@ -992,6 +1032,42 @@ func TestCreateInitramfsWithAPI(t *testing.T) {
itest.IsEmpty{},
},
},
{
name: "extra records conflict",
opts: []Modifier{
WithTempDir(dir),
WithEnv(golang.DisableCGO()),
WithInit("init"),
WithShell("ls"),
WithRecord(cpio.StaticFile("bbin/ls", "foo", 0o111)),
WithBusyboxCommands(
"github.com/u-root/u-root/cmds/core/init",
"github.com/u-root/u-root/cmds/core/ls",
),
},
errs: []error{os.ErrExist},
validators: []itest.ArchiveValidator{
itest.IsEmpty{},
},
},
{
name: "extra records",
opts: []Modifier{
WithTempDir(dir),
WithEnv(golang.DisableCGO()),
WithInit("init"),
WithShell("ls"),
WithRecord(cpio.StaticFile("etc/foo", "foo", 0o111)),
WithBusyboxCommands(
"github.com/u-root/u-root/cmds/core/init",
"github.com/u-root/u-root/cmds/core/ls",
),
},
validators: []itest.ArchiveValidator{
itest.HasFile{Path: "bbin/bb"},
itest.HasRecord{R: cpio.StaticFile("etc/foo", "foo", 0o111)},
},
},
} {
t.Run(fmt.Sprintf("Test %d [%s]", i, tt.name), func(t *testing.T) {
archive := cpio.InMemArchive()
Expand Down
Loading