Source file src/archive/tar/stat_unix.go

     1  // Copyright 2012 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.
     4  
     5  //go:build aix || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris
     6  
     7  package tar
     8  
     9  import (
    10  	"io/fs"
    11  	"os/user"
    12  	"runtime"
    13  	"strconv"
    14  	"sync"
    15  	"syscall"
    16  )
    17  
    18  func init() {
    19  	sysStat = statUnix
    20  }
    21  
    22  // userMap and groupMap caches UID and GID lookups for performance reasons.
    23  // The downside is that renaming uname or gname by the OS never takes effect.
    24  var userMap, groupMap sync.Map // map[int]string
    25  
    26  func statUnix(fi fs.FileInfo, h *Header) error {
    27  	sys, ok := fi.Sys().(*syscall.Stat_t)
    28  	if !ok {
    29  		return nil
    30  	}
    31  	h.Uid = int(sys.Uid)
    32  	h.Gid = int(sys.Gid)
    33  
    34  	// Best effort at populating Uname and Gname.
    35  	// The os/user functions may fail for any number of reasons
    36  	// (not implemented on that platform, cgo not enabled, etc).
    37  	if u, ok := userMap.Load(h.Uid); ok {
    38  		h.Uname = u.(string)
    39  	} else if u, err := user.LookupId(strconv.Itoa(h.Uid)); err == nil {
    40  		h.Uname = u.Username
    41  		userMap.Store(h.Uid, h.Uname)
    42  	}
    43  	if g, ok := groupMap.Load(h.Gid); ok {
    44  		h.Gname = g.(string)
    45  	} else if g, err := user.LookupGroupId(strconv.Itoa(h.Gid)); err == nil {
    46  		h.Gname = g.Name
    47  		groupMap.Store(h.Gid, h.Gname)
    48  	}
    49  
    50  	h.AccessTime = statAtime(sys)
    51  	h.ChangeTime = statCtime(sys)
    52  
    53  	// Best effort at populating Devmajor and Devminor.
    54  	if h.Typeflag == TypeChar || h.Typeflag == TypeBlock {
    55  		dev := uint64(sys.Rdev) // May be int32 or uint32
    56  		switch runtime.GOOS {
    57  		case "aix":
    58  			var major, minor uint32
    59  			major = uint32((dev & 0x3fffffff00000000) >> 32)
    60  			minor = uint32((dev & 0x00000000ffffffff) >> 0)
    61  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    62  		case "linux":
    63  			// Copied from golang.org/x/sys/unix/dev_linux.go.
    64  			major := uint32((dev & 0x00000000000fff00) >> 8)
    65  			major |= uint32((dev & 0xfffff00000000000) >> 32)
    66  			minor := uint32((dev & 0x00000000000000ff) >> 0)
    67  			minor |= uint32((dev & 0x00000ffffff00000) >> 12)
    68  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    69  		case "darwin", "ios":
    70  			// Copied from golang.org/x/sys/unix/dev_darwin.go.
    71  			major := uint32((dev >> 24) & 0xff)
    72  			minor := uint32(dev & 0xffffff)
    73  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    74  		case "dragonfly":
    75  			// Copied from golang.org/x/sys/unix/dev_dragonfly.go.
    76  			major := uint32((dev >> 8) & 0xff)
    77  			minor := uint32(dev & 0xffff00ff)
    78  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    79  		case "freebsd":
    80  			// Copied from golang.org/x/sys/unix/dev_freebsd.go.
    81  			major := uint32((dev >> 8) & 0xff)
    82  			minor := uint32(dev & 0xffff00ff)
    83  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    84  		case "netbsd":
    85  			// Copied from golang.org/x/sys/unix/dev_netbsd.go.
    86  			major := uint32((dev & 0x000fff00) >> 8)
    87  			minor := uint32((dev & 0x000000ff) >> 0)
    88  			minor |= uint32((dev & 0xfff00000) >> 12)
    89  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    90  		case "openbsd":
    91  			// Copied from golang.org/x/sys/unix/dev_openbsd.go.
    92  			major := uint32((dev & 0x0000ff00) >> 8)
    93  			minor := uint32((dev & 0x000000ff) >> 0)
    94  			minor |= uint32((dev & 0xffff0000) >> 8)
    95  			h.Devmajor, h.Devminor = int64(major), int64(minor)
    96  		default:
    97  			// TODO: Implement solaris (see https://golang.org/issue/8106)
    98  		}
    99  	}
   100  	return nil
   101  }
   102  

View as plain text