"Fossies" - the Fresh Open Source Software Archive 
Member "skopeo-1.2.1/vendor/github.com/containers/storage/pkg/chrootarchive/archive_unix.go" (10 Jan 2021, 4490 Bytes) of package /linux/misc/skopeo-1.2.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 // +build !windows
2
3 package chrootarchive
4
5 import (
6 "bytes"
7 "encoding/json"
8 "flag"
9 "fmt"
10 "io"
11 "io/ioutil"
12 "os"
13 "path/filepath"
14 "runtime"
15 "strings"
16
17 "github.com/containers/storage/pkg/archive"
18 "github.com/containers/storage/pkg/reexec"
19 "github.com/pkg/errors"
20 )
21
22 // untar is the entry-point for storage-untar on re-exec. This is not used on
23 // Windows as it does not support chroot, hence no point sandboxing through
24 // chroot and rexec.
25 func untar() {
26 runtime.LockOSThread()
27 flag.Parse()
28
29 var options archive.TarOptions
30
31 //read the options from the pipe "ExtraFiles"
32 if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil {
33 fatal(err)
34 }
35
36 dst := flag.Arg(0)
37 var root string
38 if len(flag.Args()) > 1 {
39 root = flag.Arg(1)
40 }
41
42 if root == "" {
43 root = dst
44 }
45
46 if err := chroot(root); err != nil {
47 fatal(err)
48 }
49
50 if err := archive.Unpack(os.Stdin, dst, &options); err != nil {
51 fatal(err)
52 }
53 // fully consume stdin in case it is zero padded
54 if _, err := flush(os.Stdin); err != nil {
55 fatal(err)
56 }
57
58 os.Exit(0)
59 }
60
61 func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions, root string) error {
62 if root == "" {
63 return errors.New("must specify a root to chroot to")
64 }
65
66 // We can't pass a potentially large exclude list directly via cmd line
67 // because we easily overrun the kernel's max argument/environment size
68 // when the full image list is passed (e.g. when this is used by
69 // `docker load`). We will marshall the options via a pipe to the
70 // child
71 r, w, err := os.Pipe()
72 if err != nil {
73 return fmt.Errorf("Untar pipe failure: %v", err)
74 }
75
76 if root != "" {
77 relDest, err := filepath.Rel(root, dest)
78 if err != nil {
79 return err
80 }
81 if relDest == "." {
82 relDest = "/"
83 }
84 if relDest[0] != '/' {
85 relDest = "/" + relDest
86 }
87 dest = relDest
88 }
89
90 cmd := reexec.Command("storage-untar", dest, root)
91 cmd.Stdin = decompressedArchive
92
93 cmd.ExtraFiles = append(cmd.ExtraFiles, r)
94 output := bytes.NewBuffer(nil)
95 cmd.Stdout = output
96 cmd.Stderr = output
97
98 if err := cmd.Start(); err != nil {
99 w.Close()
100 return fmt.Errorf("Untar error on re-exec cmd: %v", err)
101 }
102
103 //write the options to the pipe for the untar exec to read
104 if err := json.NewEncoder(w).Encode(options); err != nil {
105 w.Close()
106 return fmt.Errorf("Untar json encode to pipe failed: %v", err)
107 }
108 w.Close()
109
110 if err := cmd.Wait(); err != nil {
111 // when `xz -d -c -q | storage-untar ...` failed on storage-untar side,
112 // we need to exhaust `xz`'s output, otherwise the `xz` side will be
113 // pending on write pipe forever
114 io.Copy(ioutil.Discard, decompressedArchive)
115
116 return fmt.Errorf("Error processing tar file(%v): %s", err, output)
117 }
118 return nil
119 }
120
121 func tar() {
122 runtime.LockOSThread()
123 flag.Parse()
124
125 src := flag.Arg(0)
126 var root string
127 if len(flag.Args()) > 1 {
128 root = flag.Arg(1)
129 }
130
131 if root == "" {
132 root = src
133 }
134
135 if err := realChroot(root); err != nil {
136 fatal(err)
137 }
138
139 var options archive.TarOptions
140 if err := json.NewDecoder(os.Stdin).Decode(&options); err != nil {
141 fatal(err)
142 }
143
144 rdr, err := archive.TarWithOptions(src, &options)
145 if err != nil {
146 fatal(err)
147 }
148 defer rdr.Close()
149
150 if _, err := io.Copy(os.Stdout, rdr); err != nil {
151 fatal(err)
152 }
153
154 os.Exit(0)
155 }
156
157 func invokePack(srcPath string, options *archive.TarOptions, root string) (io.ReadCloser, error) {
158 if root == "" {
159 return nil, errors.New("root path must not be empty")
160 }
161
162 relSrc, err := filepath.Rel(root, srcPath)
163 if err != nil {
164 return nil, err
165 }
166 if relSrc == "." {
167 relSrc = "/"
168 }
169 if relSrc[0] != '/' {
170 relSrc = "/" + relSrc
171 }
172
173 // make sure we didn't trim a trailing slash with the call to `Rel`
174 if strings.HasSuffix(srcPath, "/") && !strings.HasSuffix(relSrc, "/") {
175 relSrc += "/"
176 }
177
178 cmd := reexec.Command("storage-tar", relSrc, root)
179
180 errBuff := bytes.NewBuffer(nil)
181 cmd.Stderr = errBuff
182
183 tarR, tarW := io.Pipe()
184 cmd.Stdout = tarW
185
186 stdin, err := cmd.StdinPipe()
187 if err != nil {
188 return nil, errors.Wrap(err, "error getting options pipe for tar process")
189 }
190
191 if err := cmd.Start(); err != nil {
192 return nil, errors.Wrap(err, "tar error on re-exec cmd")
193 }
194
195 go func() {
196 err := cmd.Wait()
197 err = errors.Wrapf(err, "error processing tar file: %s", errBuff)
198 tarW.CloseWithError(err)
199 }()
200
201 if err := json.NewEncoder(stdin).Encode(options); err != nil {
202 stdin.Close()
203 return nil, errors.Wrap(err, "tar json encode to pipe failed")
204 }
205 stdin.Close()
206
207 return tarR, nil
208 }