LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Package tar implements access to tar archives. | 5 // Package tar implements access to tar archives. |
6 // It aims to cover most of the variations, including those produced | 6 // It aims to cover most of the variations, including those produced |
7 // by GNU and BSD tars. | 7 // by GNU and BSD tars. |
8 // | 8 // |
9 // References: | 9 // References: |
10 // http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 | 10 // http://www.freebsd.org/cgi/man.cgi?query=tar&sektion=5 |
11 // http://www.gnu.org/software/tar/manual/html_node/Standard.html | 11 // http://www.gnu.org/software/tar/manual/html_node/Standard.html |
12 // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html | 12 // http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html |
13 package tar | 13 package tar |
14 | 14 |
15 import ( | 15 import ( |
16 "errors" | 16 "errors" |
17 "fmt" | 17 "fmt" |
18 "os" | 18 "os" |
| 19 "path" |
19 "time" | 20 "time" |
20 ) | 21 ) |
21 | 22 |
22 const ( | 23 const ( |
23 blockSize = 512 | 24 blockSize = 512 |
24 | 25 |
25 // Types | 26 // Types |
26 TypeReg = '0' // regular file | 27 TypeReg = '0' // regular file |
27 TypeRegA = '\x00' // regular file | 28 TypeRegA = '\x00' // regular file |
28 TypeLink = '1' // hard link | 29 TypeLink = '1' // hard link |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 // FileInfo returns an os.FileInfo for the Header. | 67 // FileInfo returns an os.FileInfo for the Header. |
67 func (h *Header) FileInfo() os.FileInfo { | 68 func (h *Header) FileInfo() os.FileInfo { |
68 return headerFileInfo{h} | 69 return headerFileInfo{h} |
69 } | 70 } |
70 | 71 |
71 // headerFileInfo implements os.FileInfo. | 72 // headerFileInfo implements os.FileInfo. |
72 type headerFileInfo struct { | 73 type headerFileInfo struct { |
73 h *Header | 74 h *Header |
74 } | 75 } |
75 | 76 |
76 func (fi headerFileInfo) Name() string { return fi.h.Name } | |
77 func (fi headerFileInfo) Size() int64 { return fi.h.Size } | 77 func (fi headerFileInfo) Size() int64 { return fi.h.Size } |
78 func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } | 78 func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } |
79 func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } | 79 func (fi headerFileInfo) ModTime() time.Time { return fi.h.ModTime } |
80 func (fi headerFileInfo) Sys() interface{} { return fi.h } | 80 func (fi headerFileInfo) Sys() interface{} { return fi.h } |
| 81 |
| 82 // Name returns the base name of the file. |
| 83 func (fi headerFileInfo) Name() string { |
| 84 if fi.IsDir() { |
| 85 return path.Clean(fi.h.Name) |
| 86 } |
| 87 return fi.h.Name |
| 88 } |
81 | 89 |
82 // Mode returns the permission and mode bits for the headerFileInfo. | 90 // Mode returns the permission and mode bits for the headerFileInfo. |
83 func (fi headerFileInfo) Mode() (mode os.FileMode) { | 91 func (fi headerFileInfo) Mode() (mode os.FileMode) { |
84 // Set file permission bits. | 92 // Set file permission bits. |
85 mode = os.FileMode(fi.h.Mode).Perm() | 93 mode = os.FileMode(fi.h.Mode).Perm() |
86 | 94 |
87 // Set setuid, setgid and sticky bits. | 95 // Set setuid, setgid and sticky bits. |
88 if fi.h.Mode&c_ISUID != 0 { | 96 if fi.h.Mode&c_ISUID != 0 { |
89 // setuid | 97 // setuid |
90 mode |= os.ModeSetuid | 98 mode |= os.ModeSetuid |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 c_ISFIFO = 010000 // FIFO | 169 c_ISFIFO = 010000 // FIFO |
162 c_ISREG = 0100000 // Regular file | 170 c_ISREG = 0100000 // Regular file |
163 c_ISLNK = 0120000 // Symbolic link | 171 c_ISLNK = 0120000 // Symbolic link |
164 c_ISBLK = 060000 // Block special file | 172 c_ISBLK = 060000 // Block special file |
165 c_ISCHR = 020000 // Character special file | 173 c_ISCHR = 020000 // Character special file |
166 c_ISSOCK = 0140000 // Socket | 174 c_ISSOCK = 0140000 // Socket |
167 ) | 175 ) |
168 | 176 |
169 // FileInfoHeader creates a partially-populated Header from fi. | 177 // FileInfoHeader creates a partially-populated Header from fi. |
170 // If fi describes a symlink, FileInfoHeader records link as the link target. | 178 // If fi describes a symlink, FileInfoHeader records link as the link target. |
| 179 // If fi describes a directory, a slash is appended to the name. |
171 func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { | 180 func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { |
172 if fi == nil { | 181 if fi == nil { |
173 return nil, errors.New("tar: FileInfo is nil") | 182 return nil, errors.New("tar: FileInfo is nil") |
174 } | 183 } |
175 fm := fi.Mode() | 184 fm := fi.Mode() |
176 h := &Header{ | 185 h := &Header{ |
177 Name: fi.Name(), | 186 Name: fi.Name(), |
178 ModTime: fi.ModTime(), | 187 ModTime: fi.ModTime(), |
179 Mode: int64(fm.Perm()), // or'd with c_IS* constants later | 188 Mode: int64(fm.Perm()), // or'd with c_IS* constants later |
180 } | 189 } |
181 switch { | 190 switch { |
182 case fm.IsRegular(): | 191 case fm.IsRegular(): |
183 h.Mode |= c_ISREG | 192 h.Mode |= c_ISREG |
184 h.Typeflag = TypeReg | 193 h.Typeflag = TypeReg |
185 h.Size = fi.Size() | 194 h.Size = fi.Size() |
186 case fi.IsDir(): | 195 case fi.IsDir(): |
187 h.Typeflag = TypeDir | 196 h.Typeflag = TypeDir |
188 h.Mode |= c_ISDIR | 197 h.Mode |= c_ISDIR |
| 198 h.Name += "/" |
189 case fm&os.ModeSymlink != 0: | 199 case fm&os.ModeSymlink != 0: |
190 h.Typeflag = TypeSymlink | 200 h.Typeflag = TypeSymlink |
191 h.Mode |= c_ISLNK | 201 h.Mode |= c_ISLNK |
192 h.Linkname = link | 202 h.Linkname = link |
193 case fm&os.ModeDevice != 0: | 203 case fm&os.ModeDevice != 0: |
194 if fm&os.ModeCharDevice != 0 { | 204 if fm&os.ModeCharDevice != 0 { |
195 h.Mode |= c_ISCHR | 205 h.Mode |= c_ISCHR |
196 h.Typeflag = TypeChar | 206 h.Typeflag = TypeChar |
197 } else { | 207 } else { |
198 h.Mode |= c_ISBLK | 208 h.Mode |= c_ISBLK |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 return | 250 return |
241 } | 251 } |
242 | 252 |
243 type slicer []byte | 253 type slicer []byte |
244 | 254 |
245 func (sp *slicer) next(n int) (b []byte) { | 255 func (sp *slicer) next(n int) (b []byte) { |
246 s := *sp | 256 s := *sp |
247 b, *sp = s[0:n], s[n:] | 257 b, *sp = s[0:n], s[n:] |
248 return | 258 return |
249 } | 259 } |
LEFT | RIGHT |