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  }