-
Notifications
You must be signed in to change notification settings - Fork 5
/
udf.go
118 lines (95 loc) · 2.48 KB
/
udf.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 udf
import (
"io"
)
const SECTOR_SIZE = 2048
type Udf struct {
r io.ReaderAt
isInited bool
pvd *PrimaryVolumeDescriptor
pd *PartitionDescriptor
lvd *LogicalVolumeDescriptor
fsd *FileSetDescriptor
root_fe *FileEntry
}
func (udf *Udf) PartitionStart() uint64 {
if udf.pd == nil {
panic(udf)
} else {
return uint64(udf.pd.PartitionStartingLocation)
}
}
func (udf *Udf) GetReader() io.ReaderAt {
return udf.r
}
func (udf *Udf) ReadSectors(sectorNumber uint64, sectorsCount uint64) []byte {
buf := make([]byte, SECTOR_SIZE*sectorsCount)
readed, err := udf.r.ReadAt(buf[:], int64(SECTOR_SIZE*sectorNumber))
if err != nil {
panic(err)
}
if readed != int(SECTOR_SIZE*sectorsCount) {
panic(readed)
}
return buf[:]
}
func (udf *Udf) ReadSector(sectorNumber uint64) []byte {
return udf.ReadSectors(sectorNumber, 1)
}
func (udf *Udf) init() {
if udf.isInited {
return
}
anchorDesc := NewAnchorVolumeDescriptorPointer(udf.ReadSector(256))
if anchorDesc.Descriptor.TagIdentifier != DESCRIPTOR_ANCHOR_VOLUME_POINTER {
panic(anchorDesc.Descriptor.TagIdentifier)
}
for sector := uint64(anchorDesc.MainVolumeDescriptorSeq.Location); ; sector++ {
desc := NewDescriptor(udf.ReadSector(sector))
if desc.TagIdentifier == DESCRIPTOR_TERMINATING {
break
}
switch desc.TagIdentifier {
case DESCRIPTOR_PRIMARY_VOLUME:
udf.pvd = desc.PrimaryVolumeDescriptor()
case DESCRIPTOR_PARTITION:
udf.pd = desc.PartitionDescriptor()
case DESCRIPTOR_LOGICAL_VOLUME:
udf.lvd = desc.LogicalVolumeDescriptor()
}
}
partitionStart := udf.PartitionStart()
udf.fsd = NewFileSetDescriptor(udf.ReadSector(partitionStart + udf.lvd.LogicalVolumeContentsUse.Location))
udf.root_fe = NewFileEntry(udf.ReadSector(partitionStart + udf.fsd.RootDirectoryICB.Location))
udf.isInited = true
}
func (udf *Udf) ReadDir(fe *FileEntry) []File {
udf.init()
if fe == nil {
fe = udf.root_fe
}
ps := udf.PartitionStart()
adPos := fe.AllocationDescriptors[0]
fdLen := uint64(adPos.Length)
fdBuf := udf.ReadSectors(ps+uint64(adPos.Location), (fdLen+SECTOR_SIZE-1)/SECTOR_SIZE)
fdOff := uint64(0)
result := make([]File, 0)
for uint32(fdOff) < adPos.Length {
fid := NewFileIdentifierDescriptor(fdBuf[fdOff:])
if fid.FileIdentifier != "" {
result = append(result, File{
Udf: udf,
Fid: fid,
})
}
fdOff += fid.Len()
}
return result
}
func NewUdfFromReader(r io.ReaderAt) *Udf {
udf := &Udf{
r: r,
isInited: false,
}
return udf
}