File: directory.go

package info (click to toggle)
golang-github-openshift-imagebuilder 1.2.15%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,776 kB
  • sloc: makefile: 18; sh: 3; ansic: 1
file content (87 lines) | stat: -rw-r--r-- 2,017 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package dockerclient

import (
	"archive/tar"
	"context"
	"io"
	"io/ioutil"

	docker "github.com/fsouza/go-dockerclient"
	"k8s.io/klog"
)

type DirectoryCheck interface {
	IsDirectory(path string) (bool, error)
}

type directoryCheck struct {
	containerID string
	client      *docker.Client
}

func newDirectoryCheck(client *docker.Client, containerID string) *directoryCheck {
	return &directoryCheck{
		containerID: containerID,
		client:      client,
	}
}

func (c *directoryCheck) IsDirectory(path string) (bool, error) {
	if path == "/" || path == "." || path == "./" {
		return true, nil
	}

	dir, err := isContainerPathDirectory(c.client, c.containerID, path)
	if err != nil {
		return false, err
	}

	return dir, nil
}

func isContainerPathDirectory(client *docker.Client, containerID, path string) (bool, error) {
	pr, pw := io.Pipe()
	defer pw.Close()
	ctx, cancel := context.WithCancel(context.TODO())
	go func() {
		err := client.DownloadFromContainer(containerID, docker.DownloadFromContainerOptions{
			OutputStream: pw,
			Path:         path,
			Context:      ctx,
		})
		if err != nil {
			if apiErr, ok := err.(*docker.Error); ok && apiErr.Status == 404 {
				klog.V(4).Infof("path %s did not exist in container %s: %v", path, containerID, err)
				err = nil
			}
			if err != nil && err != context.Canceled {
				klog.V(6).Infof("error while checking directory contents for container %s at path %s: %v", containerID, path, err)
			}
		}
		pw.CloseWithError(err)
	}()

	tr := tar.NewReader(pr)

	h, err := tr.Next()
	if err != nil {
		if err == io.EOF {
			err = nil
		}
		cancel()
		return false, err
	}

	klog.V(4).Infof("Retrieved first header from container %s at path %s: %#v", containerID, path, h)

	// take the remainder of the input and discard it
	go func() {
		cancel()
		n, err := io.Copy(ioutil.Discard, pr)
		if n > 0 || err != nil {
			klog.V(6).Infof("Discarded %d bytes from end of container directory check, and got error: %v", n, err)
		}
	}()

	return h.FileInfo().IsDir(), nil
}