-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathrpm2tar.go
124 lines (115 loc) · 4.04 KB
/
rpm2tar.go
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"archive/tar"
"fmt"
"os"
"sort"
"strings"
"github.com/rmohr/bazeldnf/pkg/order"
"github.com/rmohr/bazeldnf/pkg/rpm"
"github.com/spf13/cobra"
)
type rpm2tarOpts struct {
output string
input []string
sortedSymlinks []string
symlinks map[string]string
capabilities map[string]string
selinuxLabels map[string]string
}
var rpm2taropts = rpm2tarOpts{}
func NewRpm2TarCmd() *cobra.Command {
rpm2tarCmd := &cobra.Command{
Use: "rpm2tar",
Short: "convert a rpm to a tar archive",
RunE: func(cmd *cobra.Command, args []string) (err error) {
sortSymlinkKeys()
rpmStream := os.Stdin
tarStream := os.Stdout
if rpm2taropts.output != "" {
tarStream, err = os.Create(rpm2taropts.output)
if err != nil {
return fmt.Errorf("could not create tar: %v", err)
}
}
cap := map[string][]string{}
for file, caps := range rpm2taropts.capabilities {
split := strings.Split(caps, ":")
if len(split) > 0 {
cap["./"+strings.TrimPrefix(file, "/")] = split
}
}
tarWriter := tar.NewWriter(tarStream)
defer tarWriter.Close()
collector := rpm.NewCollector()
if len(rpm2taropts.input) != 0 {
directoryTree, err := order.TreeFromRPMs(rpm2taropts.input)
if err != nil {
return err
}
for _, k := range rpm2taropts.sortedSymlinks {
v := rpm2taropts.symlinks[k]
// If an absolute path is given let's add a `.` in front. This is
// not strictly necessary but adds a more correct tar path
// which aligns with the usual rpm entries which start with `./`
if strings.HasPrefix(k, "/") {
k = "." + k
}
directoryTree.Add(
[]tar.Header{
{
Typeflag: tar.TypeSymlink,
Name: k,
Linkname: v,
Mode: 0o777,
},
},
)
}
for _, header := range directoryTree.Traverse() {
err := tarWriter.WriteHeader(&header)
if err != nil {
return fmt.Errorf("failed to write header %s: %v", header.Name, err)
}
}
for _, i := range rpm2taropts.input {
rpmStream, err = os.Open(i)
if err != nil {
return fmt.Errorf("could not open rpm at %s: %v", i, err)
}
defer rpmStream.Close()
err = collector.RPMToTar(rpmStream, tarWriter, true, cap, rpm2taropts.selinuxLabels)
if err != nil {
return fmt.Errorf("could not convert rpm at %s: %v", i, err)
}
}
} else {
err := collector.RPMToTar(rpmStream, tarWriter, false, cap, rpm2taropts.selinuxLabels)
if err != nil {
return fmt.Errorf("could not convert rpm : %v", err)
}
}
return nil
},
}
rpm2tarCmd.Flags().StringVarP(&rpm2taropts.output, "output", "o", "", "location of the resulting tar file (defaults to stdout)")
rpm2tarCmd.Flags().StringArrayVarP(&rpm2taropts.input, "input", "i", []string{}, "location from where to read the rpm file (defaults to stdin)")
rpm2tarCmd.Flags().StringToStringVarP(&rpm2taropts.symlinks, "symlinks", "s", map[string]string{}, "symlinks to add. Relative or absolute.")
rpm2tarCmd.Flags().StringToStringVarP(&rpm2taropts.capabilities, "capabilities", "c", map[string]string{}, "capabilities of files (--capabilities=/bin/ls=cap_net_bind_service)")
rpm2tarCmd.Flags().StringToStringVar(&rpm2taropts.selinuxLabels, "selinux-labels", map[string]string{}, "selinux labels of files (--selinux-labels=/bin/ls=unconfined_u:object_r:default_t:s0)")
// deprecated options
rpm2tarCmd.Flags().StringToStringVar(&rpm2taropts.capabilities, "capabilties", map[string]string{}, "capabilities of files (-c=/bin/ls=cap_net_bind_service)")
rpm2tarCmd.Flags().MarkDeprecated("capabilties", "use --capabilities instead")
rpm2tarCmd.Flags().MarkShorthandDeprecated("capabilities", "use --capabilities instead")
rpm2tarCmd.Flags().MarkShorthandDeprecated("symlinks", "use --symlinks instead")
return rpm2tarCmd
}
func sortSymlinkKeys() {
rpm2taropts.sortedSymlinks = make([]string, len(rpm2taropts.symlinks))
i := 0
for k := range rpm2taropts.symlinks {
rpm2taropts.sortedSymlinks[i] = k
i++
}
sort.Strings(rpm2taropts.sortedSymlinks)
}