func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
	if fi == nil {
		return nil, errors.New("tar: FileInfo is nil")
	}
	fm := fi.Mode()
	h := &Header{
		Name:    fi.Name(),
		ModTime: fi.ModTime(),
		Mode:    int64(fm.Perm()),  
	}
	switch {
	case fm.IsRegular():
		h.Mode |= c_ISREG
		h.Typeflag = TypeReg
		h.Size = fi.Size()
	case fi.IsDir():
		h.Typeflag = TypeDir
		h.Mode |= c_ISDIR
		h.Name += "/"
	case fm&os.ModeSymlink != 0:
		h.Typeflag = TypeSymlink
		h.Mode |= c_ISLNK
		h.Linkname = link
	case fm&os.ModeDevice != 0:
		if fm&os.ModeCharDevice != 0 {
			h.Mode |= c_ISCHR
			h.Typeflag = TypeChar
		} else {
			h.Mode |= c_ISBLK
			h.Typeflag = TypeBlock
		}
	case fm&os.ModeNamedPipe != 0:
		h.Typeflag = TypeFifo
		h.Mode |= c_ISFIFO
	case fm&os.ModeSocket != 0:
		h.Mode |= c_ISSOCK
	default:
		return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
	}
	if fm&os.ModeSetuid != 0 {
		h.Mode |= c_ISUID
	}
	if fm&os.ModeSetgid != 0 {
		h.Mode |= c_ISGID
	}
	if fm&os.ModeSticky != 0 {
		h.Mode |= c_ISVTX
	}
	if sys, ok := fi.Sys().(*Header); ok {
		h.Uid = sys.Uid
		h.Gid = sys.Gid
		h.Uname = sys.Uname
		h.Gname = sys.Gname
		h.AccessTime = sys.AccessTime
		h.ChangeTime = sys.ChangeTime
		if sys.Xattrs != nil {
			h.Xattrs = make(map[string]string)
			for k, v := range sys.Xattrs {
				h.Xattrs[k] = v
			}
		}
		if sys.Typeflag == TypeLink {
			h.Typeflag = TypeLink
			h.Size = 0
			h.Linkname = sys.Linkname
		}
	}
	if sysStat != nil {
		return h, sysStat(fi, h)
	}
	return h, nil
}
FileInfoHeader creates a partially-populated Header from fi.
If fi describes a symlink, FileInfoHeader records link as the link target.
If fi describes a directory, a slash is appended to the name.
Because os.FileInfo's Name method returns only the base name of
the file it describes, it may be necessary to modify the Name field
of the returned header to provide the full path name of the file.
package tar
import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"path"
	"time"
)
const (
	blockSize = 512
	TypeReg           = '0'     
	TypeRegA          = '\x00'  
	TypeLink          = '1'     
	TypeSymlink       = '2'     
	TypeChar          = '3'     
	TypeBlock         = '4'     
	TypeDir           = '5'     
	TypeFifo          = '6'     
	TypeCont          = '7'     
	TypeXHeader       = 'x'     
	TypeXGlobalHeader = 'g'     
	TypeGNULongName   = 'L'     
	TypeGNULongLink   = 'K'     
	TypeGNUSparse     = 'S'     
)
type Header struct {
	Name       string     
	Mode       int64      
	Uid        int        
	Gid        int        
	Size       int64      
	ModTime    time.Time  
	Typeflag   byte       
	Linkname   string     
	Uname      string     
	Gname      string     
	Devmajor   int64      
	Devminor   int64      
	AccessTime time.Time  
	ChangeTime time.Time  
	Xattrs     map[string]string
}
const (
	fileNameSize       = 100  
	fileNamePrefixSize = 155  
)
func (h *Header) FileInfo() os.FileInfo {
	return headerFileInfo{h}
}
type headerFileInfo struct {
	h *Header
}
func (fi headerFileInfo) Size() int64        { return fi.h.Size }
func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime }
func (fi headerFileInfo) Sys() interface{}   { return fi.h }
func (fi headerFileInfo) Name() string {
	if fi.IsDir() {
		return path.Base(path.Clean(fi.h.Name))
	}
	return path.Base(fi.h.Name)
}
func (fi headerFileInfo) Mode() (mode os.FileMode) {
	mode = os.FileMode(fi.h.Mode).Perm()
	if fi.h.Mode&c_ISUID != 0 {
		mode |= os.ModeSetuid
	}
	if fi.h.Mode&c_ISGID != 0 {
		mode |= os.ModeSetgid
	}
	if fi.h.Mode&c_ISVTX != 0 {
		mode |= os.ModeSticky
	}
	m := os.FileMode(fi.h.Mode) &^ 07777
	if m == c_ISDIR {
		mode |= os.ModeDir
	}
	if m == c_ISFIFO {
		mode |= os.ModeNamedPipe
	}
	if m == c_ISLNK {
		mode |= os.ModeSymlink
	}
	if m == c_ISBLK {
		mode |= os.ModeDevice
	}
	if m == c_ISCHR {
		mode |= os.ModeDevice
		mode |= os.ModeCharDevice
	}
	if m == c_ISSOCK {
		mode |= os.ModeSocket
	}
	switch fi.h.Typeflag {
	case TypeSymlink:
		mode |= os.ModeSymlink
	case TypeChar:
		mode |= os.ModeDevice
		mode |= os.ModeCharDevice
	case TypeBlock:
		mode |= os.ModeDevice
	case TypeDir:
		mode |= os.ModeDir
	case TypeFifo:
		mode |= os.ModeNamedPipe
	}
	return mode
}
var sysStat func(fi os.FileInfo, h *Header) error
const (
	c_ISUID  = 04000    
	c_ISGID  = 02000    
	c_ISVTX  = 01000    
	c_ISDIR  = 040000   
	c_ISFIFO = 010000   
	c_ISREG  = 0100000  
	c_ISLNK  = 0120000  
	c_ISBLK  = 060000   
	c_ISCHR  = 020000   
	c_ISSOCK = 0140000  
)
const (
	paxAtime    = "atime"
	paxCharset  = "charset"
	paxComment  = "comment"
	paxCtime    = "ctime"  
	paxGid      = "gid"
	paxGname    = "gname"
	paxLinkpath = "linkpath"
	paxMtime    = "mtime"
	paxPath     = "path"
	paxSize     = "size"
	paxUid      = "uid"
	paxUname    = "uname"
	paxXattr    = "SCHILY.xattr."
	paxNone     = ""
)