1 // Copyright 2009 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.
5 // Package tar implements access to tar archives.
6 // It aims to cover most of the variations, including those produced
7 // by GNU and BSD tars.
10 // http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5
11 // http://www.gnu.org/software/tar/manual/html_node/Standard.html
12 // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html
28 TypeReg = '0' // regular file
29 TypeRegA = '\x00' // regular file
30 TypeLink = '1' // hard link
31 TypeSymlink = '2' // symbolic link
32 TypeChar = '3' // character device node
33 TypeBlock = '4' // block device node
34 TypeDir = '5' // directory
35 TypeFifo = '6' // fifo node
36 TypeCont = '7' // reserved
37 TypeXHeader = 'x' // extended header
38 TypeXGlobalHeader = 'g' // global extended header
39 TypeGNULongName = 'L' // Next file has a long name
40 TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name
41 TypeGNUSparse = 'S' // sparse file
44 // A Header represents a single header in a tar archive.
45 // Some fields may not be populated.
47 Name string // name of header file entry
48 Mode int64 // permission and mode bits
49 Uid int // user id of owner
50 Gid int // group id of owner
51 Size int64 // length in bytes
52 ModTime time.Time // modified time
53 Typeflag byte // type of header entry
54 Linkname string // target name of link
55 Uname string // user name of owner
56 Gname string // group name of owner
57 Devmajor int64 // major number of character or block device
58 Devminor int64 // minor number of character or block device
59 AccessTime time.Time // access time
60 ChangeTime time.Time // status change time
61 Xattrs map[string]string
64 // File name constants from the tar spec.
66 fileNameSize = 100 // Maximum number of bytes in a standard tar name.
67 fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
70 // FileInfo returns an os.FileInfo for the Header.
71 func (h *Header) FileInfo() os.FileInfo {
72 return headerFileInfo{h}
75 // headerFileInfo implements os.FileInfo.
76 type headerFileInfo struct {
80 func (fi headerFileInfo) Size() int64 { return fi.h.Size }
81 func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
82 func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime }
83 func (fi headerFileInfo) Sys() interface{} { return fi.h }
85 // Name returns the base name of the file.
86 func (fi headerFileInfo) Name() string {
88 return path.Base(path.Clean(fi.h.Name))
90 return path.Base(fi.h.Name)
93 // Mode returns the permission and mode bits for the headerFileInfo.
94 func (fi headerFileInfo) Mode() (mode os.FileMode) {
95 // Set file permission bits.
96 mode = os.FileMode(fi.h.Mode).Perm()
98 // Set setuid, setgid and sticky bits.
99 if fi.h.Mode&c_ISUID != 0 {
101 mode |= os.ModeSetuid
103 if fi.h.Mode&c_ISGID != 0 {
105 mode |= os.ModeSetgid
107 if fi.h.Mode&c_ISVTX != 0 {
109 mode |= os.ModeSticky
112 // Set file mode bits.
113 // clear perm, setuid, setgid and sticky bits.
114 m := os.FileMode(fi.h.Mode) &^ 07777
121 mode |= os.ModeNamedPipe
125 mode |= os.ModeSymlink
129 mode |= os.ModeDevice
132 // Unix character device
133 mode |= os.ModeDevice
134 mode |= os.ModeCharDevice
137 // Unix domain socket
138 mode |= os.ModeSocket
141 switch fi.h.Typeflag {
144 mode |= os.ModeSymlink
146 // character device node
147 mode |= os.ModeDevice
148 mode |= os.ModeCharDevice
151 mode |= os.ModeDevice
157 mode |= os.ModeNamedPipe
163 // sysStat, if non-nil, populates h from system-dependent fields of fi.
164 var sysStat func(fi os.FileInfo, h *Header) error
166 // Mode constants from the tar spec.
168 c_ISUID = 04000 // Set uid
169 c_ISGID = 02000 // Set gid
170 c_ISVTX = 01000 // Save text (sticky bit)
171 c_ISDIR = 040000 // Directory
172 c_ISFIFO = 010000 // FIFO
173 c_ISREG = 0100000 // Regular file
174 c_ISLNK = 0120000 // Symbolic link
175 c_ISBLK = 060000 // Block special file
176 c_ISCHR = 020000 // Character special file
177 c_ISSOCK = 0140000 // Socket
180 // Keywords for the PAX Extended Header
183 paxCharset = "charset"
184 paxComment = "comment"
185 paxCtime = "ctime" // please note that ctime is not a valid pax header.
188 paxLinkpath = "linkpath"
194 paxXattr = "SCHILY.xattr."
198 // FileInfoHeader creates a partially-populated Header from fi.
199 // If fi describes a symlink, FileInfoHeader records link as the link target.
200 // If fi describes a directory, a slash is appended to the name.
201 // Because os.FileInfo's Name method returns only the base name of
202 // the file it describes, it may be necessary to modify the Name field
203 // of the returned header to provide the full path name of the file.
204 func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
206 return nil, errors.New("tar: FileInfo is nil")
211 ModTime: fi.ModTime(),
212 Mode: int64(fm.Perm()), // or'd with c_IS* constants later
223 case fm&os.ModeSymlink != 0:
224 h.Typeflag = TypeSymlink
227 case fm&os.ModeDevice != 0:
228 if fm&os.ModeCharDevice != 0 {
230 h.Typeflag = TypeChar
233 h.Typeflag = TypeBlock
235 case fm&os.ModeNamedPipe != 0:
236 h.Typeflag = TypeFifo
238 case fm&os.ModeSocket != 0:
241 return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
243 if fm&os.ModeSetuid != 0 {
246 if fm&os.ModeSetgid != 0 {
249 if fm&os.ModeSticky != 0 {
252 // If possible, populate additional fields from OS-specific
254 if sys, ok := fi.Sys().(*Header); ok {
255 // This FileInfo came from a Header (not the OS). Use the
256 // original Header to populate all remaining fields.
261 h.AccessTime = sys.AccessTime
262 h.ChangeTime = sys.ChangeTime
263 if sys.Xattrs != nil {
264 h.Xattrs = make(map[string]string)
265 for k, v := range sys.Xattrs {
269 if sys.Typeflag == TypeLink {
271 h.Typeflag = TypeLink
273 h.Linkname = sys.Linkname
277 return h, sysStat(fi, h)
282 var zeroBlock = make([]byte, blockSize)
284 // POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signed byte values.
285 // We compute and return both.
286 func checksum(header []byte) (unsigned int64, signed int64) {
287 for i := 0; i < len(header); i++ {
289 // The chksum field (header[148:156]) is special: it should be treated as space bytes.
295 unsigned += int64(header[i])
296 signed += int64(int8(header[i]))
303 func (sp *slicer) next(n int) (b []byte) {
305 b, *sp = s[0:n], s[n:]
309 func isASCII(s string) bool {
310 for _, c := range s {
318 func toASCII(s string) string {
323 for _, c := range s {
325 buf.WriteByte(byte(c))
331 // isHeaderOnlyType checks if the given type flag is of the type that has no
332 // data section even if a size is specified.
333 func isHeaderOnlyType(flag byte) bool {
335 case TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, TypeFifo: