fix chown and seccomp
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
60f032f6f5
commit
2569457739
8197 changed files with 30742 additions and 1596554 deletions
53
vendor/github.com/containerd/continuity/fs/fstest/compare.go
generated
vendored
53
vendor/github.com/containerd/continuity/fs/fstest/compare.go
generated
vendored
|
@ -1,53 +0,0 @@
|
|||
package fstest
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/continuity"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// CheckDirectoryEqual compares two directory paths to make sure that
|
||||
// the content of the directories is the same.
|
||||
func CheckDirectoryEqual(d1, d2 string) error {
|
||||
c1, err := continuity.NewContext(d1)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to build context")
|
||||
}
|
||||
|
||||
c2, err := continuity.NewContext(d2)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to build context")
|
||||
}
|
||||
|
||||
m1, err := continuity.BuildManifest(c1)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to build manifest")
|
||||
}
|
||||
|
||||
m2, err := continuity.BuildManifest(c2)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to build manifest")
|
||||
}
|
||||
|
||||
diff := diffResourceList(m1.Resources, m2.Resources)
|
||||
if diff.HasDiff() {
|
||||
return errors.Errorf("directory diff between %s and %s\n%s", d1, d2, diff.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckDirectoryEqualWithApplier compares directory against applier
|
||||
func CheckDirectoryEqualWithApplier(root string, a Applier) error {
|
||||
applied, err := ioutil.TempDir("", "fstest")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(applied)
|
||||
if err := a.Apply(applied); err != nil {
|
||||
return err
|
||||
}
|
||||
return CheckDirectoryEqual(applied, root)
|
||||
}
|
189
vendor/github.com/containerd/continuity/fs/fstest/continuity_util.go
generated
vendored
189
vendor/github.com/containerd/continuity/fs/fstest/continuity_util.go
generated
vendored
|
@ -1,189 +0,0 @@
|
|||
package fstest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/containerd/continuity"
|
||||
)
|
||||
|
||||
type resourceUpdate struct {
|
||||
Original continuity.Resource
|
||||
Updated continuity.Resource
|
||||
}
|
||||
|
||||
func (u resourceUpdate) String() string {
|
||||
return fmt.Sprintf("%s(mode: %o, uid: %d, gid: %d) -> %s(mode: %o, uid: %d, gid: %d)",
|
||||
u.Original.Path(), u.Original.Mode(), u.Original.UID(), u.Original.GID(),
|
||||
u.Updated.Path(), u.Updated.Mode(), u.Updated.UID(), u.Updated.GID(),
|
||||
)
|
||||
}
|
||||
|
||||
type resourceListDifference struct {
|
||||
Additions []continuity.Resource
|
||||
Deletions []continuity.Resource
|
||||
Updates []resourceUpdate
|
||||
}
|
||||
|
||||
func (l resourceListDifference) HasDiff() bool {
|
||||
return len(l.Additions) > 0 || len(l.Deletions) > 0 || len(l.Updates) > 0
|
||||
}
|
||||
|
||||
func (l resourceListDifference) String() string {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
for _, add := range l.Additions {
|
||||
fmt.Fprintf(buf, "+ %s\n", add.Path())
|
||||
}
|
||||
for _, del := range l.Deletions {
|
||||
fmt.Fprintf(buf, "- %s\n", del.Path())
|
||||
}
|
||||
for _, upt := range l.Updates {
|
||||
fmt.Fprintf(buf, "~ %s\n", upt.String())
|
||||
}
|
||||
return string(buf.Bytes())
|
||||
}
|
||||
|
||||
// diffManifest compares two resource lists and returns the list
|
||||
// of adds updates and deletes, resource lists are not reordered
|
||||
// before doing difference.
|
||||
func diffResourceList(r1, r2 []continuity.Resource) resourceListDifference {
|
||||
i1 := 0
|
||||
i2 := 0
|
||||
var d resourceListDifference
|
||||
|
||||
for i1 < len(r1) && i2 < len(r2) {
|
||||
p1 := r1[i1].Path()
|
||||
p2 := r2[i2].Path()
|
||||
switch {
|
||||
case p1 < p2:
|
||||
d.Deletions = append(d.Deletions, r1[i1])
|
||||
i1++
|
||||
case p1 == p2:
|
||||
if !compareResource(r1[i1], r2[i2]) {
|
||||
d.Updates = append(d.Updates, resourceUpdate{
|
||||
Original: r1[i1],
|
||||
Updated: r2[i2],
|
||||
})
|
||||
}
|
||||
i1++
|
||||
i2++
|
||||
case p1 > p2:
|
||||
d.Additions = append(d.Additions, r2[i2])
|
||||
i2++
|
||||
}
|
||||
}
|
||||
|
||||
for i1 < len(r1) {
|
||||
d.Deletions = append(d.Deletions, r1[i1])
|
||||
i1++
|
||||
|
||||
}
|
||||
for i2 < len(r2) {
|
||||
d.Additions = append(d.Additions, r2[i2])
|
||||
i2++
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func compareResource(r1, r2 continuity.Resource) bool {
|
||||
if r1.Path() != r2.Path() {
|
||||
return false
|
||||
}
|
||||
if r1.Mode() != r2.Mode() {
|
||||
return false
|
||||
}
|
||||
if r1.UID() != r2.UID() {
|
||||
return false
|
||||
}
|
||||
if r1.GID() != r2.GID() {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO(dmcgowan): Check if is XAttrer
|
||||
|
||||
return compareResourceTypes(r1, r2)
|
||||
|
||||
}
|
||||
|
||||
func compareResourceTypes(r1, r2 continuity.Resource) bool {
|
||||
switch t1 := r1.(type) {
|
||||
case continuity.RegularFile:
|
||||
t2, ok := r2.(continuity.RegularFile)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return compareRegularFile(t1, t2)
|
||||
case continuity.Directory:
|
||||
t2, ok := r2.(continuity.Directory)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return compareDirectory(t1, t2)
|
||||
case continuity.SymLink:
|
||||
t2, ok := r2.(continuity.SymLink)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return compareSymLink(t1, t2)
|
||||
case continuity.NamedPipe:
|
||||
t2, ok := r2.(continuity.NamedPipe)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return compareNamedPipe(t1, t2)
|
||||
case continuity.Device:
|
||||
t2, ok := r2.(continuity.Device)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return compareDevice(t1, t2)
|
||||
default:
|
||||
// TODO(dmcgowan): Should this panic?
|
||||
return r1 == r2
|
||||
}
|
||||
}
|
||||
|
||||
func compareRegularFile(r1, r2 continuity.RegularFile) bool {
|
||||
if r1.Size() != r2.Size() {
|
||||
return false
|
||||
}
|
||||
p1 := r1.Paths()
|
||||
p2 := r2.Paths()
|
||||
if len(p1) != len(p2) {
|
||||
return false
|
||||
}
|
||||
for i := range p1 {
|
||||
if p1[i] != p2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
d1 := r1.Digests()
|
||||
d2 := r2.Digests()
|
||||
if len(d1) != len(d2) {
|
||||
return false
|
||||
}
|
||||
for i := range d1 {
|
||||
if d1[i] != d2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func compareSymLink(r1, r2 continuity.SymLink) bool {
|
||||
return r1.Target() == r2.Target()
|
||||
}
|
||||
|
||||
func compareDirectory(r1, r2 continuity.Directory) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func compareNamedPipe(r1, r2 continuity.NamedPipe) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func compareDevice(r1, r2 continuity.Device) bool {
|
||||
return r1.Major() == r2.Major() && r1.Minor() == r2.Minor()
|
||||
}
|
120
vendor/github.com/containerd/continuity/fs/fstest/file.go
generated
vendored
120
vendor/github.com/containerd/continuity/fs/fstest/file.go
generated
vendored
|
@ -1,120 +0,0 @@
|
|||
package fstest
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Applier applies single file changes
|
||||
type Applier interface {
|
||||
Apply(root string) error
|
||||
}
|
||||
|
||||
type applyFn func(root string) error
|
||||
|
||||
func (a applyFn) Apply(root string) error {
|
||||
return a(root)
|
||||
}
|
||||
|
||||
// CreateFile returns a file applier which creates a file as the
|
||||
// provided name with the given content and permission.
|
||||
func CreateFile(name string, content []byte, perm os.FileMode) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
fullPath := filepath.Join(root, name)
|
||||
if err := ioutil.WriteFile(fullPath, content, perm); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chmod(fullPath, perm)
|
||||
})
|
||||
}
|
||||
|
||||
// Remove returns a file applier which removes the provided file name
|
||||
func Remove(name string) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Remove(filepath.Join(root, name))
|
||||
})
|
||||
}
|
||||
|
||||
// RemoveAll returns a file applier which removes the provided file name
|
||||
// as in os.RemoveAll
|
||||
func RemoveAll(name string) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.RemoveAll(filepath.Join(root, name))
|
||||
})
|
||||
}
|
||||
|
||||
// CreateDir returns a file applier to create the directory with
|
||||
// the provided name and permission
|
||||
func CreateDir(name string, perm os.FileMode) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
fullPath := filepath.Join(root, name)
|
||||
if err := os.MkdirAll(fullPath, perm); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chmod(fullPath, perm)
|
||||
})
|
||||
}
|
||||
|
||||
// Rename returns a file applier which renames a file
|
||||
func Rename(old, new string) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Rename(filepath.Join(root, old), filepath.Join(root, new))
|
||||
})
|
||||
}
|
||||
|
||||
// Chown returns a file applier which changes the ownership of a file
|
||||
func Chown(name string, uid, gid int) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Chown(filepath.Join(root, name), uid, gid)
|
||||
})
|
||||
}
|
||||
|
||||
// Chtimes changes access and mod time of file.
|
||||
// Use Lchtimes for symbolic links.
|
||||
func Chtimes(name string, atime, mtime time.Time) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Chtimes(filepath.Join(root, name), atime, mtime)
|
||||
})
|
||||
}
|
||||
|
||||
// Chmod returns a file applier which changes the file permission
|
||||
func Chmod(name string, perm os.FileMode) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Chmod(filepath.Join(root, name), perm)
|
||||
})
|
||||
}
|
||||
|
||||
// Symlink returns a file applier which creates a symbolic link
|
||||
func Symlink(oldname, newname string) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Symlink(oldname, filepath.Join(root, newname))
|
||||
})
|
||||
}
|
||||
|
||||
// Link returns a file applier which creates a hard link
|
||||
func Link(oldname, newname string) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return os.Link(filepath.Join(root, oldname), filepath.Join(root, newname))
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Make platform specific, windows applier is always no-op
|
||||
//func Mknod(name string, mode int32, dev int) Applier {
|
||||
// return func(root string) error {
|
||||
// return return syscall.Mknod(path, mode, dev)
|
||||
// }
|
||||
//}
|
||||
|
||||
// Apply returns a new applier from the given appliers
|
||||
func Apply(appliers ...Applier) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
for _, a := range appliers {
|
||||
if err := a.Apply(root); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
29
vendor/github.com/containerd/continuity/fs/fstest/file_unix.go
generated
vendored
29
vendor/github.com/containerd/continuity/fs/fstest/file_unix.go
generated
vendored
|
@ -1,29 +0,0 @@
|
|||
// +build !windows
|
||||
|
||||
package fstest
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/continuity/sysx"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// SetXAttr sets the xatter for the file
|
||||
func SetXAttr(name, key, value string) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return sysx.LSetxattr(name, key, []byte(value), 0)
|
||||
})
|
||||
}
|
||||
|
||||
// Lchtimes changes access and mod time of file without following symlink
|
||||
func Lchtimes(name string, atime, mtime time.Time) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
path := filepath.Join(root, name)
|
||||
at := unix.NsecToTimespec(atime.UnixNano())
|
||||
mt := unix.NsecToTimespec(mtime.UnixNano())
|
||||
utimes := [2]unix.Timespec{at, mt}
|
||||
return unix.UtimesNanoAt(unix.AT_FDCWD, path, utimes[0:], unix.AT_SYMLINK_NOFOLLOW)
|
||||
})
|
||||
}
|
14
vendor/github.com/containerd/continuity/fs/fstest/file_windows.go
generated
vendored
14
vendor/github.com/containerd/continuity/fs/fstest/file_windows.go
generated
vendored
|
@ -1,14 +0,0 @@
|
|||
package fstest
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Lchtimes changes access and mod time of file without following symlink
|
||||
func Lchtimes(name string, atime, mtime time.Time) Applier {
|
||||
return applyFn(func(root string) error {
|
||||
return errors.New("Not implemented")
|
||||
})
|
||||
}
|
220
vendor/github.com/containerd/continuity/fs/fstest/testsuite.go
generated
vendored
220
vendor/github.com/containerd/continuity/fs/fstest/testsuite.go
generated
vendored
|
@ -1,220 +0,0 @@
|
|||
package fstest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestApplier applies the test context
|
||||
type TestApplier interface {
|
||||
TestContext(context.Context) (context.Context, func(), error)
|
||||
Apply(context.Context, Applier) (string, func(), error)
|
||||
}
|
||||
|
||||
// FSSuite runs the path test suite
|
||||
func FSSuite(t *testing.T, a TestApplier) {
|
||||
t.Run("Basic", makeTest(t, a, basicTest))
|
||||
t.Run("Deletion", makeTest(t, a, deletionTest))
|
||||
t.Run("Update", makeTest(t, a, updateTest))
|
||||
t.Run("DirectoryPermission", makeTest(t, a, directoryPermissionsTest))
|
||||
t.Run("ParentDirectoryPermission", makeTest(t, a, parentDirectoryPermissionsTest))
|
||||
t.Run("HardlinkUnmodified", makeTest(t, a, hardlinkUnmodified))
|
||||
t.Run("HardlinkBeforeUnmodified", makeTest(t, a, hardlinkBeforeUnmodified))
|
||||
t.Run("HardlinkBeforeModified", makeTest(t, a, hardlinkBeforeModified))
|
||||
}
|
||||
|
||||
func makeTest(t *testing.T, ta TestApplier, as []Applier) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
ctx, cleanup, err := ta.TestContext(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to get test context: %+v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
applyDir, err := ioutil.TempDir("", "test-expected-")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to make temp directory: %+v", err)
|
||||
}
|
||||
defer os.RemoveAll(applyDir)
|
||||
|
||||
for i, a := range as {
|
||||
testDir, c, err := ta.Apply(ctx, a)
|
||||
if err != nil {
|
||||
t.Fatalf("Apply failed at %d: %+v", i, err)
|
||||
}
|
||||
if err := a.Apply(applyDir); err != nil {
|
||||
if c != nil {
|
||||
c()
|
||||
}
|
||||
t.Fatalf("Error applying change to apply directory: %+v", err)
|
||||
}
|
||||
|
||||
err = CheckDirectoryEqual(applyDir, testDir)
|
||||
if c != nil {
|
||||
c()
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Directories not equal at %d (expected <> tested): %+v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// baseApplier creates a basic filesystem layout
|
||||
// with multiple types of files for basic tests.
|
||||
baseApplier = Apply(
|
||||
CreateDir("/etc/", 0755),
|
||||
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
|
||||
Link("/etc/hosts", "/etc/hosts.allow"),
|
||||
CreateDir("/usr/local/lib", 0755),
|
||||
CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0755),
|
||||
Symlink("libnothing.so", "/usr/local/lib/libnothing.so.2"),
|
||||
CreateDir("/home", 0755),
|
||||
CreateDir("/home/derek", 0700),
|
||||
)
|
||||
|
||||
// basicTest covers basic operations
|
||||
basicTest = []Applier{
|
||||
baseApplier,
|
||||
Apply(
|
||||
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||
CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0600),
|
||||
CreateFile("/etc/badfile", []byte(""), 0666),
|
||||
CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640),
|
||||
),
|
||||
Apply(
|
||||
Remove("/etc/badfile"),
|
||||
Rename("/home/derek", "/home/notderek"),
|
||||
),
|
||||
Apply(
|
||||
RemoveAll("/usr"),
|
||||
Remove("/etc/hosts.allow"),
|
||||
),
|
||||
Apply(
|
||||
RemoveAll("/home"),
|
||||
CreateDir("/home/derek", 0700),
|
||||
CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640),
|
||||
Link("/etc/hosts", "/etc/hosts.allow"),
|
||||
),
|
||||
}
|
||||
|
||||
// deletionTest covers various deletion scenarios to ensure
|
||||
// deletions are properly picked up and applied
|
||||
deletionTest = []Applier{
|
||||
Apply(
|
||||
CreateDir("/test/somedir", 0755),
|
||||
CreateDir("/lib", 0700),
|
||||
CreateFile("/lib/hidden", []byte{}, 0644),
|
||||
),
|
||||
Apply(
|
||||
CreateFile("/test/a", []byte{}, 0644),
|
||||
CreateFile("/test/b", []byte{}, 0644),
|
||||
CreateDir("/test/otherdir", 0755),
|
||||
CreateFile("/test/otherdir/.empty", []byte{}, 0644),
|
||||
RemoveAll("/lib"),
|
||||
CreateDir("/lib", 0700),
|
||||
CreateFile("/lib/not-hidden", []byte{}, 0644),
|
||||
),
|
||||
Apply(
|
||||
Remove("/test/a"),
|
||||
Remove("/test/b"),
|
||||
RemoveAll("/test/otherdir"),
|
||||
CreateFile("/lib/newfile", []byte{}, 0644),
|
||||
),
|
||||
}
|
||||
|
||||
// updateTest covers file updates for content and permission
|
||||
updateTest = []Applier{
|
||||
Apply(
|
||||
CreateDir("/d1", 0755),
|
||||
CreateDir("/d2", 0700),
|
||||
CreateFile("/d1/f1", []byte("something..."), 0644),
|
||||
CreateFile("/d1/f2", []byte("else..."), 0644),
|
||||
CreateFile("/d1/f3", []byte("entirely..."), 0644),
|
||||
),
|
||||
Apply(
|
||||
CreateFile("/d1/f1", []byte("file content of a different length"), 0664),
|
||||
Remove("/d1/f3"),
|
||||
CreateFile("/d1/f3", []byte("updated content"), 0664),
|
||||
Chmod("/d1/f2", 0766),
|
||||
Chmod("/d2", 0777),
|
||||
),
|
||||
}
|
||||
|
||||
// directoryPermissionsTest covers directory permissions on update
|
||||
directoryPermissionsTest = []Applier{
|
||||
Apply(
|
||||
CreateDir("/d1", 0700),
|
||||
CreateDir("/d2", 0751),
|
||||
CreateDir("/d3", 0777),
|
||||
),
|
||||
Apply(
|
||||
CreateFile("/d1/f", []byte("irrelevant"), 0644),
|
||||
CreateDir("/d1/d", 0700),
|
||||
CreateFile("/d1/d/f", []byte("irrelevant"), 0644),
|
||||
CreateFile("/d2/f", []byte("irrelevant"), 0644),
|
||||
CreateFile("/d3/f", []byte("irrelevant"), 0644),
|
||||
),
|
||||
}
|
||||
|
||||
// parentDirectoryPermissionsTest covers directory permissions for updated
|
||||
// files
|
||||
parentDirectoryPermissionsTest = []Applier{
|
||||
Apply(
|
||||
CreateDir("/d1", 0700),
|
||||
CreateDir("/d1/a", 0700),
|
||||
CreateDir("/d1/a/b", 0700),
|
||||
CreateDir("/d1/a/b/c", 0700),
|
||||
CreateFile("/d1/a/b/f", []byte("content1"), 0644),
|
||||
CreateDir("/d2", 0751),
|
||||
CreateDir("/d2/a/b", 0751),
|
||||
CreateDir("/d2/a/b/c", 0751),
|
||||
CreateFile("/d2/a/b/f", []byte("content1"), 0644),
|
||||
),
|
||||
Apply(
|
||||
CreateFile("/d1/a/b/f", []byte("content1"), 0644),
|
||||
Chmod("/d1/a/b/c", 0700),
|
||||
CreateFile("/d2/a/b/f", []byte("content2"), 0644),
|
||||
Chmod("/d2/a/b/c", 0751),
|
||||
),
|
||||
}
|
||||
|
||||
hardlinkUnmodified = []Applier{
|
||||
baseApplier,
|
||||
Apply(
|
||||
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||
),
|
||||
Apply(
|
||||
Link("/etc/hosts", "/etc/hosts.deny"),
|
||||
),
|
||||
}
|
||||
|
||||
// Hardlink name before with modification
|
||||
// Tests link is created for unmodified files when new hardlinked file is seen first
|
||||
hardlinkBeforeUnmodified = []Applier{
|
||||
baseApplier,
|
||||
Apply(
|
||||
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||
),
|
||||
Apply(
|
||||
Link("/etc/hosts", "/etc/before-hosts"),
|
||||
),
|
||||
}
|
||||
|
||||
// Hardlink name after without modification
|
||||
// tests link is created for modified file with new hardlink
|
||||
hardlinkBeforeModified = []Applier{
|
||||
baseApplier,
|
||||
Apply(
|
||||
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||
),
|
||||
Apply(
|
||||
Remove("/etc/hosts"),
|
||||
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
|
||||
Link("/etc/hosts", "/etc/before-hosts"),
|
||||
),
|
||||
}
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue