1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 "golang.org/x/sys/unix"
17 var testData = []byte("This is a test\n")
19 // stringsFromByteSlice converts a sequence of attributes to a []string.
20 // On Darwin, each entry is a NULL-terminated string.
21 func stringsFromByteSlice(buf []byte) []string {
24 for i, b := range buf {
26 result = append(result, string(buf[off:i]))
33 func createTestFile(t *testing.T, dir string) (f *os.File, cleanup func() error) {
34 file, err := ioutil.TempFile(dir, t.Name())
39 _, err = file.Write(testData)
49 return file, func() error {
50 return os.Remove(file.Name())
54 func TestClonefile(t *testing.T) {
55 file, cleanup := createTestFile(t, "")
58 clonedName := file.Name() + "-cloned"
59 err := unix.Clonefile(file.Name(), clonedName, 0)
60 if err == unix.ENOSYS || err == unix.ENOTSUP {
61 t.Skip("clonefile is not available or supported, skipping test")
62 } else if err != nil {
65 defer os.Remove(clonedName)
67 clonedData, err := ioutil.ReadFile(clonedName)
72 if !bytes.Equal(testData, clonedData) {
73 t.Errorf("Clonefile: got %q, expected %q", clonedData, testData)
77 func TestClonefileatWithCwd(t *testing.T) {
78 file, cleanup := createTestFile(t, "")
81 clonedName := file.Name() + "-cloned"
82 err := unix.Clonefileat(unix.AT_FDCWD, file.Name(), unix.AT_FDCWD, clonedName, 0)
83 if err == unix.ENOSYS || err == unix.ENOTSUP {
84 t.Skip("clonefileat is not available or supported, skipping test")
85 } else if err != nil {
88 defer os.Remove(clonedName)
90 clonedData, err := ioutil.ReadFile(clonedName)
95 if !bytes.Equal(testData, clonedData) {
96 t.Errorf("Clonefileat: got %q, expected %q", clonedData, testData)
100 func TestClonefileatWithRelativePaths(t *testing.T) {
101 srcDir, err := ioutil.TempDir("", "src")
105 defer os.RemoveAll(srcDir)
107 dstDir, err := ioutil.TempDir("", "dest")
111 defer os.RemoveAll(dstDir)
113 srcFd, err := unix.Open(srcDir, unix.O_RDONLY|unix.O_DIRECTORY, 0)
117 defer unix.Close(srcFd)
119 dstFd, err := unix.Open(dstDir, unix.O_RDONLY|unix.O_DIRECTORY, 0)
123 defer unix.Close(dstFd)
125 srcFile, cleanup := createTestFile(t, srcDir)
128 dstFile, err := ioutil.TempFile(dstDir, "TestClonefileat")
132 err = os.Remove(dstFile.Name())
137 src := path.Base(srcFile.Name())
138 dst := path.Base(dstFile.Name())
139 err = unix.Clonefileat(srcFd, src, dstFd, dst, 0)
140 if err == unix.ENOSYS || err == unix.ENOTSUP {
141 t.Skip("clonefileat is not available or supported, skipping test")
142 } else if err != nil {
146 clonedData, err := ioutil.ReadFile(dstFile.Name())
151 if !bytes.Equal(testData, clonedData) {
152 t.Errorf("Clonefileat: got %q, expected %q", clonedData, testData)
156 func TestFclonefileat(t *testing.T) {
157 file, cleanup := createTestFile(t, "")
160 fd, err := unix.Open(file.Name(), unix.O_RDONLY, 0)
166 dstFile, err := ioutil.TempFile("", "TestFclonefileat")
170 os.Remove(dstFile.Name())
172 err = unix.Fclonefileat(fd, unix.AT_FDCWD, dstFile.Name(), 0)
173 if err == unix.ENOSYS || err == unix.ENOTSUP {
174 t.Skip("clonefileat is not available or supported, skipping test")
175 } else if err != nil {
179 clonedData, err := ioutil.ReadFile(dstFile.Name())
184 if !bytes.Equal(testData, clonedData) {
185 t.Errorf("Fclonefileat: got %q, expected %q", clonedData, testData)
189 func TestFcntlFstore(t *testing.T) {
190 f, err := ioutil.TempFile("", t.Name())
194 defer os.Remove(f.Name())
197 fstore := &unix.Fstore_t{
198 Flags: unix.F_ALLOCATEALL,
199 Posmode: unix.F_PEOFPOSMODE,
203 err = unix.FcntlFstore(f.Fd(), unix.F_PREALLOCATE, fstore)
204 if err == unix.EOPNOTSUPP {
205 t.Skipf("fcntl with F_PREALLOCATE not supported, skipping test")
206 } else if err != nil {
207 t.Fatalf("FcntlFstore: %v", err)
216 t.Errorf("FcntlFstore: got size = %d, want %d", st.Size(), 0)