github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/archive/tar/stat_unix.go (about) 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 unix 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 }