mirror of
https://github.com/containers/podman
synced 2024-10-19 16:54:07 +00:00
pkg/ctime: Factor libpod/finished* into a separate package
This removes some boilerplate from the libpod package, so we can focus
on container stuff there. And it gives us a tidy sub-package for
focusing on ctime extraction, so we can focus on unit testing and
portability of the extraction utility there.
For the unsupported implementation, I'm falling back to Go's ModTime
[1]. That's obviously not the creation time, but it's likely to be
closer than the uninitialized Time structure from cc6f0e85
(more
changes to compile darwin, 2018-07-04, #1047). Especially for our use
case in libpod/oci, where we're looking at write-once exit files.
The test is more complicated than I initially expected, because on
Linux filesystem timestamps come from a truncated clock without
interpolation [2] (and network filesystems can be completely decoupled
[3]). So even for local disks, creation times can be up to a jiffie
earlier than 'before'. This test ensures at least monotonicity by
creating two files and ensuring the reported creation time for the
second is greater than or equal to the reported creation time for the
first. It also checks that both creation times are within the window
from one second earlier than 'before' through 'after'. That should be
enough of a window for local disks, even if the kernel for those
systems has an abnormally large jiffie. It might be ok on network
filesystems, although it will not be very resilient to network clock
lagging behind the local system clock.
[1]: https://golang.org/pkg/os/#FileInfo
[2]: https://groups.google.com/d/msg/linux.kernel/mdeXx2TBYZA/_4eJEuJoAQAJ
Subject: Re: Apparent backward time travel in timestamps on file creation
Date: Thu, 30 Mar 2017 20:20:02 +0200
Message-ID: <tqMPU-1Sb-21@gated-at.bofh.it>
[3]: https://groups.google.com/d/msg/linux.kernel/mdeXx2TBYZA/cTKj4OBuAQAJ
Subject: Re: Apparent backward time travel in timestamps on file creation
Date: Thu, 30 Mar 2017 22:10:01 +0200
Message-ID: <tqOyl-36A-1@gated-at.bofh.it>
Signed-off-by: W. Trevor King <wking@tremily.us>
Closes: #1050
Approved by: mheon
This commit is contained in:
parent
aaab26fd0c
commit
b2344b83ed
|
@ -1,16 +0,0 @@
|
|||
// +build arm 386
|
||||
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Get created time of a file
|
||||
// Only works on 32-bit OSes
|
||||
func getFinishedTime(fi os.FileInfo) time.Time {
|
||||
st := fi.Sys().(*syscall.Stat_t)
|
||||
return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec))
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// +build darwin,!linux
|
||||
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func getFinishedTime(fi os.FileInfo) time.Time {
|
||||
return time.Time{}
|
||||
}
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/pkg/ctime"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
kwait "k8s.io/apimachinery/pkg/util/wait"
|
||||
|
@ -422,7 +423,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
ctr.state.FinishedTime = getFinishedTime(fi)
|
||||
ctr.state.FinishedTime = ctime.Created(fi)
|
||||
statusCodeStr, err := ioutil.ReadFile(exitFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to read exit file for container %s", ctr.ID())
|
||||
|
|
12
pkg/ctime/ctime.go
Normal file
12
pkg/ctime/ctime.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Package ctime includes a utility for determining file-creation times.
|
||||
package ctime
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Created returns the file-creation time.
|
||||
func Created(fi os.FileInfo) time.Time {
|
||||
return created(fi)
|
||||
}
|
14
pkg/ctime/ctime_linux_32.go
Normal file
14
pkg/ctime/ctime_linux_32.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build arm,linux 386,linux
|
||||
|
||||
package ctime
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func created(fi os.FileInfo) time.Time {
|
||||
st := fi.Sys().(*syscall.Stat_t)
|
||||
return time.Unix(int64(st.Ctim.Sec), int64(st.Ctim.Nsec))
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// +build !arm,!386,linux
|
||||
|
||||
package libpod
|
||||
package ctime
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
@ -8,9 +8,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Get the created time of a file
|
||||
// Only works on 64-bit OSes
|
||||
func getFinishedTime(fi os.FileInfo) time.Time {
|
||||
func created(fi os.FileInfo) time.Time {
|
||||
st := fi.Sys().(*syscall.Stat_t)
|
||||
return time.Unix(st.Ctim.Sec, st.Ctim.Nsec)
|
||||
}
|
63
pkg/ctime/ctime_test.go
Normal file
63
pkg/ctime/ctime_test.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package ctime
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCreated(t *testing.T) {
|
||||
before := time.Now()
|
||||
|
||||
fileA, err := ioutil.TempFile("", "ctime-test-")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer os.Remove(fileA.Name())
|
||||
|
||||
fileB, err := ioutil.TempFile("", "ctime-test-")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer os.Remove(fileB.Name())
|
||||
|
||||
after := time.Now()
|
||||
|
||||
infoA, err := fileA.Stat()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
err = fileA.Close()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
infoB, err := fileB.Stat()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
err = fileB.Close()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
createdA := Created(infoA)
|
||||
beforeToCreateA := createdA.Sub(before)
|
||||
if beforeToCreateA.Nanoseconds() < -1000000000 {
|
||||
t.Errorf("created file A %s is %v nanoseconds before %s", createdA, -beforeToCreateA.Nanoseconds(), before)
|
||||
}
|
||||
|
||||
createdB := Created(infoB)
|
||||
createAToCreateB := createdB.Sub(createdA)
|
||||
if createAToCreateB.Nanoseconds() < 0 {
|
||||
t.Errorf("created file B %s is %v nanoseconds before file A %s", createdB, -createAToCreateB.Nanoseconds(), createdA)
|
||||
}
|
||||
|
||||
createBToAfter := after.Sub(createdB)
|
||||
if createBToAfter.Nanoseconds() < 0 {
|
||||
t.Errorf("created file B %s is %v nanoseconds after %s", createdB, -createBToAfter.Nanoseconds(), after)
|
||||
}
|
||||
}
|
12
pkg/ctime/ctime_unsupported.go
Normal file
12
pkg/ctime/ctime_unsupported.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build !linux
|
||||
|
||||
package ctime
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func created(fi os.FileInfo) time.Time {
|
||||
return fi.ModTime()
|
||||
}
|
Loading…
Reference in a new issue