summaryrefslogtreecommitdiff
path: root/actions/raw_action.go
diff options
context:
space:
mode:
Diffstat (limited to 'actions/raw_action.go')
-rw-r--r--actions/raw_action.go130
1 files changed, 130 insertions, 0 deletions
diff --git a/actions/raw_action.go b/actions/raw_action.go
new file mode 100644
index 0000000..d3e66fe
--- /dev/null
+++ b/actions/raw_action.go
@@ -0,0 +1,130 @@
+/*
+Raw Action
+
+Directly write a file to the output image at a given offset.
+This is typically useful for bootloaders.
+
+Yaml syntax:
+ - action: raw
+ origin: name
+ source: filename
+ offset: bytes
+
+Mandatory properties:
+
+- origin -- reference to named file or directory.
+
+- source -- the name of file located in 'origin' to be written into the output image.
+
+Optional properties:
+
+- offset -- offset in bytes for output image file.
+It is possible to use internal templating mechanism of debos to calculate offset
+with sectors (512 bytes) instead of bytes, for instance: '{{ sector 256 }}'.
+The default value is zero.
+
+- partition -- named partition to write to
+*/
+package actions
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "strconv"
+
+ "github.com/go-debos/debos"
+)
+
+type RawAction struct {
+ debos.BaseAction `yaml:",inline"`
+ Origin string // there the source comes from
+ Offset string
+ Source string // relative path inside of origin
+ Path string // deprecated option (for backward compatibility)
+ Partition string // Partition to write otherwise full image
+}
+
+func (raw *RawAction) checkDeprecatedSyntax() error {
+
+ // New syntax is based on 'origin' and 'source'
+ // Check if we do not mix new and old syntax
+ // TODO: remove deprecated syntax verification
+ if len(raw.Path) > 0 {
+ // Deprecated syntax based on 'source' and 'path'
+ log.Printf("Usage of 'source' and 'path' properties is deprecated.")
+ log.Printf("Please use 'origin' and 'source' properties.")
+ if len(raw.Origin) > 0 {
+ return errors.New("Can't mix 'origin' and 'path'(deprecated option) properties")
+ }
+ if len(raw.Source) == 0 {
+ return errors.New("'source' and 'path' properties can't be empty")
+ }
+ // Switch to new syntax
+ raw.Origin = raw.Source
+ raw.Source = raw.Path
+ raw.Path = ""
+ }
+ return nil
+}
+
+func (raw *RawAction) Verify(context *debos.DebosContext) error {
+ if err := raw.checkDeprecatedSyntax(); err != nil {
+ return err
+ }
+
+ if len(raw.Origin) == 0 || len(raw.Source) == 0 {
+ return errors.New("'origin' and 'source' properties can't be empty")
+ }
+
+ return nil
+}
+
+func (raw *RawAction) Run(context *debos.DebosContext) error {
+ raw.LogStart()
+ origin, found := context.Origins[raw.Origin]
+ if !found {
+ return fmt.Errorf("Origin `%s` doesn't exist\n", raw.Origin)
+ }
+ s := path.Join(origin, raw.Source)
+ content, err := ioutil.ReadFile(s)
+
+ if err != nil {
+ return fmt.Errorf("Failed to read %s", s)
+ }
+
+ var devicePath string
+ if raw.Partition != "" {
+ for _, p := range context.ImagePartitions {
+ if p.Name == raw.Partition {
+ devicePath = p.DevicePath
+ break
+ }
+ }
+
+ if devicePath == "" {
+ return fmt.Errorf("Failed to find partition named %s", raw.Partition)
+ }
+ } else {
+ devicePath = context.Image
+ }
+
+ target, err := os.OpenFile(devicePath, os.O_WRONLY, 0)
+ if err != nil {
+ return fmt.Errorf("Failed to open %s: %v", devicePath, err)
+ }
+
+ offset, err := strconv.ParseInt(raw.Offset, 0, 64)
+ if err != nil {
+ return fmt.Errorf("Couldn't parse offset %v", err)
+ }
+ bytes, err := target.WriteAt(content, offset)
+ if bytes != len(content) {
+ return errors.New("Couldn't write complete data")
+ }
+
+ return nil
+}