forked from sophaskins/efs2tar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
140 lines (128 loc) · 3.22 KB
/
main.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// EFS .iso, .img, .efs => .tar
package main
import (
"archive/tar"
"errors"
"flag"
"log"
"os"
"strings"
"github.com/sgi-demos/efs2tar/efs"
"github.com/sgi-demos/efs2tar/sgi"
)
func exists(pathName string) bool {
_, err := os.Stat(pathName)
return !os.IsNotExist(err)
}
func main() {
// get efs and tar file names
inputPath := flag.String("in", "", "the file to be read as an efs filesystem")
outputPath := flag.String("out", "", "the file to written to as a tar file")
checkPath := flag.String("check", "", "the file to be checked for an efs filesystem")
flag.Parse()
checkEFSonly := len(*inputPath) == 0 && len(*checkPath) > 0
if checkEFSonly {
inputPath = checkPath
}
// allow input path as the only arg without specifying -in
if len(*inputPath) == 0 {
args := os.Args
if len(*outputPath) == 0 && len(args) == 2 {
*inputPath = args[1]
} else {
log.Fatal(errors.New("ERROR: need input EFS"))
}
}
if !checkEFSonly {
// generate tar file name if not provided
var outFile string
var rootName string
if len(*inputPath) > 0 && len(*outputPath) == 0 {
inFile := *inputPath
extPos := strings.LastIndex(inFile, ".")
if extPos > 0 {
rootName = inFile[:extPos]
} else {
rootName = inFile
}
outFile = rootName + ".tar"
outputPath = &outFile
}
if exists(*outputPath) {
log.Fatal(errors.New("WARNING: tar exists: " + *outputPath))
}
}
// read efs file
file, err := os.Open(*inputPath)
if err != nil {
log.Fatal(err)
}
b := make([]byte, 51200)
_, err = file.Read(b)
if err != nil {
log.Fatal(err)
}
// ensure efs file is valid
vh := sgi.NewVolumeHeader(b)
p := vh.Partitions[7]
fs := efs.NewFilesystem(file, p.Blocks, p.First)
rootNode := fs.RootInode()
if rootNode.Size == 0 {
log.Fatal(errors.New("WARNING: invalid EFS: " + *inputPath))
} else {
if !checkEFSonly {
// write tar file
outputFile, err := os.OpenFile(*outputPath, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0755)
if err != nil {
log.Fatal(err)
}
tw := tar.NewWriter(outputFile)
fs.WalkFilesystem(buildTarCallback(tw, fs))
tw.Close()
log.Fatal(errors.New("OK: valid EFS: " + *inputPath + "\nwrote tar: " + *outputPath))
} else {
// just check EFS
log.Fatal(errors.New("OK: valid EFS: " + *inputPath))
}
}
}
func buildTarCallback(tw *tar.Writer, fs *efs.Filesystem) func(efs.Inode, string) {
return func(in efs.Inode, path string) {
if path == "" {
return
}
if in.Type() == efs.FileTypeDirectory {
hdr := &tar.Header{
Name: path,
Mode: 0755,
Typeflag: tar.TypeDir,
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatal(err)
}
} else if in.Type() == efs.FileTypeRegular {
contents := fs.FileContents(in)
hdr := &tar.Header{
Name: path,
Mode: 0755,
Size: int64(len(contents)),
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatal(err)
}
if _, err := tw.Write([]byte(contents)); err != nil {
log.Fatal(err)
}
} else if in.Type() == efs.FileTypeSymlink {
contents := fs.FileContents(in)
hdr := &tar.Header{
Name: path,
Linkname: string(contents[:int64(len(contents))]),
Typeflag: tar.TypeSymlink,
}
if err := tw.WriteHeader(hdr); err != nil {
log.Fatal(err)
}
}
}
}