diff --git a/internal/embedbin/embedbin.go b/internal/embedbin/embedbin.go index e92ec09e5..2ff14b4ee 100644 --- a/internal/embedbin/embedbin.go +++ b/internal/embedbin/embedbin.go @@ -2,3 +2,11 @@ // // The Install function creates a temporary file and writes the contents to it. package embedbin + +// Installed is a handle to an installed binary. +// Users must call Uninstall to clean it up. +type Installed interface { + Path() string + IsRegular() bool + Uninstall() error +} diff --git a/internal/embedbin/install_linux.go b/internal/embedbin/install_linux.go index b41354f73..aecb52d34 100644 --- a/internal/embedbin/install_linux.go +++ b/internal/embedbin/install_linux.go @@ -3,20 +3,37 @@ package embedbin import ( "fmt" + "github.com/spf13/afero" "golang.org/x/sys/unix" ) // MemfdInstaller installs embedded binaries. -type MemfdInstaller struct{} +type MemfdInstaller struct { + fallback *RegularInstaller +} // New returns a new installer. func New() *MemfdInstaller { - return &MemfdInstaller{} + return &MemfdInstaller{ + fallback: &RegularInstaller{fs: afero.NewOsFs()}, + } } // Install creates a memfd and writes the contents to it. // the first argument is ignored on Linux (would be the prefix on other implementations). -func (*MemfdInstaller) Install(_ string, contents []byte) (*MemfdInstall, error) { +func (i *MemfdInstaller) Install(_ string, contents []byte) (Installed, error) { + // Try to install using memfd. + install, err := New().installMemfd(contents) + if err == nil { + return install, nil + } + + // Fallback to regular installer. + return i.fallback.Install("", contents) +} + +// installMemfd creates a memfd and writes the contents to it. +func (*MemfdInstaller) installMemfd(contents []byte) (*MemfdInstall, error) { // Create a memfd. fd, err := unix.MemfdCreate("embedded-binary", 0) if err != nil { diff --git a/internal/embedbin/regular.go b/internal/embedbin/regular.go index 6479efebf..d9485a42e 100644 --- a/internal/embedbin/regular.go +++ b/internal/embedbin/regular.go @@ -14,7 +14,7 @@ type RegularInstaller struct { // Install creates a regular file and writes the contents to it. // prefix is an optional prefix for the temporary file. // If prefix is empty, a temporary directory will be used. -func (r *RegularInstaller) Install(prefix string, contents []byte) (*RegularInstall, error) { +func (r *RegularInstaller) Install(prefix string, contents []byte) (Installed, error) { if prefix != "" { if err := r.fs.MkdirAll(prefix, os.ModePerm); err != nil { return nil, err