...

Source file src/pkg/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	// +build aix linux darwin dragonfly freebsd openbsd netbsd solaris
     6	
     7	package tar
     8	
     9	import (
    10		"os"
    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 os.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":
    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