WriteFile adds a file to the tarball with the specified name using the srcPath file as the contents of the file. The ignoreGrowth argument indicates whether to error if the srcPath file increases in size beyond the size in fi during the write. If false the write will return an error. If true, no err
(name string, srcPath string, fi os.FileInfo, ignoreGrowth bool)
| 44 | // during the write. If false the write will return an error. If true, no error is returned, instead only the size |
| 45 | // specified in fi is written to the tarball. This can be used when you don't need a consistent copy of the file. |
| 46 | func (ctw *InstanceTarWriter) WriteFile(name string, srcPath string, fi os.FileInfo, ignoreGrowth bool) error { |
| 47 | var err error |
| 48 | var major, minor uint32 |
| 49 | var nlink int |
| 50 | var ino uint64 |
| 51 | |
| 52 | link := "" |
| 53 | if fi.Mode()&os.ModeSymlink == os.ModeSymlink { |
| 54 | link, err = os.Readlink(srcPath) |
| 55 | if err != nil { |
| 56 | return fmt.Errorf("Failed to resolve symlink for %q: %w", srcPath, err) |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | // Sockets cannot be stored in tarballs, just skip them (consistent with tar). |
| 61 | if fi.Mode()&os.ModeSocket == os.ModeSocket { |
| 62 | return nil |
| 63 | } |
| 64 | |
| 65 | hdr, err := tar.FileInfoHeader(fi, link) |
| 66 | if err != nil { |
| 67 | return fmt.Errorf("Failed to create tar info header: %w", err) |
| 68 | } |
| 69 | |
| 70 | hdr.Name = name |
| 71 | if fi.IsDir() || fi.Mode()&os.ModeSymlink == os.ModeSymlink { |
| 72 | hdr.Size = 0 |
| 73 | } else { |
| 74 | hdr.Size = fi.Size() |
| 75 | } |
| 76 | |
| 77 | // Get file stat. |
| 78 | var stat unix.Stat_t |
| 79 | err = unix.Lstat(srcPath, &stat) |
| 80 | if err != nil { |
| 81 | return fmt.Errorf("Failed to get file stat: %w", err) |
| 82 | } |
| 83 | |
| 84 | hdr.Uid = int(stat.Uid) |
| 85 | hdr.Gid = int(stat.Gid) |
| 86 | ino = stat.Ino |
| 87 | nlink = int(stat.Nlink) |
| 88 | |
| 89 | if stat.Mode&unix.S_IFBLK != 0 || stat.Mode&unix.S_IFCHR != 0 { |
| 90 | major = unix.Major(uint64(stat.Rdev)) |
| 91 | minor = unix.Minor(uint64(stat.Rdev)) |
| 92 | } |
| 93 | |
| 94 | // Unshift the id under rootfs/ for unpriv containers. |
| 95 | if strings.HasPrefix(hdr.Name, "rootfs") && ctw.idmapSet != nil { |
| 96 | hUID, hGID := ctw.idmapSet.ShiftFromNS(int64(hdr.Uid), int64(hdr.Gid)) |
| 97 | hdr.Uid = int(hUID) |
| 98 | hdr.Gid = int(hGID) |
| 99 | if hdr.Uid == -1 || hdr.Gid == -1 { |
| 100 | return nil |
| 101 | } |
| 102 | } |
| 103 |
no test coverage detected