Merge lp:~mvo/snappy/snappy-tar-unpack-mknod into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by Michael Vogt on 2015-05-06
Status: Merged
Approved by: Michael Vogt on 2015-05-07
Approved revision: 449
Merged at revision: 447
Proposed branch: lp:~mvo/snappy/snappy-tar-unpack-mknod
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Prerequisite: lp:~mvo/snappy/snappy-hashes-yaml-for-devices
Diff against target: 150 lines (+98/-8)
3 files modified
helpers/helpers.go (+43/-0)
helpers/helpers_test.go (+52/-0)
snappy/build.go (+3/-8)
To merge this branch: bzr merge lp:~mvo/snappy/snappy-tar-unpack-mknod
Reviewer Review Type Date Requested Status
Michael Vogt Approve on 2015-05-07
John Lenton 2015-05-06 Approve on 2015-05-07
Review via email: mp+258407@code.launchpad.net

Commit Message

Add support for unpacking device files in a tar.

Description of the Change

This branch adds support for unpack tars that contains device files.

To post a comment you must log in.
John Lenton (chipaca) wrote :

Silly things, inline.

review: Needs Fixing
Michael Vogt (mvo) wrote :

Thanks a lot for the review! I commented inline and I hope I addressed the comments in r447.

John Lenton (chipaca) wrote :

Yes, thank you.

review: Approve
Snappy Tarmac (snappydevtarmac) wrote :

The attempt to merge lp:~mvo/snappy/snappy-tar-unpack-mknod into lp:snappy failed. Below is the output from the failed tests.

Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update code.google.com/p/go.crypto failed; trying to fetch newer version
update github.com/blakesmith/ar failed; trying to fetch newer version
code.google.com/p/go.crypto now at 69e2a90ed92d03812364aeb947b7068dc42e561e
update github.com/cheggaaa/pb failed; trying to fetch newer version
github.com/blakesmith/ar now at c9a977dd0cc1392b023382c7bfa5a22af8d3b730
update github.com/jessevdk/go-flags failed; trying to fetch newer version
github.com/cheggaaa/pb now at e8c7cc515bfde3e267957a3b110080ceed51354e
update github.com/juju/loggo failed; trying to fetch newer version
github.com/jessevdk/go-flags now at 15347ef417a300349807983f15af9e65cd2e1b3a
update github.com/mvo5/goconfigparser failed; trying to fetch newer version
github.com/juju/loggo now at 4c7cbce140ca070eeb59a28f4bf9507e511711f9
update gopkg.in/yaml.v2 failed; trying to fetch newer version
github.com/mvo5/goconfigparser now at 26426272dda20cc76aa1fa44286dc743d2972fe8
update launchpad.net/gocheck failed; trying to fetch newer version
gopkg.in/yaml.v2 now at 49c95bdc21843256fb6c4e0d370a05f24a0bf213
launchpad.net/gocheck now at <email address hidden>
Building

# we always run in a fresh dir in tarmac
export GOPATH=$(mktemp -d)
trap 'rm -rf "$GOPATH"' EXIT

# this is a hack, but not sure tarmac is golang friendly
mkdir -p $GOPATH/src/launchpad.net/snappy
cp -a . $GOPATH/src/launchpad.net/snappy/
cd $GOPATH/src/launchpad.net/snappy

./run-checks

if which goctest >/dev/null; then
    goctest="goctest"
else
    goctest="go test"
fi

echo Checking formatting
fmt=$(gofmt -l .)

if [ -n "$fmt" ]; then
    echo "Formatting wrong in following files"
    echo $fmt
    exit 1
fi

echo Installing godeps
go get launchpad.net/godeps
export PATH=$PATH:$GOPATH/bin

echo Install golint
go get github.com/golang/lint/golint
export PATH=$PATH:$GOPATH/bin

echo Obtaining dependencies
godeps -u dependencies.tsv

echo Building
go build -v launchpad.net/snappy/...
github.com/blakesmith/ar
launchpad.net/snappy/helpers
launchpad.net/snappy/clickdeb
code.google.com/p/go.crypto/ssh/terminal
github.com/jessevdk/go-flags
github.com/juju/loggo
launchpad.net/snappy/logger
launchpad.net/snappy/priv
github.com/cheggaaa/pb
launchpad.net/snappy/progress
github.com/mvo5/goconfigparser
gopkg.in/yaml.v2
launchpad.net/snappy/coreconfig
launchpad.net/snappy/partition
launchpad.net/snappy/policy
launchpad.net/snappy/release
launchpad.net/snappy/systemd
launchpad.net/snappy/snappy
# launchpad.net/snappy/snappy
snappy/build.go:398: undefined: syscall
snappy/build.go:399: undefined: syscall

448. By Michael Vogt on 2015-05-07

merged lp:snappy

449. By Michael Vogt on 2015-05-07

snappy/build.go: fix test failure

Michael Vogt (mvo) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'helpers/helpers.go'
2--- helpers/helpers.go 2015-04-29 09:10:08 +0000
3+++ helpers/helpers.go 2015-05-07 16:27:49 +0000
4@@ -95,10 +95,17 @@
5 return (mode & os.ModeSymlink) == os.ModeSymlink
6 }
7
8+// IsDevice checks if the given os.FileMode coresponds to a device (char/block)
9+func IsDevice(mode os.FileMode) bool {
10+ return (mode & (os.ModeDevice | os.ModeCharDevice)) != 0
11+}
12+
13 // UnpackTarTransformFunc can be used to change the names during unpack
14 // or to return a error for files that are not acceptable
15 type UnpackTarTransformFunc func(path string) (newPath string, err error)
16
17+var mknod = syscall.Mknod
18+
19 // UnpackTar unpacks the given tar file into the target directory
20 func UnpackTar(r io.Reader, targetDir string, fn UnpackTarTransformFunc) error {
21 return TarIterate(r, func(tr *tar.Reader, hdr *tar.Header) (err error) {
22@@ -127,6 +134,18 @@
23 if err := os.Symlink(hdr.Linkname, path); err != nil {
24 return err
25 }
26+ case IsDevice(mode):
27+ switch {
28+ case (mode & os.ModeCharDevice) != 0:
29+ mode |= syscall.S_IFCHR
30+ case (mode & os.ModeDevice) != 0:
31+ mode |= syscall.S_IFBLK
32+ }
33+ devNum := Makedev(uint32(hdr.Devmajor), uint32(hdr.Devminor))
34+ err = mknod(path, uint32(mode), int(devNum))
35+ if err != nil {
36+ return err
37+ }
38 case mode.IsRegular():
39 out, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, mode)
40 if err != nil {
41@@ -317,3 +336,27 @@
42 return syscall.Getuid() == 0 || syscall.Getgid() == 0
43
44 }
45+
46+// MajorMinor returns the major/minor number of the given os.FileInfo
47+func MajorMinor(info os.FileInfo) (uint32, uint32, error) {
48+ if !IsDevice(info.Mode()) {
49+ return 0, 0, fmt.Errorf("No device %s", info.Name())
50+ }
51+
52+ unixStat, ok := info.Sys().(*syscall.Stat_t)
53+ if ok {
54+ // see glibc: sysdeps/unix/sysv/linux/makedev.c
55+ dev := uint32(unixStat.Rdev)
56+ major := ((dev >> 8) & 0xfff) | ((dev >> 32) & ^uint32(0xfff))
57+ minor := (dev & 0xff) | ((dev >> 12) & ^uint32(0xff))
58+
59+ return major, minor, nil
60+ }
61+
62+ return 0, 0, fmt.Errorf("failed to get syscall.stat_t for %v", info.Name())
63+}
64+
65+// Makedev implements makedev(3)
66+func Makedev(major, minor uint32) uint32 {
67+ return uint32((minor & 0xff) | ((major & 0xfff) << 8))
68+}
69
70=== modified file 'helpers/helpers_test.go'
71--- helpers/helpers_test.go 2015-04-23 11:12:32 +0000
72+++ helpers/helpers_test.go 2015-05-07 16:27:49 +0000
73@@ -268,3 +268,55 @@
74 c.Assert(err, IsNil)
75 c.Assert(home, Equals, oldHome)
76 }
77+
78+func (ts *HTestSuite) TestMajorMinorSimple(c *C) {
79+ stat, err := os.Stat("/dev/kmsg")
80+ if err != nil {
81+ c.Skip("Can not stat /dev/kmsg")
82+ }
83+
84+ major, minor, err := MajorMinor(stat)
85+ c.Assert(err, IsNil)
86+ c.Assert(major, Equals, uint32(1))
87+ c.Assert(minor, Equals, uint32(11))
88+}
89+
90+func (ts *HTestSuite) TestMajorMinorNoDevice(c *C) {
91+ stat, err := os.Stat(c.MkDir())
92+ c.Assert(err, IsNil)
93+
94+ _, _, err = MajorMinor(stat)
95+ c.Assert(err, NotNil)
96+}
97+
98+func (ts *HTestSuite) TestMakedev(c *C) {
99+ // $ python -c 'import os;print(os.makedev(1,11))'
100+ // 267
101+ c.Assert(Makedev(1, 11), Equals, uint32(267))
102+}
103+
104+func (ts *HTestSuite) TestUnpacksMknod(c *C) {
105+
106+ // mknod mock
107+ mknodWasCalled := false
108+ mknod = func(path string, mode uint32, dev int) error {
109+ mknodWasCalled = true
110+ return nil
111+ }
112+
113+ // setup tmpdir
114+ tmpdir := c.MkDir()
115+ tmpfile := filepath.Join(tmpdir, "device.tar")
116+
117+ cmd := exec.Command("tar", "cf", tmpfile, "/dev/kmsg")
118+ err := cmd.Run()
119+ c.Assert(err, IsNil)
120+
121+ f, err := os.Open(tmpfile)
122+ c.Assert(err, IsNil)
123+
124+ err = UnpackTar(f, c.MkDir(), nil)
125+ c.Assert(err, IsNil)
126+ c.Assert(mknodWasCalled, Equals, true)
127+
128+}
129
130=== modified file 'snappy/build.go'
131--- snappy/build.go 2015-05-07 10:34:05 +0000
132+++ snappy/build.go 2015-05-07 16:27:49 +0000
133@@ -233,14 +233,9 @@
134
135 // major/minor handling
136 device := ""
137- if (info.Mode()&os.ModeDevice) != 0 || (info.Mode()&os.ModeCharDevice) != 0 {
138- unixStat, ok := info.Sys().(*syscall.Stat_t)
139- if ok {
140- // see /usr/include/linux/kdev_t.h
141- major := int64(unixStat.Rdev >> 8)
142- minor := int64(unixStat.Rdev & 0xff)
143- device = fmt.Sprintf("%v,%v", major, minor)
144- }
145+ major, minor, err := helpers.MajorMinor(info)
146+ if err == nil {
147+ device = fmt.Sprintf("%v,%v", major, minor)
148 }
149
150 if buildDir != "" {

Subscribers

People subscribed via source and target branches