Exemple #1
0
// We have a dummy version of this call in posix.go.
// Windows does not implement the syscall.Stat_t type we
// need, but the *nixes do. We use this in util.AddToArchive
// to set owner/group on files being added to a tar archive.
func GetOwnerAndGroup(finfo os.FileInfo, header *tar.Header) {
	systat := finfo.Sys().(*syscall.Stat_t)
	if systat != nil {
		header.Uid = int(systat.Uid)
		header.Gid = int(systat.Gid)
	}
}
Exemple #2
0
func writeTarEntry(tw *tar.Writer, name string, data []byte) error {
	h := new(tar.Header)
	h.Name = name
	h.Uid = 1000
	h.Gid = 1000
	h.Mode = 0755
	h.Size = int64(len(data))
	if err := tw.WriteHeader(h); err != nil {
		return err
	}
	if _, err := tw.Write(data); err != nil {
		return err
	}
	return nil
}
Exemple #3
0
func populateHeaderUnix(h *tar.Header, fi os.FileInfo, seen map[uint64]string) {
	st, ok := fi.Sys().(*syscall.Stat_t)
	if !ok {
		return
	}
	h.Uid = int(st.Uid)
	h.Gid = int(st.Gid)
	// If we have already seen this inode, generate a hardlink
	p, ok := seen[uint64(st.Ino)]
	if ok {
		h.Linkname = p
		h.Typeflag = tar.TypeLink
	} else {
		seen[uint64(st.Ino)] = h.Name
	}
}
Exemple #4
0
func populateHeaderUnix(h *tar.Header, fi os.FileInfo, seen map[uint64]string) {
	st, ok := fi.Sys().(*syscall.Stat_t)
	if !ok {
		return
	}
	h.Uid = int(st.Uid)
	h.Gid = int(st.Gid)
	if st.Mode&syscall.S_IFMT == syscall.S_IFBLK || st.Mode&syscall.S_IFMT == syscall.S_IFCHR {
		h.Devminor = int64(C.my_minor(C.dev_t(st.Rdev)))
		h.Devmajor = int64(C.my_major(C.dev_t(st.Rdev)))
	}
	// If we have already seen this inode, generate a hardlink
	p, ok := seen[uint64(st.Ino)]
	if ok {
		h.Linkname = p
		h.Typeflag = tar.TypeLink
	} else {
		seen[uint64(st.Ino)] = h.Name
	}
}
Exemple #5
0
// fills tar.Header missing information (uid/gid, username/groupname, times ...)
func FillHeader(hdr *tar.Header) {
	var cuname string
	cuid := os.Getuid()
	if curr, err := user.LookupId(fmt.Sprintf("%d", cuid)); err == nil {
		cuname = curr.Username
	}
	if hdr.Uid == 0 {
		if hdr.Uname == "" {
			hdr.Uid = cuid
			hdr.Uname = cuname
		} else {
			if usr, err := user.Lookup(hdr.Uname); err == nil {
				if i, err := fmt.Sscanf("%d", usr.Uid); err == nil {
					hdr.Uid = i
					hdr.Uname = usr.Username
				}
			}
		}
	}
	if hdr.Gid == 0 {
		if hdr.Gname == "" {
			if hdr.Uid != 0 {
				if usr, err := user.LookupId(fmt.Sprintf("%d", hdr.Uid)); err == nil {
					if i, err := fmt.Sscanf("%d", usr.Gid); err == nil {
						hdr.Gid = i
					}
				}
			}
		}
	}
	if hdr.ModTime.IsZero() {
		hdr.ModTime = time.Now()
	}
	if hdr.AccessTime.IsZero() {
		hdr.AccessTime = hdr.ModTime
	}
	if hdr.ChangeTime.IsZero() {
		hdr.ChangeTime = hdr.ModTime
	}
}
Exemple #6
0
func fakeTar() (io.Reader, error) {
	uid := os.Getuid()
	gid := os.Getgid()

	content := []byte("Hello world!\n")
	buf := new(bytes.Buffer)
	tw := tar.NewWriter(buf)
	for _, name := range []string{"/etc/postgres/postgres.conf", "/etc/passwd", "/var/log/postgres/postgres.conf"} {
		hdr := new(tar.Header)

		// Leaving these fields blank requires root privileges
		hdr.Uid = uid
		hdr.Gid = gid

		hdr.Size = int64(len(content))
		hdr.Name = name
		if err := tw.WriteHeader(hdr); err != nil {
			return nil, err
		}
		tw.Write([]byte(content))
	}
	tw.Close()
	return buf, nil
}
Exemple #7
0
func TestUntarIDMappings(t *testing.T) {
	StartTest(t)
	defer FinishTest(t)

	// create a buffer and tar.Writer
	buffer := bytes.NewBufferString("")
	archive := tar.NewWriter(buffer)

	writeDirectoryWithOwners := func(name string, uid, gid int) {
		header := new(tar.Header)
		header.Name = name + "/"
		header.Typeflag = tar.TypeDir
		header.Mode = 0755
		header.Mode |= c_ISDIR
		header.ModTime = time.Now()
		header.Uid = uid
		header.Gid = gid
		TestExpectSuccess(t, archive.WriteHeader(header))
	}

	writeFileWithOwners := func(name, contents string, uid, gid int) {
		b := []byte(contents)
		header := new(tar.Header)
		header.Name = name
		header.Typeflag = tar.TypeReg
		header.Mode = 0644
		header.Mode |= c_ISREG
		header.ModTime = time.Now()
		header.Size = int64(len(b))
		header.Uid = uid
		header.Gid = gid

		TestExpectSuccess(t, archive.WriteHeader(header))
		_, err := archive.Write(b)
		TestExpectSuccess(t, err)
		TestExpectSuccess(t, archive.Flush())
	}

	writeDirectoryWithOwners(".", 0, 0)
	writeFileWithOwners("./foo", "foo", 0, 0)
	archive.Close()

	// setup our mapping func
	usr, err := user.Current()
	TestExpectSuccess(t, err)
	myUid, err := strconv.Atoi(usr.Uid)
	TestExpectSuccess(t, err)
	myGid, err := strconv.Atoi(usr.Gid)
	TestExpectSuccess(t, err)
	uidFuncCalled := false
	gidFuncCalled := false
	uidMappingFunc := func(uid int) (int, error) {
		uidFuncCalled = true
		TestEqual(t, uid, 0)
		return myUid, nil
	}
	gidMappingFunc := func(gid int) (int, error) {
		gidFuncCalled = true
		TestEqual(t, gid, 0)
		return myGid, nil
	}

	// extract
	tempDir := TempDir(t)
	r := bytes.NewReader(buffer.Bytes())
	u := NewUntar(r, tempDir)
	u.PreserveOwners = true
	u.OwnerMappingFunc = uidMappingFunc
	u.GroupMappingFunc = gidMappingFunc
	TestExpectSuccess(t, u.Extract())

	// verify it was called
	TestEqual(t, uidFuncCalled, true)
	TestEqual(t, gidFuncCalled, true)

	// verify the file
	stat, err := os.Stat(path.Join(tempDir, "foo"))
	TestExpectSuccess(t, err)
	sys := stat.Sys().(*syscall.Stat_t)
	TestEqual(t, sys.Uid, uint32(myUid))
	TestEqual(t, sys.Gid, uint32(myGid))
}
Exemple #8
0
func createArchive() int {
	archive := tar.NewWriter(output)
	defer archive.Close()
	exit_value := 0

	for _, f := range fileList {
		err := filepath.Walk(f, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}

			if verbose {
				fmt.Fprintf(os.Stderr, "%s\n", path)
			}

			var hdr tar.Header
			hdr.Name = path
			hdr.Size = info.Size()
			hdr.Mode = int64(info.Mode())
			hdr.ModTime = info.ModTime()

			// this is not portable:
			hdr.Uid = int(info.Sys().(*syscall.Stat_t).Uid)
			hdr.Gid = int(info.Sys().(*syscall.Stat_t).Gid)

			if user, err := user.LookupId(fmt.Sprintf("%d", hdr.Uid)); err == nil {
				hdr.Uname = user.Name
			}
			// TODO: lookup group, too.

			switch info.Mode() & os.ModeType {
			case 0:
				hdr.Typeflag = tar.TypeReg
			case os.ModeDir:
				hdr.Typeflag = tar.TypeDir
			case os.ModeSymlink:
				hdr.Typeflag = tar.TypeSymlink
				linkname, err := os.Readlink(path)
				if err != nil {
					fmt.Fprintf(os.Stderr, "Warning: can't readlink a symlink: %v\n", err)
					return nil
				} else {
					hdr.Linkname = linkname
				}
			case os.ModeNamedPipe:
				hdr.Typeflag = tar.TypeFifo
			case os.ModeSocket:
				fmt.Fprintf(os.Stderr, "Warning: can't tar a socket\n")
				return nil
			case os.ModeDevice:
				fmt.Fprintf(os.Stderr, "Warning: device files are currently unsupported\n")
				return nil
				/*
					if (info.Mode() & os.ModeCharDevice) != 0 {
						os.Typeflag = tar.TypeChar
					} else {
						os.Typeflag = tar.TypeBlock
					}
				*/
			}

			if err := archive.WriteHeader(&hdr); err != nil {
				fmt.Fprintf(os.Stderr, "Writing archive header for %s failed: %v\n", path, err)
				exit_value = 1
				return nil
			}
			defer archive.Flush()

			if hdr.Typeflag == tar.TypeReg {
				if f, err := os.Open(path); err != nil {
					fmt.Fprintf(os.Stderr, "Opening file %s failed: %v\n", path, err)
					exit_value = 1
					return nil
				} else {
					io.Copy(archive, f)
					f.Close()
				}
			}
			return nil
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "An error occured: %v\n", err)
			exit_value = 1
		}
	}

	return exit_value
}