...
Run Format

Source file src/archive/tar/stat_unix.go

Documentation: archive/tar

  // Copyright 2012 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // +build linux darwin dragonfly freebsd openbsd netbsd solaris
  
  package tar
  
  import (
  	"os"
  	"os/user"
  	"runtime"
  	"strconv"
  	"sync"
  	"syscall"
  )
  
  func init() {
  	sysStat = statUnix
  }
  
  // userMap and groupMap caches UID and GID lookups for performance reasons.
  // The downside is that renaming uname or gname by the OS never takes effect.
  var userMap, groupMap sync.Map // map[int]string
  
  func statUnix(fi os.FileInfo, h *Header) error {
  	sys, ok := fi.Sys().(*syscall.Stat_t)
  	if !ok {
  		return nil
  	}
  	h.Uid = int(sys.Uid)
  	h.Gid = int(sys.Gid)
  
  	// Best effort at populating Uname and Gname.
  	// The os/user functions may fail for any number of reasons
  	// (not implemented on that platform, cgo not enabled, etc).
  	if u, ok := userMap.Load(h.Uid); ok {
  		h.Uname = u.(string)
  	} else if u, err := user.LookupId(strconv.Itoa(h.Uid)); err == nil {
  		h.Uname = u.Username
  		userMap.Store(h.Uid, h.Uname)
  	}
  	if g, ok := groupMap.Load(h.Gid); ok {
  		h.Gname = g.(string)
  	} else if g, err := user.LookupGroupId(strconv.Itoa(h.Gid)); err == nil {
  		h.Gname = g.Name
  		groupMap.Store(h.Gid, h.Gname)
  	}
  
  	h.AccessTime = statAtime(sys)
  	h.ChangeTime = statCtime(sys)
  
  	// Best effort at populating Devmajor and Devminor.
  	if h.Typeflag == TypeChar || h.Typeflag == TypeBlock {
  		dev := uint64(sys.Rdev) // May be int32 or uint32
  		switch runtime.GOOS {
  		case "linux":
  			// Copied from golang.org/x/sys/unix/dev_linux.go.
  			major := uint32((dev & 0x00000000000fff00) >> 8)
  			major |= uint32((dev & 0xfffff00000000000) >> 32)
  			minor := uint32((dev & 0x00000000000000ff) >> 0)
  			minor |= uint32((dev & 0x00000ffffff00000) >> 12)
  			h.Devmajor, h.Devminor = int64(major), int64(minor)
  		case "darwin":
  			// Copied from golang.org/x/sys/unix/dev_darwin.go.
  			major := uint32((dev >> 24) & 0xff)
  			minor := uint32(dev & 0xffffff)
  			h.Devmajor, h.Devminor = int64(major), int64(minor)
  		case "dragonfly":
  			// Copied from golang.org/x/sys/unix/dev_dragonfly.go.
  			major := uint32((dev >> 8) & 0xff)
  			minor := uint32(dev & 0xffff00ff)
  			h.Devmajor, h.Devminor = int64(major), int64(minor)
  		case "freebsd":
  			// Copied from golang.org/x/sys/unix/dev_freebsd.go.
  			major := uint32((dev >> 8) & 0xff)
  			minor := uint32(dev & 0xffff00ff)
  			h.Devmajor, h.Devminor = int64(major), int64(minor)
  		case "netbsd":
  			// Copied from golang.org/x/sys/unix/dev_netbsd.go.
  			major := uint32((dev & 0x000fff00) >> 8)
  			minor := uint32((dev & 0x000000ff) >> 0)
  			minor |= uint32((dev & 0xfff00000) >> 12)
  			h.Devmajor, h.Devminor = int64(major), int64(minor)
  		case "openbsd":
  			// Copied from golang.org/x/sys/unix/dev_openbsd.go.
  			major := uint32((dev & 0x0000ff00) >> 8)
  			minor := uint32((dev & 0x000000ff) >> 0)
  			minor |= uint32((dev & 0xffff0000) >> 8)
  			h.Devmajor, h.Devminor = int64(major), int64(minor)
  		default:
  			// TODO: Implement solaris (see https://golang.org/issue/8106)
  		}
  	}
  	return nil
  }
  

View as plain text