Commit 66b5a2f3 authored by Lars Jeppesen's avatar Lars Jeppesen Committed by Joe Tsai

archive/tar: remove file type bits from mode field

When writing tar files by using the FileInfoHeader
the type bits was set in the mode field of the header
This is not correct according to the standard (GNU/Posix) and
other implementations.

Fixed #20150

Change-Id: I3be7d946a1923ad5827cf45c696546a5e287ebba
Reviewed-on: https://go-review.googlesource.com/42093Reviewed-by: default avatarJoe Tsai <thebrokentoaster@gmail.com>
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 8f06e217
...@@ -158,11 +158,15 @@ func (fi headerFileInfo) Mode() (mode os.FileMode) { ...@@ -158,11 +158,15 @@ func (fi headerFileInfo) Mode() (mode os.FileMode) {
// sysStat, if non-nil, populates h from system-dependent fields of fi. // sysStat, if non-nil, populates h from system-dependent fields of fi.
var sysStat func(fi os.FileInfo, h *Header) error var sysStat func(fi os.FileInfo, h *Header) error
// Mode constants from the tar spec.
const ( const (
// Mode constants from the USTAR spec:
// See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_06
c_ISUID = 04000 // Set uid c_ISUID = 04000 // Set uid
c_ISGID = 02000 // Set gid c_ISGID = 02000 // Set gid
c_ISVTX = 01000 // Save text (sticky bit) c_ISVTX = 01000 // Save text (sticky bit)
// Common Unix mode constants; these are not defined in any common tar standard.
// Header.FileInfo understands these, but FileInfoHeader will never produce these.
c_ISDIR = 040000 // Directory c_ISDIR = 040000 // Directory
c_ISFIFO = 010000 // FIFO c_ISFIFO = 010000 // FIFO
c_ISREG = 0100000 // Regular file c_ISREG = 0100000 // Regular file
...@@ -208,30 +212,24 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { ...@@ -208,30 +212,24 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
} }
switch { switch {
case fm.IsRegular(): case fm.IsRegular():
h.Mode |= c_ISREG
h.Typeflag = TypeReg h.Typeflag = TypeReg
h.Size = fi.Size() h.Size = fi.Size()
case fi.IsDir(): case fi.IsDir():
h.Typeflag = TypeDir h.Typeflag = TypeDir
h.Mode |= c_ISDIR
h.Name += "/" h.Name += "/"
case fm&os.ModeSymlink != 0: case fm&os.ModeSymlink != 0:
h.Typeflag = TypeSymlink h.Typeflag = TypeSymlink
h.Mode |= c_ISLNK
h.Linkname = link h.Linkname = link
case fm&os.ModeDevice != 0: case fm&os.ModeDevice != 0:
if fm&os.ModeCharDevice != 0 { if fm&os.ModeCharDevice != 0 {
h.Mode |= c_ISCHR
h.Typeflag = TypeChar h.Typeflag = TypeChar
} else { } else {
h.Mode |= c_ISBLK
h.Typeflag = TypeBlock h.Typeflag = TypeBlock
} }
case fm&os.ModeNamedPipe != 0: case fm&os.ModeNamedPipe != 0:
h.Typeflag = TypeFifo h.Typeflag = TypeFifo
h.Mode |= c_ISFIFO
case fm&os.ModeSocket != 0: case fm&os.ModeSocket != 0:
h.Mode |= c_ISSOCK return nil, fmt.Errorf("archive/tar: sockets not supported")
default: default:
return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm) return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
} }
......
...@@ -29,7 +29,7 @@ func TestFileInfoHeader(t *testing.T) { ...@@ -29,7 +29,7 @@ func TestFileInfoHeader(t *testing.T) {
if g, e := h.Name, "small.txt"; g != e { if g, e := h.Name, "small.txt"; g != e {
t.Errorf("Name = %q; want %q", g, e) t.Errorf("Name = %q; want %q", g, e)
} }
if g, e := h.Mode, int64(fi.Mode().Perm())|c_ISREG; g != e { if g, e := h.Mode, int64(fi.Mode().Perm()); g != e {
t.Errorf("Mode = %#o; want %#o", g, e) t.Errorf("Mode = %#o; want %#o", g, e)
} }
if g, e := h.Size, int64(5); g != e { if g, e := h.Size, int64(5); g != e {
...@@ -57,7 +57,7 @@ func TestFileInfoHeaderDir(t *testing.T) { ...@@ -57,7 +57,7 @@ func TestFileInfoHeaderDir(t *testing.T) {
t.Errorf("Name = %q; want %q", g, e) t.Errorf("Name = %q; want %q", g, e)
} }
// Ignoring c_ISGID for golang.org/issue/4867 // Ignoring c_ISGID for golang.org/issue/4867
if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm())|c_ISDIR; g != e { if g, e := h.Mode&^c_ISGID, int64(fi.Mode().Perm()); g != e {
t.Errorf("Mode = %#o; want %#o", g, e) t.Errorf("Mode = %#o; want %#o", g, e)
} }
if g, e := h.Size, int64(0); g != e { if g, e := h.Size, int64(0); g != e {
...@@ -157,7 +157,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -157,7 +157,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// regular file. // regular file.
h: &Header{ h: &Header{
Name: "test.txt", Name: "test.txt",
Mode: 0644 | c_ISREG, Mode: 0644,
Size: 12, Size: 12,
ModTime: time.Unix(1360600916, 0), ModTime: time.Unix(1360600916, 0),
Typeflag: TypeReg, Typeflag: TypeReg,
...@@ -167,7 +167,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -167,7 +167,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// symbolic link. // symbolic link.
h: &Header{ h: &Header{
Name: "link.txt", Name: "link.txt",
Mode: 0777 | c_ISLNK, Mode: 0777,
Size: 0, Size: 0,
ModTime: time.Unix(1360600852, 0), ModTime: time.Unix(1360600852, 0),
Typeflag: TypeSymlink, Typeflag: TypeSymlink,
...@@ -177,7 +177,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -177,7 +177,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// character device node. // character device node.
h: &Header{ h: &Header{
Name: "dev/null", Name: "dev/null",
Mode: 0666 | c_ISCHR, Mode: 0666,
Size: 0, Size: 0,
ModTime: time.Unix(1360578951, 0), ModTime: time.Unix(1360578951, 0),
Typeflag: TypeChar, Typeflag: TypeChar,
...@@ -187,7 +187,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -187,7 +187,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// block device node. // block device node.
h: &Header{ h: &Header{
Name: "dev/sda", Name: "dev/sda",
Mode: 0660 | c_ISBLK, Mode: 0660,
Size: 0, Size: 0,
ModTime: time.Unix(1360578954, 0), ModTime: time.Unix(1360578954, 0),
Typeflag: TypeBlock, Typeflag: TypeBlock,
...@@ -197,7 +197,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -197,7 +197,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// directory. // directory.
h: &Header{ h: &Header{
Name: "dir/", Name: "dir/",
Mode: 0755 | c_ISDIR, Mode: 0755,
Size: 0, Size: 0,
ModTime: time.Unix(1360601116, 0), ModTime: time.Unix(1360601116, 0),
Typeflag: TypeDir, Typeflag: TypeDir,
...@@ -207,7 +207,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -207,7 +207,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// fifo node. // fifo node.
h: &Header{ h: &Header{
Name: "dev/initctl", Name: "dev/initctl",
Mode: 0600 | c_ISFIFO, Mode: 0600,
Size: 0, Size: 0,
ModTime: time.Unix(1360578949, 0), ModTime: time.Unix(1360578949, 0),
Typeflag: TypeFifo, Typeflag: TypeFifo,
...@@ -217,7 +217,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -217,7 +217,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// setuid. // setuid.
h: &Header{ h: &Header{
Name: "bin/su", Name: "bin/su",
Mode: 0755 | c_ISREG | c_ISUID, Mode: 0755 | c_ISUID,
Size: 23232, Size: 23232,
ModTime: time.Unix(1355405093, 0), ModTime: time.Unix(1355405093, 0),
Typeflag: TypeReg, Typeflag: TypeReg,
...@@ -227,7 +227,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -227,7 +227,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// setguid. // setguid.
h: &Header{ h: &Header{
Name: "group.txt", Name: "group.txt",
Mode: 0750 | c_ISREG | c_ISGID, Mode: 0750 | c_ISGID,
Size: 0, Size: 0,
ModTime: time.Unix(1360602346, 0), ModTime: time.Unix(1360602346, 0),
Typeflag: TypeReg, Typeflag: TypeReg,
...@@ -237,7 +237,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -237,7 +237,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// sticky. // sticky.
h: &Header{ h: &Header{
Name: "sticky.txt", Name: "sticky.txt",
Mode: 0600 | c_ISREG | c_ISVTX, Mode: 0600 | c_ISVTX,
Size: 7, Size: 7,
ModTime: time.Unix(1360602540, 0), ModTime: time.Unix(1360602540, 0),
Typeflag: TypeReg, Typeflag: TypeReg,
...@@ -247,7 +247,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -247,7 +247,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// hard link. // hard link.
h: &Header{ h: &Header{
Name: "hard.txt", Name: "hard.txt",
Mode: 0644 | c_ISREG, Mode: 0644,
Size: 0, Size: 0,
Linkname: "file.txt", Linkname: "file.txt",
ModTime: time.Unix(1360600916, 0), ModTime: time.Unix(1360600916, 0),
...@@ -258,7 +258,7 @@ func TestHeaderRoundTrip(t *testing.T) { ...@@ -258,7 +258,7 @@ func TestHeaderRoundTrip(t *testing.T) {
// More information. // More information.
h: &Header{ h: &Header{
Name: "info.txt", Name: "info.txt",
Mode: 0600 | c_ISREG, Mode: 0600,
Size: 0, Size: 0,
Uid: 1000, Uid: 1000,
Gid: 1000, Gid: 1000,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment