Unverified Commit 62d044bb authored by lluiscampos's avatar lluiscampos Committed by GitHub
Browse files

Merge pull request #205 from oleorhagen/MEN-2544

Men 2544
parents 0881d943 35ae4b53
Pipeline #82469553 passed with stages
in 7 minutes
......@@ -77,37 +77,38 @@ func Copy(c *cli.Context) (err error) {
var vfile VPFile
switch parseCLIOptions(c) {
case copyin:
r, err = os.OpenFile(c.Args().First(), os.O_CREATE|os.O_RDONLY, 0655)
r, err = os.Open(c.Args().First())
defer r.Close()
if err != nil {
return cli.NewExitError(fmt.Sprintf("%v", err), 1)
return cli.NewExitError(err, 1)
}
vfile, err = virtualPartitionFile.Open(comp, c.Args().Get(1))
defer wclose(vfile)
if err != nil {
return cli.NewExitError(fmt.Sprintf("%v", err), 1)
return cli.NewExitError(err, 1)
}
w = vfile
if err = vfile.CopyTo(c.Args().First()); err != nil {
return cli.NewExitError(err, 1)
}
return nil
case copyinstdin:
r = os.Stdin
vfile, err = virtualPartitionFile.Open(comp, c.Args().First())
defer wclose(vfile)
if err != nil {
return cli.NewExitError(fmt.Sprintf("%v", err), 1)
return cli.NewExitError(err, 1)
}
w = vfile
case copyout:
vfile, err = virtualPartitionFile.Open(comp, c.Args().First())
defer wclose(vfile)
if err != nil {
return cli.NewExitError(fmt.Sprintf("%v", err), 1)
return cli.NewExitError(err, 1)
}
r = vfile
w, err = os.OpenFile(c.Args().Get(1), os.O_CREATE|os.O_WRONLY, 0655)
defer w.Close()
if err != nil {
if err = vfile.CopyFrom(c.Args().Get(1)); err != nil {
return cli.NewExitError(fmt.Sprintf("%v", err), 1)
}
return nil
case parseError:
return cli.NewExitError(fmt.Sprintln("no artifact or sdimage provided"), 1)
case argerror:
......@@ -116,10 +117,10 @@ func Copy(c *cli.Context) (err error) {
return cli.NewExitError("critical error", 1)
}
if _, err = io.Copy(w, r); err != nil {
_, err = io.Copy(w, r)
if err != nil {
return cli.NewExitError(err, 1)
}
return nil
}
......
This diff is collapsed.
......@@ -30,7 +30,7 @@ import (
)
const (
debugfsMissingErr = "The `debugfs` binary is not found on the system. The binary can typically be installed through"+
debugfsMissingErr = "The `debugfs` binary is not found on the system. The binary can typically be installed through" +
" the `e2fsprogs` package."
)
......@@ -107,7 +107,7 @@ func debugfsCopyFile(file, image string) (string, error) {
return tmpDir, nil
}
func debugfsReplaceFile(imageFile, newFile, image string) (err error) {
func debugfsReplaceFile(imageFile, hostFile, image string) (err error) {
// First check that the path exists. (cd path)
cmd := fmt.Sprintf("cd %s\nclose", filepath.Dir(imageFile))
if _, err = executeCommand(cmd, image); err != nil {
......@@ -118,7 +118,7 @@ func debugfsReplaceFile(imageFile, newFile, image string) (err error) {
cmd = fmt.Sprintf("rm %s\nclose", imageFile)
executeCommand(cmd, image)
// Write to the partition
cmd = fmt.Sprintf("cd %s\nwrite %s %s\nclose", filepath.Dir(imageFile), newFile, filepath.Base(imageFile))
cmd = fmt.Sprintf("cd %s\nwrite %s %s\nclose", filepath.Dir(imageFile), hostFile, filepath.Base(imageFile))
_, err = executeCommand(cmd, image)
return err
}
......
......@@ -15,7 +15,6 @@
package main
import (
"fmt"
"os"
"testing"
......@@ -45,7 +44,6 @@ func TestExecuteCommand(t *testing.T) {
for name, test := range tests {
_, err := executeCommand(test.cmd, "mender_test.img")
t.Log(name)
fmt.Fprintf(os.Stderr, "err: %s\n", err)
assert.Contains(t, err.Error(), test.expected, "Unexpected error")
}
}
......
......@@ -79,6 +79,9 @@ func TestDebugfs(t *testing.T) {
filepath.Join(tmp, "mender_test.img"))
assert.NoError(t, err)
err = debugfsReplaceFile("/nonexisting/foo.txt", tFile.Name(), filepath.Join(tmp, "mender_test.img"))
assert.Error(t, err)
os.RemoveAll(tDir)
}
......
......@@ -23,6 +23,7 @@ import (
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/mendersoftware/mender-artifact/artifact"
......@@ -44,6 +45,8 @@ const (
type VPFile interface {
io.ReadWriteCloser
Delete(recursive bool) error
CopyTo(hostFile string) error
CopyFrom(hostFile string) error
}
type partition struct {
......@@ -67,7 +70,7 @@ func (v vFile) Open(comp artifact.Compressor, imgpath string) (VPFile, error) {
return nil, err
}
if modcands == nil {
return nil, fmt.Errorf("No partitions found in file %s, only " +
return nil, fmt.Errorf("No partitions found in file %s, only "+
"rootfs Artifact or image are supported", imgname)
} else {
for i := 0; i < len(modcands); i++ {
......@@ -137,15 +140,15 @@ func newSDImgFile(fpath string, modcands []partition) (sdimgFile, error) {
// Only return the data partition.
if strings.HasPrefix(fpath, "/data") {
// The data dir is not a directory in the data partition
fpath = strings.TrimPrefix(fpath, "/data")
fpath = strings.TrimPrefix(fpath, "/data/")
delPartition = append(delPartition, modcands[0:3]...)
ext, err := newExtFile(fpath, modcands[3]) // Data partition
return sdimgFile{ext}, err
}
reg := regexp.MustCompile("/(uboot|boot/(efi|grub))")
reg := regexp.MustCompile("/(uboot|boot/(efi|grub))[/]")
// Only return the boot-partition.
if reg.MatchString(fpath) {
// /uboot, /boot/efi, /boot/grup are not directories on the boot partition.
// /uboot, /boot/efi, /boot/grub are not directories on the boot partition.
fpath = reg.ReplaceAllString(fpath, "")
// Since boot partitions can be either fat or ext,
// return a readWriteCloser dependent upon the underlying filesystem type.
......@@ -195,9 +198,29 @@ func (p sdimgFile) Write(b []byte) (int, error) {
// Read reads a file from an sdimg.
func (p sdimgFile) Read(b []byte) (int, error) {
// A read from the first partition wrapped should suffice in all cases.
if len(p) == 0 {
return 0, errors.New("No partition set to read from")
}
return p[0].Read(b)
}
func (p sdimgFile) CopyTo(hostFile string) error {
for _, part := range p {
err := part.CopyTo(hostFile)
if err != nil {
return err
}
}
return nil
}
func (p sdimgFile) CopyFrom(hostFile string) error {
if len(p) == 0 {
return errors.New("No partition set to copy from")
}
return p[0].CopyFrom(hostFile)
}
// Read reads a file from an sdimg.
func (p sdimgFile) Delete(recursive bool) (err error) {
for _, part := range p {
......@@ -231,19 +254,6 @@ type artifactExtFile struct {
}
func newArtifactExtFile(comp artifact.Compressor, fpath string, p partition) (af *artifactExtFile, err error) {
tmpf, err := ioutil.TempFile("", "mendertmp-artifactextfile")
// Cleanup resources in case of error.
af = &artifactExtFile{
extFile{
partition: p,
imagefilepath: fpath,
tmpf: tmpf,
},
comp,
}
if err != nil {
return af, err
}
reg := regexp.MustCompile("/(uboot|boot/(efi|grub))")
if reg.MatchString(fpath) {
return af, errors.New("newArtifactExtFile: A mender artifact does not contain a boot partition, only a rootfs")
......@@ -251,6 +261,15 @@ func newArtifactExtFile(comp artifact.Compressor, fpath string, p partition) (af
if strings.HasPrefix(fpath, "/data") {
return af, errors.New("newArtifactExtFile: A mender artifact does not contain a data partition, only a rootfs")
}
extf, err := newExtFile(fpath, p)
if err != nil {
return nil, err
}
af = &artifactExtFile{*extf, comp}
if err != nil {
return af, err
}
return af, nil
}
......@@ -278,6 +297,11 @@ type extFile struct {
}
func newExtFile(imagefilepath string, p partition) (e *extFile, err error) {
// Check that the given directory exists.
_, err = executeCommand(fmt.Sprintf("cd %s", filepath.Dir(imagefilepath)), p.path)
if err != nil {
return nil, fmt.Errorf("The directory: %s does not exist in the image", filepath.Dir(imagefilepath))
}
tmpf, err := ioutil.TempFile("", "mendertmp-extfile")
// Cleanup resources in case of error.
e = &extFile{
......@@ -318,6 +342,46 @@ func (ef *extFile) Read(b []byte) (int, error) {
return copy(b, data), io.EOF
}
func (ef *extFile) CopyTo(hostFile string) error {
if err := debugfsReplaceFile(ef.imagefilepath, hostFile, ef.path); err != nil {
return err
}
ef.repack = true
return nil
}
func (ef *extFile) CopyFrom(hostFile string) error {
// Get the file permissions
d, err := executeCommand(fmt.Sprintf("stat %s", ef.imagefilepath), ef.partition.path)
if err != nil {
if strings.Contains(err.Error(), "File not found by ext2_lookup") {
return fmt.Errorf("The file: %s does not exist in the image", ef.imagefilepath)
}
return err
}
// Extract the Mode: oooo octal code
reg := regexp.MustCompile(`Mode: +(0[0-9]{3})`)
m := reg.FindStringSubmatch(d.String())
if m == nil || len(m) != 2 {
return fmt.Errorf("Could not extract the filemode information from the file: %s\n", ef.imagefilepath)
}
mode, err := strconv.ParseInt(m[1], 8, 32)
if err != nil {
return fmt.Errorf("Failed to extract the file permissions for the file: %s\nerr: %s", ef.imagefilepath, err)
}
_, err = executeCommand(fmt.Sprintf("dump %s %s\nclose", ef.imagefilepath, hostFile), ef.partition.path)
if err != nil {
if strings.Contains(err.Error(), "File not found by ext2_lookup") {
return fmt.Errorf("The file: %s does not exist in the image", ef.imagefilepath)
}
return err
}
if err = os.Chmod(hostFile, os.FileMode(mode)); err != nil {
return err
}
return nil
}
func (ef *extFile) Delete(recursive bool) (err error) {
err = debugfsRemoveFileOrDir(ef.imagefilepath, ef.path, recursive)
if err != nil {
......@@ -365,7 +429,7 @@ func newFatFile(imageFilePath string, partition partition) (*fatFile, error) {
// Read Dump the file contents to stdout, and capture, using MTools' mtype
func (f *fatFile) Read(b []byte) (n int, err error) {
cmd := exec.Command("mtype", "-i", f.path, "::"+f.imageFilePath)
cmd := exec.Command("mtype", "-n", "-i", f.path, "::"+f.imageFilePath)
dbuf := bytes.NewBuffer(nil)
cmd.Stdout = dbuf // capture Stdout
if err = cmd.Run(); err != nil {
......@@ -392,6 +456,27 @@ func (f *fatFile) Write(b []byte) (n int, err error) {
return len(b), nil
}
func (f *fatFile) CopyTo(hostFile string) error {
cmd := exec.Command("mcopy", "-oi", f.path, hostFile, "::"+f.imageFilePath)
data := bytes.NewBuffer(nil)
cmd.Stdout = data
if err := cmd.Run(); err != nil {
return errors.Wrap(err, "fatFile: Write: MTools execution failed")
}
f.repack = true
return nil
}
func (f *fatFile) CopyFrom(hostFile string) error {
cmd := exec.Command("mcopy", "-n", "-i", f.path, "::"+f.imageFilePath, hostFile)
dbuf := bytes.NewBuffer(nil)
cmd.Stdout = dbuf // capture Stdout
if err := cmd.Run(); err != nil {
return errors.Wrap(err, "fatPartitionFile: Read: MTools mcopy failed")
}
return nil
}
func (f *fatFile) Delete(recursive bool) (err error) {
isDir := filepath.Dir(f.imageFilePath) == strings.TrimRight(f.imageFilePath, "/")
var deleteCmd string
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment