github.com/coreos/mantle@v0.13.0/platform/api/esx/archive.go (about) 1 // Copyright (c) 2016 VMware, Inc. All Rights Reserved. 2 // Copyright 2017 CoreOS, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package esx 17 18 import ( 19 "archive/tar" 20 "fmt" 21 "io" 22 "io/ioutil" 23 "os" 24 "path" 25 26 "github.com/vmware/govmomi/ovf" 27 ) 28 29 type archive struct { 30 path string 31 } 32 33 type archiveEntry struct { 34 io.Reader 35 f *os.File 36 } 37 38 func (t *archiveEntry) Close() error { 39 return t.f.Close() 40 } 41 42 func (t *archive) readOvf(fpath string) ([]byte, error) { 43 r, _, err := t.open(fpath) 44 if err != nil { 45 return nil, err 46 } 47 defer r.Close() 48 49 return ioutil.ReadAll(r) 50 } 51 52 func (t *archive) readEnvelope(fpath string) (*ovf.Envelope, error) { 53 if fpath == "" { 54 return nil, nil 55 } 56 57 r, _, err := t.open(fpath) 58 if err != nil { 59 return nil, err 60 } 61 defer r.Close() 62 63 e, err := ovf.Unmarshal(r) 64 if err != nil { 65 return nil, fmt.Errorf("failed to parse ovf: %s", err.Error()) 66 } 67 68 return e, nil 69 } 70 71 func (t *archive) open(pattern string) (io.ReadCloser, int64, error) { 72 f, err := os.Open(t.path) 73 if err != nil { 74 return nil, 0, err 75 } 76 77 r := tar.NewReader(f) 78 79 for { 80 h, err := r.Next() 81 if err == io.EOF { 82 break 83 } 84 if err != nil { 85 f.Close() 86 return nil, 0, err 87 } 88 89 matched, err := path.Match(pattern, path.Base(h.Name)) 90 if err != nil { 91 f.Close() 92 return nil, 0, err 93 } 94 95 if matched { 96 return &archiveEntry{r, f}, h.Size, nil 97 } 98 } 99 100 f.Close() 101 return nil, 0, fmt.Errorf("couldn't find file in archive") 102 }