// 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.

//go:build unix

package tar

import (
	
	
	
	
	
	
)

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( fs.FileInfo,  *Header) error {
	,  := .Sys().(*syscall.Stat_t)
	if ! {
		return nil
	}
	.Uid = int(.Uid)
	.Gid = int(.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 ,  := userMap.Load(.Uid);  {
		.Uname = .(string)
	} else if ,  := user.LookupId(strconv.Itoa(.Uid));  == nil {
		.Uname = .Username
		userMap.Store(.Uid, .Uname)
	}
	if ,  := groupMap.Load(.Gid);  {
		.Gname = .(string)
	} else if ,  := user.LookupGroupId(strconv.Itoa(.Gid));  == nil {
		.Gname = .Name
		groupMap.Store(.Gid, .Gname)
	}

	.AccessTime = statAtime()
	.ChangeTime = statCtime()

	// Best effort at populating Devmajor and Devminor.
	if .Typeflag == TypeChar || .Typeflag == TypeBlock {
		 := uint64(.Rdev) // May be int32 or uint32
		switch runtime.GOOS {
		case "aix":
			var ,  uint32
			 = uint32(( & 0x3fffffff00000000) >> 32)
			 = uint32(( & 0x00000000ffffffff) >> 0)
			.Devmajor, .Devminor = int64(), int64()
		case "linux":
			// Copied from golang.org/x/sys/unix/dev_linux.go.
			 := uint32(( & 0x00000000000fff00) >> 8)
			 |= uint32(( & 0xfffff00000000000) >> 32)
			 := uint32(( & 0x00000000000000ff) >> 0)
			 |= uint32(( & 0x00000ffffff00000) >> 12)
			.Devmajor, .Devminor = int64(), int64()
		case "darwin", "ios":
			// Copied from golang.org/x/sys/unix/dev_darwin.go.
			 := uint32(( >> 24) & 0xff)
			 := uint32( & 0xffffff)
			.Devmajor, .Devminor = int64(), int64()
		case "dragonfly":
			// Copied from golang.org/x/sys/unix/dev_dragonfly.go.
			 := uint32(( >> 8) & 0xff)
			 := uint32( & 0xffff00ff)
			.Devmajor, .Devminor = int64(), int64()
		case "freebsd":
			// Copied from golang.org/x/sys/unix/dev_freebsd.go.
			 := uint32(( >> 8) & 0xff)
			 := uint32( & 0xffff00ff)
			.Devmajor, .Devminor = int64(), int64()
		case "netbsd":
			// Copied from golang.org/x/sys/unix/dev_netbsd.go.
			 := uint32(( & 0x000fff00) >> 8)
			 := uint32(( & 0x000000ff) >> 0)
			 |= uint32(( & 0xfff00000) >> 12)
			.Devmajor, .Devminor = int64(), int64()
		case "openbsd":
			// Copied from golang.org/x/sys/unix/dev_openbsd.go.
			 := uint32(( & 0x0000ff00) >> 8)
			 := uint32(( & 0x000000ff) >> 0)
			 |= uint32(( & 0xffff0000) >> 8)
			.Devmajor, .Devminor = int64(), int64()
		default:
			// TODO: Implement solaris (see https://golang.org/issue/8106)
		}
	}
	return nil
}