Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(51)

Delta Between Two Patch Sets: src/pkg/archive/tar/common.go

Issue 7305072: code review 7305072: archive/tar: add Header.FileInfo method. Add more cases... (Closed)
Left Patch Set: diff -r 85d759cdb33d https://code.google.com/p/go Created 11 years, 1 month ago
Right Patch Set: diff -r d4024b084e0c https://code.google.com/p/go Created 11 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/archive/tar/tar_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 package tar 13 package tar
13 14
14 import ( 15 import (
15 "errors" 16 "errors"
16 "fmt" 17 "fmt"
17 "os" 18 "os"
19 "path"
18 "time" 20 "time"
19 ) 21 )
20 22
21 const ( 23 const (
22 blockSize = 512 24 blockSize = 512
23 25
24 // Types 26 // Types
25 TypeReg = '0' // regular file 27 TypeReg = '0' // regular file
26 TypeRegA = '\x00' // regular file 28 TypeRegA = '\x00' // regular file
27 TypeLink = '1' // hard link 29 TypeLink = '1' // hard link
28 TypeSymlink = '2' // symbolic link 30 TypeSymlink = '2' // symbolic link
29 TypeChar = '3' // character device node 31 TypeChar = '3' // character device node
30 TypeBlock = '4' // block device node 32 TypeBlock = '4' // block device node
31 TypeDir = '5' // directory 33 TypeDir = '5' // directory
32 TypeFifo = '6' // fifo node 34 TypeFifo = '6' // fifo node
33 TypeCont = '7' // reserved 35 TypeCont = '7' // reserved
34 TypeXHeader = 'x' // extended header 36 TypeXHeader = 'x' // extended header
35 TypeXGlobalHeader = 'g' // global extended header 37 TypeXGlobalHeader = 'g' // global extended header
38 TypeGNULongName = 'L' // Next file has a long name
39 TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long nam e
36 ) 40 )
37 41
38 // A Header represents a single header in a tar archive. 42 // A Header represents a single header in a tar archive.
39 // Some fields may not be populated. 43 // Some fields may not be populated.
40 type Header struct { 44 type Header struct {
41 Name string // name of header file entry 45 Name string // name of header file entry
42 Mode int64 // permission and mode bits 46 Mode int64 // permission and mode bits
43 Uid int // user id of owner 47 Uid int // user id of owner
44 Gid int // group id of owner 48 Gid int // group id of owner
45 Size int64 // length in bytes 49 Size int64 // length in bytes
46 ModTime time.Time // modified time 50 ModTime time.Time // modified time
47 Typeflag byte // type of header entry 51 Typeflag byte // type of header entry
48 Linkname string // target name of link 52 Linkname string // target name of link
49 Uname string // user name of owner 53 Uname string // user name of owner
50 Gname string // group name of owner 54 Gname string // group name of owner
51 Devmajor int64 // major number of character or block device 55 Devmajor int64 // major number of character or block device
52 Devminor int64 // minor number of character or block device 56 Devminor int64 // minor number of character or block device
53 AccessTime time.Time // access time 57 AccessTime time.Time // access time
54 ChangeTime time.Time // status change time 58 ChangeTime time.Time // status change time
55 } 59 }
56 60
61 // File name constants from the tar spec.
62 const (
63 fileNameSize = 100 // Maximum number of bytes in a standard tar na me.
64 fileNamePrefixSize = 155 // Maximum number of ustar extension bytes.
65 )
66
57 // FileInfo returns an os.FileInfo for the Header. 67 // FileInfo returns an os.FileInfo for the Header.
58 func (h *Header) FileInfo() os.FileInfo { 68 func (h *Header) FileInfo() os.FileInfo {
59 return headerFileInfo{h} 69 return headerFileInfo{h}
60 } 70 }
61 71
62 // headerFileInfo implements os.FileInfo. 72 // headerFileInfo implements os.FileInfo.
63 type headerFileInfo struct { 73 type headerFileInfo struct {
64 h *Header 74 h *Header
65 } 75 }
66 76
67 func (fi headerFileInfo) Name() string { return fi.h.Name }
68 func (fi headerFileInfo) Size() int64 { return fi.h.Size } 77 func (fi headerFileInfo) Size() int64 { return fi.h.Size }
69 func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() } 78 func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
70 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 }
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 }
71 89
72 // Mode returns the permission and mode bits for the headerFileInfo. 90 // Mode returns the permission and mode bits for the headerFileInfo.
73 func (fi headerFileInfo) Mode() (mode os.FileMode) { 91 func (fi headerFileInfo) Mode() (mode os.FileMode) {
74 // Set file permission bits. 92 // Set file permission bits.
75 » mode = os.FileMode(fi.h.Mode) & os.ModePerm 93 » mode = os.FileMode(fi.h.Mode).Perm()
94
95 » // Set setuid, setgid and sticky bits.
96 » if fi.h.Mode&c_ISUID != 0 {
97 » » // setuid
98 » » mode |= os.ModeSetuid
99 » }
100 » if fi.h.Mode&c_ISGID != 0 {
101 » » // setgid
102 » » mode |= os.ModeSetgid
103 » }
104 » if fi.h.Mode&c_ISVTX != 0 {
105 » » // sticky
106 » » mode |= os.ModeSticky
107 » }
76 108
77 // Set file mode bits. 109 // Set file mode bits.
78 » m := os.FileMode(fi.h.Mode) &^ os.ModePerm 110 » // clear perm, setuid, setgid and sticky bits.
79 » switch { 111 » m := os.FileMode(fi.h.Mode) &^ 07777
80 » case m&c_ISDIR != 0: 112 » if m == c_ISDIR {
113 » » // directory
81 mode |= os.ModeDir 114 mode |= os.ModeDir
82 » case m&c_ISFIFO != 0: 115 » }
116 » if m == c_ISFIFO {
117 » » // named pipe (FIFO)
83 mode |= os.ModeNamedPipe 118 mode |= os.ModeNamedPipe
u 2013/02/09 20:21:11 Could someone please verify that os.ModeNamedPipe
84 » case m&c_ISREG != 0: 119 » }
85 » » // regular file 120 » if m == c_ISLNK {
u 2013/02/09 20:21:11 Should we remove this nop case?
86 » case m&c_ISLNK != 0: 121 » » // symbolic link
87 mode |= os.ModeSymlink 122 mode |= os.ModeSymlink
88 » case m&c_ISBLK != 0: 123 » }
89 » » mode |= os.ModeDevice 124 » if m == c_ISBLK {
90 » case m&c_ISCHR != 0: 125 » » // device file
126 » » mode |= os.ModeDevice
127 » }
128 » if m == c_ISCHR {
129 » » // Unix character device
91 mode |= os.ModeDevice 130 mode |= os.ModeDevice
92 mode |= os.ModeCharDevice 131 mode |= os.ModeCharDevice
93 » case m&c_ISSOCK != 0: 132 » }
133 » if m == c_ISSOCK {
134 » » // Unix domain socket
94 mode |= os.ModeSocket 135 mode |= os.ModeSocket
95 } 136 }
96 137
97 switch fi.h.Typeflag { 138 switch fi.h.Typeflag {
98 » case '0', '\x00': 139 » case TypeLink, TypeSymlink:
99 » » // regular file
u 2013/02/09 20:21:11 Should we remove nop cases ('0', '\x00', '7', 'x',
100 » case '1', '2':
101 // hard link, symbolic link 140 // hard link, symbolic link
102 mode |= os.ModeSymlink 141 mode |= os.ModeSymlink
u 2013/02/09 20:21:11 Is there a way to differentiate a hard link from a
103 » case '3': 142 » case TypeChar:
104 // character device node 143 // character device node
105 mode |= os.ModeDevice 144 mode |= os.ModeDevice
106 mode |= os.ModeCharDevice 145 mode |= os.ModeCharDevice
107 » case '4': 146 » case TypeBlock:
108 // block device node 147 // block device node
109 mode |= os.ModeDevice 148 mode |= os.ModeDevice
110 » case '5': 149 » case TypeDir:
111 // directory 150 // directory
112 mode |= os.ModeDir 151 mode |= os.ModeDir
113 » case '6': 152 » case TypeFifo:
114 // fifo node 153 // fifo node
115 mode |= os.ModeNamedPipe 154 mode |= os.ModeNamedPipe
u 2013/02/09 20:21:11 Could someone please verify that os.ModeNamedPipe
116 case '7':
117 // reserved
118 case 'x':
119 // extended header
120 case 'g':
121 // global extended header
122 } 155 }
123 156
124 return mode 157 return mode
125 } 158 }
126
127 func (fi headerFileInfo) Sys() interface{} { return fi.h }
128 159
129 // sysStat, if non-nil, populates h from system-dependent fields of fi. 160 // sysStat, if non-nil, populates h from system-dependent fields of fi.
130 var sysStat func(fi os.FileInfo, h *Header) error 161 var sysStat func(fi os.FileInfo, h *Header) error
131 162
132 // Mode constants from the tar spec. 163 // Mode constants from the tar spec.
133 const ( 164 const (
134 » c_ISDIR = 040000 165 » c_ISUID = 04000 // Set uid
135 » c_ISFIFO = 010000 166 » c_ISGID = 02000 // Set gid
136 » c_ISREG = 0100000 167 » c_ISVTX = 01000 // Save text (sticky bit)
137 » c_ISLNK = 0120000 168 » c_ISDIR = 040000 // Directory
138 » c_ISBLK = 060000 169 » c_ISFIFO = 010000 // FIFO
139 » c_ISCHR = 020000 170 » c_ISREG = 0100000 // Regular file
140 » c_ISSOCK = 0140000 171 » c_ISLNK = 0120000 // Symbolic link
172 » c_ISBLK = 060000 // Block special file
173 » c_ISCHR = 020000 // Character special file
174 » c_ISSOCK = 0140000 // Socket
141 ) 175 )
142 176
143 // FileInfoHeader creates a partially-populated Header from fi. 177 // FileInfoHeader creates a partially-populated Header from fi.
144 // 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.
145 func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { 180 func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
146 if fi == nil { 181 if fi == nil {
147 return nil, errors.New("tar: FileInfo is nil") 182 return nil, errors.New("tar: FileInfo is nil")
148 } 183 }
184 fm := fi.Mode()
149 h := &Header{ 185 h := &Header{
150 Name: fi.Name(), 186 Name: fi.Name(),
151 ModTime: fi.ModTime(), 187 ModTime: fi.ModTime(),
152 » » Mode: int64(fi.Mode().Perm()), // or'd with c_IS* constants l ater 188 » » Mode: int64(fm.Perm()), // or'd with c_IS* constants later
153 } 189 }
154 switch { 190 switch {
155 » case fi.Mode().IsRegular(): 191 » case fm.IsRegular():
156 h.Mode |= c_ISREG 192 h.Mode |= c_ISREG
157 h.Typeflag = TypeReg 193 h.Typeflag = TypeReg
158 h.Size = fi.Size() 194 h.Size = fi.Size()
159 case fi.IsDir(): 195 case fi.IsDir():
160 h.Typeflag = TypeDir 196 h.Typeflag = TypeDir
161 h.Mode |= c_ISDIR 197 h.Mode |= c_ISDIR
162 » case fi.Mode()&os.ModeSymlink != 0: 198 » » h.Name += "/"
199 » case fm&os.ModeSymlink != 0:
163 h.Typeflag = TypeSymlink 200 h.Typeflag = TypeSymlink
164 h.Mode |= c_ISLNK 201 h.Mode |= c_ISLNK
165 h.Linkname = link 202 h.Linkname = link
166 » case fi.Mode()&os.ModeDevice != 0: 203 » case fm&os.ModeDevice != 0:
167 » » if fi.Mode()&os.ModeCharDevice != 0 { 204 » » if fm&os.ModeCharDevice != 0 {
168 h.Mode |= c_ISCHR 205 h.Mode |= c_ISCHR
169 h.Typeflag = TypeChar 206 h.Typeflag = TypeChar
170 } else { 207 } else {
171 h.Mode |= c_ISBLK 208 h.Mode |= c_ISBLK
172 h.Typeflag = TypeBlock 209 h.Typeflag = TypeBlock
173 } 210 }
174 » case fi.Mode()&os.ModeSocket != 0: 211 » case fm&os.ModeNamedPipe != 0:
212 » » h.Typeflag = TypeFifo
213 » » h.Mode |= c_ISFIFO
214 » case fm&os.ModeSocket != 0:
175 h.Mode |= c_ISSOCK 215 h.Mode |= c_ISSOCK
176 default: 216 default:
177 » » return nil, fmt.Errorf("archive/tar: unknown file mode %v", fi.M ode()) 217 » » return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
218 » }
219 » if fm&os.ModeSetuid != 0 {
220 » » h.Mode |= c_ISUID
221 » }
222 » if fm&os.ModeSetgid != 0 {
223 » » h.Mode |= c_ISGID
224 » }
225 » if fm&os.ModeSticky != 0 {
226 » » h.Mode |= c_ISVTX
178 } 227 }
179 if sysStat != nil { 228 if sysStat != nil {
180 return h, sysStat(fi, h) 229 return h, sysStat(fi, h)
181 } 230 }
182 return h, nil 231 return h, nil
183 } 232 }
184 233
185 var zeroBlock = make([]byte, blockSize) 234 var zeroBlock = make([]byte, blockSize)
186 235
187 // POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signe d byte values. 236 // POSIX specifies a sum of the unsigned byte values, but the Sun tar uses signe d byte values.
(...skipping 13 matching lines...) Expand all
201 return 250 return
202 } 251 }
203 252
204 type slicer []byte 253 type slicer []byte
205 254
206 func (sp *slicer) next(n int) (b []byte) { 255 func (sp *slicer) next(n int) (b []byte) {
207 s := *sp 256 s := *sp
208 b, *sp = s[0:n], s[n:] 257 b, *sp = s[0:n], s[n:]
209 return 258 return
210 } 259 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b