package inject import ( "fmt" "os" "path/filepath" ) var setFileMode = os.Chmod // Injector writes node config into a mounted image (boot/root paths supplied by caller). type Injector struct { BootPath string RootPath string } // FileSpec describes a file to write. type FileSpec struct { Path string Content []byte Mode os.FileMode RootFS bool // if true, write under root path; else boot path Symlink string // relative target for native systemd enablement } // Write materializes the requested files under the boot or root mount because // the burn flow needs a single place to stage config fragments before sync. func (i *Injector) Write(files []FileSpec) error { for _, f := range files { base := i.BootPath if f.RootFS { base = i.RootPath } target := filepath.Join(base, f.Path) if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil { return fmt.Errorf("mkdir %s: %w", filepath.Dir(target), err) } if f.Symlink != "" { if current, err := os.Readlink(target); err == nil && current == f.Symlink { continue } // Refuse to replace unrelated files in the mounted image. if err := os.Symlink(f.Symlink, target); err != nil { return fmt.Errorf("link %s: %w", target, err) } continue } if err := os.WriteFile(target, f.Content, f.Mode); err != nil { return fmt.Errorf("write %s: %w", target, err) } // WriteFile retains an existing file's permissions, including loose // permissions inherited from a recovery image. if err := setFileMode(target, f.Mode); err != nil { return fmt.Errorf("chmod %s: %w", target, err) } } return nil }