| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- //
- // Use and distribution licensed under the Apache license version 2.
- //
- // See the COPYING file in the root project directory for full text.
- //
- package snapshot
- import (
- "archive/tar"
- "compress/gzip"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "github.com/jaypipes/ghw/pkg/option"
- )
- const (
- TargetRoot = "ghw-snapshot-*"
- )
- const (
- // If set, `ghw` will not unpack the snapshot in the user-supplied directory
- // unless the aforementioned directory is empty.
- OwnTargetDirectory = 1 << iota
- )
- // Clanup removes the unpacket snapshot from the target root.
- // Please not that the environs variable `GHW_SNAPSHOT_PRESERVE`, if set,
- // will make this function silently skip.
- func Cleanup(targetRoot string) error {
- if option.EnvOrDefaultSnapshotPreserve() {
- return nil
- }
- return os.RemoveAll(targetRoot)
- }
- // Unpack expands the given snapshot in a temporary directory managed by `ghw`. Returns the path of that directory.
- func Unpack(snapshotName string) (string, error) {
- targetRoot, err := ioutil.TempDir("", TargetRoot)
- if err != nil {
- return "", err
- }
- _, err = UnpackInto(snapshotName, targetRoot, 0)
- return targetRoot, err
- }
- // UnpackInto expands the given snapshot in a client-supplied directory.
- // Returns true if the snapshot was actually unpacked, false otherwise
- func UnpackInto(snapshotName, targetRoot string, flags uint) (bool, error) {
- if (flags&OwnTargetDirectory) == OwnTargetDirectory && !isEmptyDir(targetRoot) {
- return false, nil
- }
- snap, err := os.Open(snapshotName)
- if err != nil {
- return false, err
- }
- defer snap.Close()
- return true, Untar(targetRoot, snap)
- }
- // Untar extracts data from the given reader (providing data in tar.gz format) and unpacks it in the given directory.
- func Untar(root string, r io.Reader) error {
- var err error
- gzr, err := gzip.NewReader(r)
- if err != nil {
- return err
- }
- defer gzr.Close()
- tr := tar.NewReader(gzr)
- for {
- header, err := tr.Next()
- if err == io.EOF {
- // we are done
- return nil
- }
- if err != nil {
- // bail out
- return err
- }
- if header == nil {
- // TODO: how come?
- continue
- }
- target := filepath.Join(root, header.Name)
- mode := os.FileMode(header.Mode)
- switch header.Typeflag {
- case tar.TypeDir:
- err = os.MkdirAll(target, mode)
- if err != nil {
- return err
- }
- case tar.TypeReg:
- dst, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, mode)
- if err != nil {
- return err
- }
- _, err = io.Copy(dst, tr)
- if err != nil {
- return err
- }
- dst.Close()
- case tar.TypeSymlink:
- err = os.Symlink(header.Linkname, target)
- if err != nil {
- return err
- }
- }
- }
- }
- func isEmptyDir(name string) bool {
- entries, err := ioutil.ReadDir(name)
- if err != nil {
- return false
- }
- return len(entries) == 0
- }
|