diff --git a/oci/cas/drivers/dir/dir_test.go b/oci/cas/drivers/dir/dir_test.go index 9ca8c586f..f44695406 100644 --- a/oci/cas/drivers/dir/dir_test.go +++ b/oci/cas/drivers/dir/dir_test.go @@ -23,12 +23,12 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" "testing" "github.com/openSUSE/umoci/oci/cas" "github.com/pkg/errors" "golang.org/x/net/context" + "golang.org/x/sys/unix" ) // NOTE: These tests aren't really testing OCI-style manifests. It's all just @@ -47,10 +47,10 @@ func readonly(t *testing.T, path string) { t.Logf("mounting %s as readonly", path) - if err := syscall.Mount(path, path, "", syscall.MS_BIND|syscall.MS_RDONLY, ""); err != nil { + if err := unix.Mount(path, path, "", unix.MS_BIND|unix.MS_RDONLY, ""); err != nil { t.Fatalf("mount %s as ro: %s", path, err) } - if err := syscall.Mount("none", path, "", syscall.MS_BIND|syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil { + if err := unix.Mount("none", path, "", unix.MS_BIND|unix.MS_REMOUNT|unix.MS_RDONLY, ""); err != nil { t.Fatalf("mount %s as ro: %s", path, err) } } @@ -62,7 +62,7 @@ func readwrite(t *testing.T, path string) { t.Skip() } - if err := syscall.Unmount(path, syscall.MNT_DETACH); err != nil { + if err := unix.Unmount(path, unix.MNT_DETACH); err != nil { t.Fatalf("unmount %s: %s", path, err) } } diff --git a/oci/layer/tar_extract.go b/oci/layer/tar_extract.go index cd2163690..a2f4f1b18 100644 --- a/oci/layer/tar_extract.go +++ b/oci/layer/tar_extract.go @@ -43,7 +43,7 @@ type tarExtractor struct { // newTarExtractor creates a new tarExtractor. func newTarExtractor(opt MapOptions) *tarExtractor { - var fsEval fseval.FsEval = fseval.DefaultFsEval + fsEval := fseval.DefaultFsEval if opt.Rootless { fsEval = fseval.RootlessFsEval } diff --git a/oci/layer/tar_extract_test.go b/oci/layer/tar_extract_test.go index 9e1f29cca..54e0a8749 100644 --- a/oci/layer/tar_extract_test.go +++ b/oci/layer/tar_extract_test.go @@ -23,11 +23,11 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" "testing" "time" rspec "github.com/opencontainers/runtime-spec/specs-go" + "golang.org/x/sys/unix" ) // TODO: Test the parent directory metadata is kept the same when unpacking. @@ -393,40 +393,34 @@ func TestUnpackHardlink(t *testing.T) { } // Now we have to check the inode numbers. - regFi, err := os.Lstat(filepath.Join(dir, regFile)) - if err != nil { + var regFi, symFi, hardAFi, hardBFi unix.Stat_t + + if err := unix.Lstat(filepath.Join(dir, regFile), ®Fi); err != nil { t.Fatalf("could not stat regular file: %s", err) } - symFi, err := os.Lstat(filepath.Join(dir, symFile)) - if err != nil { + if err := unix.Lstat(filepath.Join(dir, symFile), &symFi); err != nil { t.Fatalf("could not stat symlink: %s", err) } - hardAFi, err := os.Lstat(filepath.Join(dir, hardFileA)) - if err != nil { + if err := unix.Lstat(filepath.Join(dir, hardFileA), &hardAFi); err != nil { t.Fatalf("could not stat hardlinkA: %s", err) } - hardBFi, err := os.Lstat(filepath.Join(dir, hardFileB)) - if err != nil { + if err := unix.Lstat(filepath.Join(dir, hardFileB), &hardBFi); err != nil { t.Fatalf("could not stat hardlinkB: %s", err) } // This test only runs on Linux anyway. - regIno := regFi.Sys().(*syscall.Stat_t).Ino - symIno := symFi.Sys().(*syscall.Stat_t).Ino - hardAIno := hardAFi.Sys().(*syscall.Stat_t).Ino - hardBIno := hardBFi.Sys().(*syscall.Stat_t).Ino - if regIno == symIno { - t.Errorf("regular and symlink have the same inode! ino=%d", regIno) + if regFi.Ino == symFi.Ino { + t.Errorf("regular and symlink have the same inode! ino=%d", regFi.Ino) } - if hardAIno == hardBIno { - t.Errorf("both hardlinks have the same inode! ino=%d", hardAIno) + if hardAFi.Ino == hardBFi.Ino { + t.Errorf("both hardlinks have the same inode! ino=%d", hardAFi.Ino) } - if hardAIno != regIno { - t.Errorf("hardlink to regular has a different inode: reg=%d hard=%d", regIno, hardAIno) + if hardAFi.Ino != regFi.Ino { + t.Errorf("hardlink to regular has a different inode: reg=%d hard=%d", regFi.Ino, hardAFi.Ino) } - if hardBIno != symIno { - t.Errorf("hardlink to symlink has a different inode: sym=%d hard=%d", symIno, hardBIno) + if hardBFi.Ino != symFi.Ino { + t.Errorf("hardlink to symlink has a different inode: sym=%d hard=%d", symFi.Ino, hardBFi.Ino) } // Double-check readlink. @@ -443,21 +437,17 @@ func TestUnpackHardlink(t *testing.T) { } // Make sure that uid and gid don't apply to hardlinks. - regUID := int(regFi.Sys().(*syscall.Stat_t).Uid) - if regUID != os.Getuid() { - t.Errorf("regular file: uid was changed by hardlink unpack: expected=%d got=%d", os.Getuid(), regUID) + if int(regFi.Uid) != os.Getuid() { + t.Errorf("regular file: uid was changed by hardlink unpack: expected=%d got=%d", os.Getuid(), regFi.Uid) } - regGID := int(regFi.Sys().(*syscall.Stat_t).Gid) - if regGID != os.Getgid() { - t.Errorf("regular file: gid was changed by hardlink unpack: expected=%d got=%d", os.Getgid(), regGID) + if int(regFi.Gid) != os.Getgid() { + t.Errorf("regular file: gid was changed by hardlink unpack: expected=%d got=%d", os.Getgid(), regFi.Gid) } - symUID := int(symFi.Sys().(*syscall.Stat_t).Uid) - if symUID != os.Getuid() { - t.Errorf("symlink: uid was changed by hardlink unpack: expected=%d got=%d", os.Getuid(), symUID) + if int(symFi.Uid) != os.Getuid() { + t.Errorf("symlink: uid was changed by hardlink unpack: expected=%d got=%d", os.Getuid(), symFi.Uid) } - symGID := int(symFi.Sys().(*syscall.Stat_t).Gid) - if symGID != os.Getgid() { - t.Errorf("symlink: gid was changed by hardlink unpack: expected=%d got=%d", os.Getgid(), symGID) + if int(symFi.Gid) != os.Getgid() { + t.Errorf("symlink: gid was changed by hardlink unpack: expected=%d got=%d", os.Getgid(), symFi.Gid) } } @@ -488,8 +478,9 @@ func TestUnpackEntryMap(t *testing.T) { t.Logf("running with uid=%#v gid=%#v", test.uidMap, test.gidMap) var ( - hdr *tar.Header - hdrUID, hdrGID int + hdrUID, hdrGID, uUID, uGID int + hdr *tar.Header + fi unix.Stat_t ctrValue = []byte("some content we won't check") regFile = "regular" @@ -519,16 +510,17 @@ func TestUnpackEntryMap(t *testing.T) { if err := te.unpackEntry(dir, hdr, bytes.NewBuffer(ctrValue)); err != nil { t.Fatalf("regfile: unexpected unpackEntry error: %s", err) } - if fi, err := os.Lstat(filepath.Join(dir, hdr.Name)); err != nil { + + if err := unix.Lstat(filepath.Join(dir, hdr.Name), &fi); err != nil { t.Errorf("failed to lstat %s: %s", hdr.Name, err) } else { - theUID := int(fi.Sys().(*syscall.Stat_t).Uid) - theGID := int(fi.Sys().(*syscall.Stat_t).Gid) - if theUID != int(test.uidMap.HostID)+hdrUID { - t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, theUID, int(test.uidMap.HostID)+hdrUID) + uUID = int(fi.Uid) + uGID = int(fi.Gid) + if uUID != int(test.uidMap.HostID)+hdrUID { + t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, uUID, int(test.uidMap.HostID)+hdrUID) } - if theGID != int(test.gidMap.HostID)+hdrGID { - t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, theGID, int(test.gidMap.HostID)+hdrGID) + if uGID != int(test.gidMap.HostID)+hdrGID { + t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, uGID, int(test.gidMap.HostID)+hdrGID) } } @@ -547,16 +539,17 @@ func TestUnpackEntryMap(t *testing.T) { if err := te.unpackEntry(dir, hdr, bytes.NewBuffer(ctrValue)); err != nil { t.Fatalf("regdir: unexpected unpackEntry error: %s", err) } - if fi, err := os.Lstat(filepath.Join(dir, hdr.Name)); err != nil { + + if err := unix.Lstat(filepath.Join(dir, hdr.Name), &fi); err != nil { t.Errorf("failed to lstat %s: %s", hdr.Name, err) } else { - theUID := int(fi.Sys().(*syscall.Stat_t).Uid) - theGID := int(fi.Sys().(*syscall.Stat_t).Gid) - if theUID != int(test.uidMap.HostID)+hdrUID { - t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, theUID, int(test.uidMap.HostID)+hdrUID) + uUID = int(fi.Uid) + uGID = int(fi.Gid) + if uUID != int(test.uidMap.HostID)+hdrUID { + t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, uUID, int(test.uidMap.HostID)+hdrUID) } - if theGID != int(test.gidMap.HostID)+hdrGID { - t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, theGID, int(test.gidMap.HostID)+hdrGID) + if uGID != int(test.gidMap.HostID)+hdrGID { + t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, uGID, int(test.gidMap.HostID)+hdrGID) } } @@ -575,16 +568,17 @@ func TestUnpackEntryMap(t *testing.T) { if err := te.unpackEntry(dir, hdr, bytes.NewBuffer(ctrValue)); err != nil { t.Fatalf("regdir: unexpected unpackEntry error: %s", err) } - if fi, err := os.Lstat(filepath.Join(dir, hdr.Name)); err != nil { + + if err := unix.Lstat(filepath.Join(dir, hdr.Name), &fi); err != nil { t.Errorf("failed to lstat %s: %s", hdr.Name, err) } else { - theUID := int(fi.Sys().(*syscall.Stat_t).Uid) - theGID := int(fi.Sys().(*syscall.Stat_t).Gid) - if theUID != int(test.uidMap.HostID)+hdrUID { - t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, theUID, int(test.uidMap.HostID)+hdrUID) + uUID = int(fi.Uid) + uGID = int(fi.Gid) + if uUID != int(test.uidMap.HostID)+hdrUID { + t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, uUID, int(test.uidMap.HostID)+hdrUID) } - if theGID != int(test.gidMap.HostID)+hdrGID { - t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, theGID, int(test.gidMap.HostID)+hdrGID) + if uGID != int(test.gidMap.HostID)+hdrGID { + t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, uGID, int(test.gidMap.HostID)+hdrGID) } } @@ -603,16 +597,17 @@ func TestUnpackEntryMap(t *testing.T) { if err := te.unpackEntry(dir, hdr, bytes.NewBuffer(ctrValue)); err != nil { t.Fatalf("regdir: unexpected unpackEntry error: %s", err) } - if fi, err := os.Lstat(filepath.Join(dir, hdr.Name)); err != nil { + + if err := unix.Lstat(filepath.Join(dir, hdr.Name), &fi); err != nil { t.Errorf("failed to lstat %s: %s", hdr.Name, err) } else { - theUID := int(fi.Sys().(*syscall.Stat_t).Uid) - theGID := int(fi.Sys().(*syscall.Stat_t).Gid) - if theUID != int(test.uidMap.HostID)+hdrUID { - t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, theUID, int(test.uidMap.HostID)+hdrUID) + uUID = int(fi.Uid) + uGID = int(fi.Gid) + if uUID != int(test.uidMap.HostID)+hdrUID { + t.Errorf("file %s has the wrong uid mapping: got=%d expected=%d", hdr.Name, uUID, int(test.uidMap.HostID)+hdrUID) } - if theGID != int(test.gidMap.HostID)+hdrGID { - t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, theGID, int(test.gidMap.HostID)+hdrGID) + if uGID != int(test.gidMap.HostID)+hdrGID { + t.Errorf("file %s has the wrong gid mapping: got=%d expected=%d", hdr.Name, uGID, int(test.gidMap.HostID)+hdrGID) } } } diff --git a/oci/layer/tar_generate.go b/oci/layer/tar_generate.go index 08fce1655..fcdec2b1c 100644 --- a/oci/layer/tar_generate.go +++ b/oci/layer/tar_generate.go @@ -64,7 +64,7 @@ type tarGenerator struct { // newTarGenerator creates a new tarGenerator using the provided writer as the // output writer. func newTarGenerator(w io.Writer, opt MapOptions) *tarGenerator { - var fsEval fseval.FsEval = fseval.DefaultFsEval + fsEval := fseval.DefaultFsEval if opt.Rootless { fsEval = fseval.RootlessFsEval } @@ -109,6 +109,7 @@ func normalise(rawPath string, isDir bool) (string, error) { // hardlinks. This should be functionally equivalent to adding entries with GNU // tar. func (tg *tarGenerator) AddFile(name, path string) error { + fi, err := tg.fsEval.Lstat(path) if err != nil { return errors.Wrap(err, "add file lstat") @@ -144,9 +145,11 @@ func (tg *tarGenerator) AddFile(name, path string) error { // Different systems have different special things they need to set within // a tar header. For example, device numbers are quite important to be set // by us. - if err := updateHeader(hdr, fi); err != nil { - return errors.Wrap(err, "update hdr header") + statx, err := tg.fsEval.Lstatx(path) + if err != nil { + return errors.Wrapf(err, "lstatx %q", path) } + updateHeader(hdr, statx) // Set up xattrs externally to updateHeader because the function signature // would look really dumb otherwise. @@ -183,24 +186,16 @@ func (tg *tarGenerator) AddFile(name, path string) error { // Not all systems have the concept of an inode, but I'm not in the mood to // handle this in a way that makes anything other than GNU/Linux happy - // right now. - ino, err := getInode(fi) - if err != nil { - return errors.Wrap(err, "get inode") - } - - // Handle hardlinks. - if oldpath, ok := tg.inodes[ino]; ok { + // right now. Handle hardlinks. + if oldpath, ok := tg.inodes[statx.Ino]; ok { // We just hit a hardlink, so we just have to change the header. hdr.Typeflag = tar.TypeLink hdr.Linkname = oldpath hdr.Size = 0 } else { - tg.inodes[ino] = name + tg.inodes[statx.Ino] = name } - // XXX: What about xattrs. - // Apply any header mappings. if err := mapHeader(hdr, tg.mapOptions); err != nil { return errors.Wrap(err, "map header") diff --git a/oci/layer/tar_unix.go b/oci/layer/tar_unix.go index 050f255a8..686ac1c2f 100644 --- a/oci/layer/tar_unix.go +++ b/oci/layer/tar_unix.go @@ -19,11 +19,9 @@ package layer import ( "archive/tar" - "fmt" - "os" - "syscall" "github.com/openSUSE/umoci/pkg/system" + "golang.org/x/sys/unix" ) // These values come from new_decode_dev() inside . @@ -36,26 +34,11 @@ func minor(device uint64) uint64 { return (device & 0xff) | ((device >> 12) & 0xfff00) } -func updateHeader(hdr *tar.Header, fi os.FileInfo) error { - s, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return fmt.Errorf("failed to cast fileinfo to *syscall.stat_t") - } - +func updateHeader(hdr *tar.Header, s unix.Stat_t) { // Currently the Go stdlib doesn't fill in the major/minor numbers of // devices, so we have to do it manually. - if s.Mode&syscall.S_IFBLK == syscall.S_IFBLK || s.Mode&syscall.S_IFCHR == syscall.S_IFCHR { + if s.Mode&unix.S_IFBLK == unix.S_IFBLK || s.Mode&unix.S_IFCHR == unix.S_IFCHR { hdr.Devmajor = int64(system.Majordev(system.Dev_t(s.Rdev))) hdr.Devminor = int64(system.Minordev(system.Dev_t(s.Rdev))) } - - return nil -} - -func getInode(fi os.FileInfo) (uint64, error) { - s, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return 0, fmt.Errorf("failed to cast fileinfo to *syscall.stat_t") - } - return s.Ino, nil } diff --git a/pkg/fseval/fseval.go b/pkg/fseval/fseval.go index 998a71e63..a57733438 100644 --- a/pkg/fseval/fseval.go +++ b/pkg/fseval/fseval.go @@ -23,6 +23,7 @@ import ( "github.com/openSUSE/umoci/pkg/system" "github.com/vbatts/go-mtree" + "golang.org/x/sys/unix" ) // Ensure that mtree.FsEval is implemented by FsEval. @@ -45,6 +46,9 @@ type FsEval interface { // Lstat is equivalent to os.Lstat. Lstat(path string) (os.FileInfo, error) + // Lstatx is equivalent to unix.Lstat. + Lstatx(path string) (unix.Stat_t, error) + // Readlink is equivalent to os.Readlink. Readlink(path string) (string, error) diff --git a/pkg/fseval/fseval_default.go b/pkg/fseval/fseval_default.go index b8c86130d..2f1a172bc 100644 --- a/pkg/fseval/fseval_default.go +++ b/pkg/fseval/fseval_default.go @@ -60,6 +60,13 @@ func (fs osFsEval) Lstat(path string) (os.FileInfo, error) { return os.Lstat(path) } +// Lstatx is equivalent to unix.Lstat. +func (fs osFsEval) Lstatx(path string) (unix.Stat_t, error) { + var s unix.Stat_t + err := unix.Lstat(path, &s) + return s, err +} + // Readlink is equivalent to os.Readlink. func (fs osFsEval) Readlink(path string) (string, error) { return os.Readlink(path) diff --git a/pkg/fseval/fseval_rootless.go b/pkg/fseval/fseval_rootless.go index 1f8cddcff..ad565b88e 100644 --- a/pkg/fseval/fseval_rootless.go +++ b/pkg/fseval/fseval_rootless.go @@ -25,6 +25,7 @@ import ( "github.com/openSUSE/umoci/pkg/system" "github.com/openSUSE/umoci/pkg/unpriv" "github.com/vbatts/go-mtree" + "golang.org/x/sys/unix" ) // RootlessFsEval is an FsEval implementation that uses "umoci/pkg/unpriv".* @@ -57,6 +58,10 @@ func (fs unprivFsEval) Lstat(path string) (os.FileInfo, error) { return unpriv.Lstat(path) } +func (fs unprivFsEval) Lstatx(path string) (unix.Stat_t, error) { + return unpriv.Lstatx(path) +} + // Readlink is equivalent to unpriv.Readlink. func (fs unprivFsEval) Readlink(path string) (string, error) { return unpriv.Readlink(path) diff --git a/pkg/system/link_linux.go b/pkg/system/link_linux.go index 49d0d096c..60838824c 100644 --- a/pkg/system/link_linux.go +++ b/pkg/system/link_linux.go @@ -17,9 +17,9 @@ package system -import "syscall" +import "golang.org/x/sys/unix" // Unlink is a wrapper around unlink(2). func Unlink(path string) error { - return syscall.Unlink(path) + return unix.Unlink(path) } diff --git a/pkg/system/mknod_linux.go b/pkg/system/mknod_linux.go index 57df791a1..83a78a8b4 100644 --- a/pkg/system/mknod_linux.go +++ b/pkg/system/mknod_linux.go @@ -20,7 +20,8 @@ package system import ( "archive/tar" "os" - "syscall" + + "golang.org/x/sys/unix" ) // Dev_t represents a dev_t structure. @@ -32,15 +33,15 @@ type Dev_t uint64 func Tarmode(typeflag byte) uint32 { switch typeflag { case tar.TypeSymlink: - return syscall.S_IFLNK + return unix.S_IFLNK case tar.TypeChar: - return syscall.S_IFCHR + return unix.S_IFCHR case tar.TypeBlock: - return syscall.S_IFBLK + return unix.S_IFBLK case tar.TypeFifo: - return syscall.S_IFIFO + return unix.S_IFIFO case tar.TypeDir: - return syscall.S_IFDIR + return unix.S_IFDIR } return 0 } @@ -66,5 +67,5 @@ func Minordev(device Dev_t) uint64 { // Mknod is a wrapper around mknod(2). func Mknod(path string, mode os.FileMode, dev Dev_t) error { - return syscall.Mknod(path, uint32(mode), int(dev)) + return unix.Mknod(path, uint32(mode), int(dev)) } diff --git a/pkg/system/utils.go b/pkg/system/utils.go index d01f0493b..500962b4c 100644 --- a/pkg/system/utils.go +++ b/pkg/system/utils.go @@ -18,12 +18,13 @@ package system import ( - "syscall" "unsafe" + + "golang.org/x/sys/unix" ) func assertPtrFromString(s string) unsafe.Pointer { - ptr, err := syscall.BytePtrFromString(s) + ptr, err := unix.BytePtrFromString(s) if err != nil { panic(err) } diff --git a/pkg/system/utime_linux.go b/pkg/system/utime_linux.go index 9da08bbda..fd901048c 100644 --- a/pkg/system/utime_linux.go +++ b/pkg/system/utime_linux.go @@ -20,20 +20,20 @@ package system import ( "os" "path/filepath" - "syscall" "time" "unsafe" "github.com/pkg/errors" + "golang.org/x/sys/unix" ) // Lutimes is a wrapper around utimensat(2), with the AT_SYMLINK_NOFOLLOW flag // set, to allow changing the time of a symlink rather than the file it points // to. func Lutimes(path string, atime, mtime time.Time) error { - var times [2]syscall.Timespec - times[0] = syscall.NsecToTimespec(atime.UnixNano()) - times[1] = syscall.NsecToTimespec(mtime.UnixNano()) + var times [2]unix.Timespec + times[0] = unix.NsecToTimespec(atime.UnixNano()) + times[1] = unix.NsecToTimespec(mtime.UnixNano()) // Split up the path. dir, file := filepath.Split(path) @@ -41,14 +41,14 @@ func Lutimes(path string, atime, mtime time.Time) error { file = filepath.Clean(file) // Open the parent directory. - dirFile, err := os.OpenFile(filepath.Clean(dir), syscall.O_RDONLY|syscall.O_NOFOLLOW|syscall.O_DIRECTORY, 0) + dirFile, err := os.OpenFile(filepath.Clean(dir), unix.O_RDONLY|unix.O_NOFOLLOW|unix.O_DIRECTORY, 0) if err != nil { return errors.Wrap(err, "lutimes: open parent directory") } defer dirFile.Close() // The interface for this is really, really silly. - _, _, errno := syscall.RawSyscall6(syscall.SYS_UTIMENSAT, // int utimensat( + _, _, errno := unix.RawSyscall6(unix.SYS_UTIMENSAT, // int utimensat( uintptr(dirFile.Fd()), // int dirfd, uintptr(assertPtrFromString(file)), // char *pathname, uintptr(unsafe.Pointer(×[0])), // struct timespec times[2], diff --git a/pkg/system/utime_linux_test.go b/pkg/system/utime_linux_test.go index 4f9a03b4b..f45970206 100644 --- a/pkg/system/utime_linux_test.go +++ b/pkg/system/utime_linux_test.go @@ -21,12 +21,15 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" "testing" "time" + + "golang.org/x/sys/unix" ) func TestLutimesFile(t *testing.T) { + var fiOld, fiNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesFile") if err != nil { t.Fatal(err) @@ -42,8 +45,7 @@ func TestLutimesFile(t *testing.T) { atime := time.Unix(125812851, 128518257) mtime := time.Unix(257172893, 995216512) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } @@ -51,15 +53,14 @@ func TestLutimesFile(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -76,6 +77,8 @@ func TestLutimesFile(t *testing.T) { } func TestLutimesDirectory(t *testing.T) { + var fiOld, fiNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesDirectory") if err != nil { t.Fatal(err) @@ -91,8 +94,7 @@ func TestLutimesDirectory(t *testing.T) { atime := time.Unix(128551231, 273285257) mtime := time.Unix(185726393, 752135712) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } @@ -100,15 +102,14 @@ func TestLutimesDirectory(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -125,6 +126,8 @@ func TestLutimesDirectory(t *testing.T) { } func TestLutimesSymlink(t *testing.T) { + var fiOld, fiParentOld, fiNew, fiParentNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesSymlink") if err != nil { t.Fatal(err) @@ -140,12 +143,10 @@ func TestLutimesSymlink(t *testing.T) { atime := time.Unix(128551231, 273285257) mtime := time.Unix(185726393, 752135712) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } - fiParentOld, err := os.Lstat(dir) - if err != nil { + if err := unix.Lstat(dir, &fiParentOld); err != nil { t.Fatal(err) } @@ -153,19 +154,17 @@ func TestLutimesSymlink(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - fiParentNew, err := os.Lstat(dir) - if err != nil { + if err := unix.Lstat(dir, &fiParentNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -181,10 +180,10 @@ func TestLutimesSymlink(t *testing.T) { } // Make sure that the parent directory was unchanged. - atimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeParentOld := time.Unix(fiParentOld.Atim.Sec, fiParentOld.Atim.Nsec) + mtimeParentOld := time.Unix(fiParentOld.Mtim.Sec, fiParentOld.Mtim.Nsec) + atimeParentNew := time.Unix(fiParentNew.Atim.Sec, fiParentNew.Atim.Nsec) + mtimeParentNew := time.Unix(fiParentNew.Mtim.Sec, fiParentNew.Mtim.Nsec) if !atimeParentOld.Equal(atimeParentNew) { t.Errorf("parent directory atime was changed! old='%s' new='%s'", atimeParentOld, atimeParentNew) @@ -195,6 +194,8 @@ func TestLutimesSymlink(t *testing.T) { } func TestLutimesRelative(t *testing.T) { + var fiOld, fiParentOld, fiNew, fiParentNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesRelative") if err != nil { t.Fatal(err) @@ -220,12 +221,10 @@ func TestLutimesRelative(t *testing.T) { atime := time.Unix(134858232, 258921237) mtime := time.Unix(171257291, 425815288) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } - fiParentOld, err := os.Lstat(".") - if err != nil { + if err := unix.Lstat(".", &fiParentOld); err != nil { t.Fatal(err) } @@ -233,19 +232,17 @@ func TestLutimesRelative(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - fiParentNew, err := os.Lstat(".") - if err != nil { + if err := unix.Lstat(".", &fiParentNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -261,10 +258,10 @@ func TestLutimesRelative(t *testing.T) { } // Make sure that the parent directory was unchanged. - atimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeParentOld := time.Unix(fiParentOld.Atim.Sec, fiParentOld.Atim.Nsec) + mtimeParentOld := time.Unix(fiParentOld.Mtim.Sec, fiParentOld.Mtim.Nsec) + atimeParentNew := time.Unix(fiParentNew.Atim.Sec, fiParentNew.Atim.Nsec) + mtimeParentNew := time.Unix(fiParentNew.Mtim.Sec, fiParentNew.Mtim.Nsec) if !atimeParentOld.Equal(atimeParentNew) { t.Errorf("parent directory atime was changed! old='%s' new='%s'", atimeParentOld, atimeParentNew) diff --git a/pkg/system/xattr_linux.go b/pkg/system/xattr_linux.go index 4ebddc7b2..8f791f3aa 100644 --- a/pkg/system/xattr_linux.go +++ b/pkg/system/xattr_linux.go @@ -20,7 +20,6 @@ package system import ( "bytes" "os" - "syscall" "github.com/pkg/errors" "golang.org/x/sys/unix" @@ -45,7 +44,7 @@ func Llistxattr(path string) ([]string, error) { // If we got an ERANGE then we have to resize the buffer because // someone raced with us getting the list. Don't you just love C // interfaces. - if serr, ok := err.(syscall.Errno); ok && serr == syscall.ERANGE { + if err == unix.ERANGE { continue } return nil, err @@ -86,7 +85,7 @@ func Lgetxattr(path string, name string) ([]byte, error) { // If we got an ERANGE then we have to resize the buffer because // someone raced with us getting the list. Don't you just love C // interfaces. - if serr, ok := err.(syscall.Errno); ok && serr == syscall.ERANGE { + if err == unix.ERANGE { continue } return nil, err diff --git a/pkg/unpriv/unpriv.go b/pkg/unpriv/unpriv.go index b81eb3ade..74517d0fb 100644 --- a/pkg/unpriv/unpriv.go +++ b/pkg/unpriv/unpriv.go @@ -23,7 +23,6 @@ import ( "os" "path/filepath" "strings" - "syscall" "time" "github.com/cyphar/filepath-securejoin" @@ -202,6 +201,15 @@ func Lstat(path string) (os.FileInfo, error) { return fi, errors.Wrap(err, "unpriv.lstat") } +// Lstatx is like Lstat but uses unix.Lstat and returns unix.Stat_t instead +func Lstatx(path string) (unix.Stat_t, error) { + var s unix.Stat_t + err := Wrap(path, func(path string) error { + return unix.Lstat(path, &s) + }) + return s, errors.Wrap(err, "unpriv.lstatx") +} + // Readlink is a wrapper around os.Readlink which has been wrapped with // unpriv.Wrap to make it possible to get the linkname of a symlink even if you // do not currently have teh required mode bits set to resolve the path. Note @@ -389,7 +397,7 @@ func MkdirAll(path string, perm os.FileMode) error { if fi.IsDir() { return nil } - return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} + return &os.PathError{Op: "mkdir", Path: path, Err: unix.ENOTDIR} } // Create parent. diff --git a/pkg/unpriv/unpriv_utimes_test.go b/pkg/unpriv/unpriv_utimes_test.go index a5ca405b6..423e808a1 100644 --- a/pkg/unpriv/unpriv_utimes_test.go +++ b/pkg/unpriv/unpriv_utimes_test.go @@ -21,12 +21,15 @@ import ( "io/ioutil" "os" "path/filepath" - "syscall" "testing" "time" + + "golang.org/x/sys/unix" ) func TestLutimesFile(t *testing.T) { + var fiOld, fiNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesFile") if err != nil { t.Fatal(err) @@ -41,8 +44,7 @@ func TestLutimesFile(t *testing.T) { atime := time.Unix(125812851, 128518257) mtime := time.Unix(257172893, 995216512) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } @@ -50,15 +52,14 @@ func TestLutimesFile(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -75,6 +76,8 @@ func TestLutimesFile(t *testing.T) { } func TestLutimesDirectory(t *testing.T) { + var fiOld, fiNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesDirectory") if err != nil { t.Fatal(err) @@ -89,8 +92,7 @@ func TestLutimesDirectory(t *testing.T) { atime := time.Unix(128551231, 273285257) mtime := time.Unix(185726393, 752135712) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } @@ -98,15 +100,14 @@ func TestLutimesDirectory(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -123,6 +124,8 @@ func TestLutimesDirectory(t *testing.T) { } func TestLutimesSymlink(t *testing.T) { + var fiOld, fiParentOld, fiNew, fiParentNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesSymlink") if err != nil { t.Fatal(err) @@ -137,12 +140,10 @@ func TestLutimesSymlink(t *testing.T) { atime := time.Unix(128551231, 273285257) mtime := time.Unix(185726393, 752135712) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } - fiParentOld, err := os.Lstat(dir) - if err != nil { + if err := unix.Lstat(dir, &fiParentOld); err != nil { t.Fatal(err) } @@ -150,19 +151,17 @@ func TestLutimesSymlink(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - fiParentNew, err := os.Lstat(dir) - if err != nil { + if err := unix.Lstat(dir, &fiParentNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -178,10 +177,10 @@ func TestLutimesSymlink(t *testing.T) { } // Make sure that the parent directory was unchanged. - atimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeParentOld := time.Unix(fiParentOld.Atim.Sec, fiParentOld.Atim.Nsec) + mtimeParentOld := time.Unix(fiParentOld.Mtim.Sec, fiParentOld.Mtim.Nsec) + atimeParentNew := time.Unix(fiParentNew.Atim.Sec, fiParentNew.Atim.Nsec) + mtimeParentNew := time.Unix(fiParentNew.Mtim.Sec, fiParentNew.Mtim.Nsec) if !atimeParentOld.Equal(atimeParentNew) { t.Errorf("parent directory atime was changed! old='%s' new='%s'", atimeParentOld, atimeParentNew) @@ -192,6 +191,8 @@ func TestLutimesSymlink(t *testing.T) { } func TestLutimesRelative(t *testing.T) { + var fiOld, fiParentOld, fiNew, fiParentNew unix.Stat_t + dir, err := ioutil.TempDir("", "umoci-system.TestLutimesRelative") if err != nil { t.Fatal(err) @@ -217,12 +218,10 @@ func TestLutimesRelative(t *testing.T) { atime := time.Unix(134858232, 258921237) mtime := time.Unix(171257291, 425815288) - fiOld, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiOld); err != nil { t.Fatal(err) } - fiParentOld, err := os.Lstat(".") - if err != nil { + if err := unix.Lstat(".", &fiParentOld); err != nil { t.Fatal(err) } @@ -230,19 +229,17 @@ func TestLutimesRelative(t *testing.T) { t.Errorf("unexpected error with system.lutimes: %s", err) } - fiNew, err := os.Lstat(path) - if err != nil { + if err := unix.Lstat(path, &fiNew); err != nil { t.Fatal(err) } - fiParentNew, err := os.Lstat(".") - if err != nil { + if err := unix.Lstat(".", &fiParentNew); err != nil { t.Fatal(err) } - atimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeOld := time.Unix(fiOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeNew := time.Unix(fiNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeOld := time.Unix(fiOld.Atim.Sec, fiOld.Atim.Nsec) + mtimeOld := time.Unix(fiOld.Mtim.Sec, fiOld.Mtim.Nsec) + atimeNew := time.Unix(fiNew.Atim.Sec, fiNew.Atim.Nsec) + mtimeNew := time.Unix(fiNew.Mtim.Sec, fiNew.Mtim.Nsec) if atimeOld.Equal(atimeNew) { t.Errorf("atime was not changed at all!") @@ -258,10 +255,10 @@ func TestLutimesRelative(t *testing.T) { } // Make sure that the parent directory was unchanged. - atimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentOld := time.Unix(fiParentOld.Sys().(*syscall.Stat_t).Mtim.Unix()) - atimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Atim.Unix()) - mtimeParentNew := time.Unix(fiParentNew.Sys().(*syscall.Stat_t).Mtim.Unix()) + atimeParentOld := time.Unix(fiParentOld.Atim.Sec, fiParentOld.Atim.Nsec) + mtimeParentOld := time.Unix(fiParentOld.Mtim.Sec, fiParentOld.Mtim.Nsec) + atimeParentNew := time.Unix(fiParentNew.Atim.Sec, fiParentNew.Atim.Nsec) + mtimeParentNew := time.Unix(fiParentNew.Mtim.Sec, fiParentNew.Mtim.Nsec) if !atimeParentOld.Equal(atimeParentNew) { t.Errorf("parent directory atime was changed! old='%s' new='%s'", atimeParentOld, atimeParentNew)