-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcontainer.go
executable file
·118 lines (93 loc) · 2.22 KB
/
container.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
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
"unicode/utf16"
)
type InvalidElementHeader struct {
}
func (err InvalidElementHeader) Error() string {
return "Invalid element header!"
}
type DataProcessor interface {
ProcessData(f *os.File, filename string) error
}
// FileHeader is a file header
type FileHeader struct {
NextPageAddr int32
PageSize int32
StorageVer int32
Reserved int32
}
type ElemAddr struct {
ElemHeaderAddr int32
ElemDataAddr int32
Reserved int32
}
func ElemAddrSize() int {
return 4 + 4 + 4
}
func (header *FileHeader) Read(r io.Reader) {
binary.Read(r, binary.LittleEndian, header)
}
type ElemHeader struct {
DateCreation uint64
DateModification uint64
Reserved int32
}
func getElemName(data []byte) (header ElemHeader, name string, err error) {
sz := binary.Size(header)
if sz >= len(data) {
err = InvalidElementHeader{}
return
}
inbuffer := bytes.NewBuffer(data)
binary.Read(inbuffer, binary.LittleEndian, &header)
off := data[sz:]
len := len(off) / 2
utf16Data := make([]uint16, len)
for i := 0; i < len; i++ {
utf16Data[i] = uint16(off[i*2]) | uint16(off[i*2+1])<<8
}
name = string(utf16.Decode(utf16Data))
return
}
// UnpackToDirectoryNoLoad Unpacks
func UnpackToDirectoryNoLoad(dirname string, file *os.File, FileDataSize int64, fileProcessor DataProcessor) error {
supplyDirectory(dirname)
var header FileHeader
header.Read(file)
elemAddrs, err := ReadDataBlock(file)
if err != nil {
return err
}
elemsNum := len(elemAddrs) / ElemAddrSize()
elemsReader := bytes.NewReader(elemAddrs)
for i := 0; i < elemsNum; i++ {
var addr ElemAddr
binary.Read(elemsReader, binary.LittleEndian, &addr)
if addr.Reserved != magicUndefined {
fmt.Printf("Done at %d\n", i)
break
}
file.Seek(int64(addr.ElemHeaderAddr), os.SEEK_SET)
elemHeaderData, err := ReadDataBlock(file)
if err != nil {
return err
}
_, elemName, err := getElemName(elemHeaderData)
if err != nil {
return err
}
fmt.Printf("found file %s/%s ", dirname, elemName)
if addr.ElemDataAddr != magicUndefined {
file.Seek(int64(addr.ElemDataAddr), os.SEEK_SET)
fileProcessor.ProcessData(file, elemName)
}
fmt.Println()
}
return nil
}