267c7cd2fa31824bec7389f9d2473af91c66057a
[multicloud/k8s.git] / src / k8splugin / internal / rb / archive.go
1 /*
2  * Copyright 2018 Intel Corporation, 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
17 package rb
18
19 import (
20         "archive/tar"
21         "compress/gzip"
22         pkgerrors "github.com/pkg/errors"
23         "io"
24         "io/ioutil"
25         "os"
26         "path/filepath"
27
28         utils "github.com/onap/multicloud-k8s/src/k8splugin/internal"
29 )
30
31 func isTarGz(r io.Reader) error {
32         //Check if it is a valid gz
33         gzf, err := gzip.NewReader(r)
34         if err != nil {
35                 return pkgerrors.Wrap(err, "Invalid gzip format")
36         }
37
38         //Check if it is a valid tar file
39         //Unfortunately this can only be done by inspecting all the tar contents
40         tarR := tar.NewReader(gzf)
41         first := true
42
43         for true {
44                 header, err := tarR.Next()
45
46                 if err == io.EOF {
47                         //Check if we have just a gzip file without a tar archive inside
48                         if first {
49                                 return pkgerrors.New("Empty or non-existant Tar file found")
50                         }
51                         //End of archive
52                         break
53                 }
54
55                 if err != nil {
56                         return pkgerrors.Errorf("Error reading tar file %s", err.Error())
57                 }
58
59                 //Check if files are of type directory and regular file
60                 if header.Typeflag != tar.TypeDir &&
61                         header.Typeflag != tar.TypeReg {
62                         return pkgerrors.Errorf("Unknown header in tar %s, %s",
63                                 header.Name, string(header.Typeflag))
64                 }
65
66                 first = false
67         }
68
69         return nil
70 }
71
72 //ExtractTarBall provides functionality to extract a tar.gz file
73 //into a temporary location for later use.
74 //It returns the path to the new location
75 func ExtractTarBall(r io.Reader) (string, error) {
76         //Check if it is a valid gz
77         gzf, err := gzip.NewReader(r)
78         if err != nil {
79                 return "", pkgerrors.Wrap(err, "Invalid gzip format")
80         }
81
82         //Check if it is a valid tar file
83         //Unfortunately this can only be done by inspecting all the tar contents
84         tarR := tar.NewReader(gzf)
85         first := true
86
87         outDir, _ := ioutil.TempDir("", "k8s-ext-")
88
89         for true {
90                 header, err := tarR.Next()
91
92                 if err == io.EOF {
93                         //Check if we have just a gzip file without a tar archive inside
94                         if first {
95                                 return "", pkgerrors.New("Empty or non-existant Tar file found")
96                         }
97                         //End of archive
98                         break
99                 }
100
101                 if err != nil {
102                         return "", pkgerrors.Wrap(err, "Error reading tar file")
103                 }
104
105                 target := filepath.Join(outDir, header.Name)
106
107                 switch header.Typeflag {
108                 case tar.TypeDir:
109                         if _, err := os.Stat(target); err != nil {
110                                 // Using 755 read, write, execute for owner
111                                 // groups and others get read and execute permissions
112                                 // on the folder.
113                                 if err := os.MkdirAll(target, 0755); err != nil {
114                                         return "", pkgerrors.Wrap(err, "Creating directory")
115                                 }
116                         }
117                 case tar.TypeReg:
118                         if target == outDir { // Handle '.' substituted to '' entry
119                                 continue
120                         }
121
122                         err = utils.EnsureDirectory(target)
123                         if err != nil {
124                                 return "", pkgerrors.Wrap(err, "Creating Directory")
125                         }
126
127                         f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
128                         if err != nil {
129                                 return "", pkgerrors.Wrap(err, "Creating file")
130                         }
131
132                         // copy over contents
133                         if _, err := io.Copy(f, tarR); err != nil {
134                                 return "", pkgerrors.Wrap(err, "Copying file content")
135                         }
136
137                         // close for each file instead of a defer for all
138                         // at the end of the function
139                         f.Close()
140                 }
141
142                 first = false
143         }
144
145         return outDir, nil
146 }