forked from toolshed/abra
		
	
		
			
				
	
	
		
			87 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build !windows
 | |
| 
 | |
| package archive
 | |
| 
 | |
| import (
 | |
| 	"archive/tar"
 | |
| 	"errors"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 	"syscall"
 | |
| 
 | |
| 	"golang.org/x/sys/unix"
 | |
| )
 | |
| 
 | |
| // addLongPathPrefix adds the Windows long path prefix to the path provided if
 | |
| // it does not already have it. It is a no-op on platforms other than Windows.
 | |
| func addLongPathPrefix(srcPath string) string {
 | |
| 	return srcPath
 | |
| }
 | |
| 
 | |
| // getWalkRoot calculates the root path when performing a TarWithOptions.
 | |
| // We use a separate function as this is platform specific. On Linux, we
 | |
| // can't use filepath.Join(srcPath,include) because this will clean away
 | |
| // a trailing "." or "/" which may be important.
 | |
| func getWalkRoot(srcPath string, include string) string {
 | |
| 	return strings.TrimSuffix(srcPath, string(filepath.Separator)) + string(filepath.Separator) + include
 | |
| }
 | |
| 
 | |
| // chmodTarEntry is used to adjust the file permissions used in tar header based
 | |
| // on the platform the archival is done.
 | |
| func chmodTarEntry(perm os.FileMode) os.FileMode {
 | |
| 	return perm // noop for unix as golang APIs provide perm bits correctly
 | |
| }
 | |
| 
 | |
| func getInodeFromStat(stat interface{}) (uint64, error) {
 | |
| 	s, ok := stat.(*syscall.Stat_t)
 | |
| 	if !ok {
 | |
| 		// FIXME(thaJeztah): this should likely return an error; see https://github.com/moby/moby/pull/49493#discussion_r1979152897
 | |
| 		return 0, nil
 | |
| 	}
 | |
| 	return s.Ino, nil
 | |
| }
 | |
| 
 | |
| func getFileUIDGID(stat interface{}) (int, int, error) {
 | |
| 	s, ok := stat.(*syscall.Stat_t)
 | |
| 
 | |
| 	if !ok {
 | |
| 		return 0, 0, errors.New("cannot convert stat value to syscall.Stat_t")
 | |
| 	}
 | |
| 	return int(s.Uid), int(s.Gid), nil
 | |
| }
 | |
| 
 | |
| // handleTarTypeBlockCharFifo is an OS-specific helper function used by
 | |
| // createTarFile to handle the following types of header: Block; Char; Fifo.
 | |
| //
 | |
| // Creating device nodes is not supported when running in a user namespace,
 | |
| // produces a [syscall.EPERM] in most cases.
 | |
| func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
 | |
| 	mode := uint32(hdr.Mode & 0o7777)
 | |
| 	switch hdr.Typeflag {
 | |
| 	case tar.TypeBlock:
 | |
| 		mode |= unix.S_IFBLK
 | |
| 	case tar.TypeChar:
 | |
| 		mode |= unix.S_IFCHR
 | |
| 	case tar.TypeFifo:
 | |
| 		mode |= unix.S_IFIFO
 | |
| 	}
 | |
| 
 | |
| 	return mknod(path, mode, unix.Mkdev(uint32(hdr.Devmajor), uint32(hdr.Devminor)))
 | |
| }
 | |
| 
 | |
| func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
 | |
| 	if hdr.Typeflag == tar.TypeLink {
 | |
| 		if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) {
 | |
| 			if err := os.Chmod(path, hdrInfo.Mode()); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 	} else if hdr.Typeflag != tar.TypeSymlink {
 | |
| 		if err := os.Chmod(path, hdrInfo.Mode()); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 |