1
16
17 package fs
18
19 import (
20 "fmt"
21 "os"
22 "syscall"
23
24 "github.com/containerd/continuity/sysx"
25 "golang.org/x/sys/unix"
26 )
27
28 func copyFileInfo(fi os.FileInfo, src, name string) error {
29 st := fi.Sys().(*syscall.Stat_t)
30 if err := os.Lchown(name, int(st.Uid), int(st.Gid)); err != nil {
31 if os.IsPermission(err) {
32
33
34
35 if dstStat, err2 := os.Lstat(name); err2 == nil {
36 st2 := dstStat.Sys().(*syscall.Stat_t)
37 if st.Uid == st2.Uid && st.Gid == st2.Gid {
38 err = nil
39 }
40 }
41 }
42 if err != nil {
43 return fmt.Errorf("failed to chown %s: %w", name, err)
44 }
45 }
46
47 if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
48 if err := os.Chmod(name, fi.Mode()); err != nil {
49 return fmt.Errorf("failed to chmod %s: %w", name, err)
50 }
51 }
52
53 timespec := []unix.Timespec{
54 unix.NsecToTimespec(syscall.TimespecToNsec(StatAtime(st))),
55 unix.NsecToTimespec(syscall.TimespecToNsec(StatMtime(st))),
56 }
57 if err := unix.UtimesNanoAt(unix.AT_FDCWD, name, timespec, unix.AT_SYMLINK_NOFOLLOW); err != nil {
58 return fmt.Errorf("failed to utime %s: %w", name, err)
59 }
60
61 return nil
62 }
63
64 func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAttrErrorHandler) error {
65 xattrKeys, err := sysx.LListxattr(src)
66 if err != nil {
67 e := fmt.Errorf("failed to list xattrs on %s: %w", src, err)
68 if errorHandler != nil {
69 e = errorHandler(dst, src, "", e)
70 }
71 return e
72 }
73 for _, xattr := range xattrKeys {
74 if _, exclude := excludes[xattr]; exclude {
75 continue
76 }
77 data, err := sysx.LGetxattr(src, xattr)
78 if err != nil {
79 e := fmt.Errorf("failed to get xattr %q on %s: %w", xattr, src, err)
80 if errorHandler != nil {
81 if e = errorHandler(dst, src, xattr, e); e == nil {
82 continue
83 }
84 }
85 return e
86 }
87 if err := sysx.LSetxattr(dst, xattr, data, 0); err != nil {
88 e := fmt.Errorf("failed to set xattr %q on %s: %w", xattr, dst, err)
89 if errorHandler != nil {
90 if e = errorHandler(dst, src, xattr, e); e == nil {
91 continue
92 }
93 }
94 return e
95 }
96 }
97
98 return nil
99 }
100
View as plain text