1
1
package main
2
2
3
3
import (
4
+ "bytes"
4
5
"github.com/golang/protobuf/proto"
6
+ "heckel.io/fsdup/internal"
7
+ "io"
5
8
"io/ioutil"
6
9
"log"
7
10
"os"
8
11
)
9
12
13
+ type fileType int
14
+
15
+ const (
16
+ typeNtfs fileType = iota + 1
17
+ typeMbrDisk
18
+ typeUnknown
19
+ )
20
+
21
+ const (
22
+ probeTypeBufferLength = 512
23
+
24
+ mbrLength = 512
25
+ mbrSectorSize = 512
26
+ mbrSignatureOffset = 510
27
+ mbrSignatureLength = 2
28
+ mbrSignatureMagic = 0xaa55 // 0x55aa as little endian
29
+ mbrEntryCount = 4
30
+ mbrEntryFirstOffset = 446
31
+ mbrEntryLength = 16
32
+ mbrFirstSectorRelativeOffset = 8
33
+ mbrEntryFirstSectorRelativeLength = 4
34
+ )
35
+
10
36
func index (inputFile string , manifestFile string , offset int64 , nowrite bool , exact bool ) error {
11
37
file , err := os .Open (inputFile )
12
38
if err != nil {
@@ -15,13 +41,20 @@ func index(inputFile string, manifestFile string, offset int64, nowrite bool, ex
15
41
16
42
defer file .Close ()
17
43
18
- // Determine file type (partition, NTFS, other)
19
- // ...
44
+ manifest := & internal.ManifestV1 {}
20
45
21
- ntfs := NewNtfsDeduper (file , offset , nowrite , exact )
22
- manifest , err := ntfs .Dedup ()
46
+ fileType , err := probeType (file , offset )
23
47
if err != nil {
24
- log .Fatalln ("Failed to dedup:" , err )
48
+ return err
49
+ }
50
+
51
+ switch fileType {
52
+ case typeNtfs :
53
+ manifest , err = indexNtfs (file , offset , nowrite , exact )
54
+ case typeMbrDisk :
55
+ manifest , err = indexMbrDisk (file , offset , nowrite , exact )
56
+ default :
57
+ manifest , err = indexOther (file , offset , nowrite )
25
58
}
26
59
27
60
if debug {
@@ -38,4 +71,74 @@ func index(inputFile string, manifestFile string, offset int64, nowrite bool, ex
38
71
}
39
72
40
73
return nil
41
- }
74
+ }
75
+
76
+
77
+ func probeType (reader io.ReaderAt , offset int64 ) (fileType , error ) {
78
+ buffer := make ([]byte , probeTypeBufferLength )
79
+ _ , err := reader .ReadAt (buffer , offset )
80
+ if err != nil {
81
+ return - 1 , err
82
+ }
83
+
84
+ // Detect NTFS (note: this also has an MBR signature!)
85
+ if bytes .Compare ([]byte (ntfsBootMagic ), buffer [ntfsBootMagicOffset :ntfsBootMagicOffset + len (ntfsBootMagic )]) == 0 {
86
+ return typeNtfs , nil
87
+ }
88
+
89
+ // Detect MBR
90
+ if mbrSignatureMagic == parseUintLE (buffer , mbrSignatureOffset , mbrSignatureLength ) {
91
+ return typeMbrDisk , nil
92
+ }
93
+
94
+ return typeUnknown , nil
95
+ }
96
+
97
+ func indexMbrDisk (reader io.ReaderAt , offset int64 , nowrite bool , exact bool ) (* internal.ManifestV1 , error ) {
98
+ println ("i am a disk" )
99
+
100
+ buffer := make ([]byte , mbrLength )
101
+ _ , err := reader .ReadAt (buffer , offset )
102
+ if err != nil {
103
+ return nil , err
104
+ }
105
+
106
+ for i := int64 (0 ); i < mbrEntryCount ; i ++ {
107
+ entryOffset := mbrEntryFirstOffset + i * mbrEntryLength
108
+
109
+ partitionFirstSector := parseUintLE (buffer , entryOffset + mbrFirstSectorRelativeOffset , mbrEntryFirstSectorRelativeLength )
110
+ partitionOffset := offset + partitionFirstSector * mbrSectorSize
111
+ Debugf ("Reading MBR entry at %d, partition begins at sector %d, offset %d\n " ,
112
+ entryOffset , partitionFirstSector , partitionOffset )
113
+
114
+ if partitionOffset == 0 {
115
+ continue
116
+ }
117
+
118
+ partitionType , err := probeType (reader , partitionOffset )
119
+ if err != nil {
120
+ continue
121
+ }
122
+
123
+ if partitionType == typeNtfs {
124
+ Debugf ("NTFS partition found at offset %d\n " , partitionOffset )
125
+ return indexNtfs (reader , partitionOffset , nowrite , exact )
126
+ }
127
+ }
128
+
129
+ return nil , nil
130
+ }
131
+
132
+ func indexNtfs (reader io.ReaderAt , offset int64 , nowrite bool , exact bool ) (* internal.ManifestV1 , error ) {
133
+ ntfs := NewNtfsDeduper (reader , offset , nowrite , exact )
134
+ manifest , err := ntfs .Dedup ()
135
+ if err != nil {
136
+ return nil , err
137
+ }
138
+
139
+ return manifest , nil
140
+ }
141
+
142
+ func indexOther (file * os.File , offset int64 , nowrite bool ) (* internal.ManifestV1 , error ) {
143
+ return nil , nil
144
+ }
0 commit comments