]> Cypherpunks.ru repositories - gostls13.git/blob - src/archive/tar/stat_unix.go
0f3428bc24b47d3683ace47bd38bd0548f7d5dd7
[gostls13.git] / 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 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 }