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
|
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -pa ebin -pa ../lager/ebin -pa ../lager/deps/goldrush/ebin
-mode(compile).
-include_lib("kernel/include/file.hrl").
-define(DATA_COMMIT_START_COOKIE, 16#75c2e4b3d5f643a1).
-define(DATA_COMMIT_END_COOKIE, 16#2b05eed61b5af550).
-define(INDEX_COMMIT_END_COOKIE, 16#2fb1778c74a402e4).
-define(DATA_FILE_COOKIE, 16#d53551ba539a4252).
-define(INDEX_FILE_COOKIE, 16#b7e16b02ba8a6d1b).
-define(DATA_ENTRY_COOKIE, 16#e7c1cdc2ba3dc77c).
-define(INDEX_NODE_COOKIE, 16#2e0f555ad73210d1).
openfile(Filename) ->
{ok, File} = file:open(Filename, [read, write, binary, raw]),
File.
%% getroot(File) ->
%% {ok, RootNodeBinary} = file:read(File, ?NODESIZE),
%% Nodemagic = ?NODEMAGIC,
%% <<Nodemagic:2/binary, Node/binary>> = RootNodeBinary,
%% ets:insert(State#state.cachename, {root, Node}),
%% Node;
%% [{root, Node}] ->
%% Node
%% end.
printfile(<<?INDEX_FILE_COOKIE:64/native, Rest/binary>>) ->
io:format("index file header~n", []),
printcommit(Rest, index, 8);
printfile(<<?DATA_FILE_COOKIE:64, Blocksize:32, Q:32, Keylength:32, Rest/binary>>) ->
io:format("data file header: blocksize ~p q ~p keylength ~p~n", [Blocksize, Q, Keylength]),
printcommit(Rest, data, 8+4*3);
printfile(<<Unknown:16/binary, _Rest/binary>>) ->
io:format("unknown byte: ~p at file start~n", [Unknown]),
error.
printnode(<<>>) ->
ok;
printnode(<<Child:64/native, Rest/binary>>) ->
case <<Child:64/big>> of
<<0:1, Offset:63>> ->
io:format(" child ~p~n", [Offset]);
<<1:1, Offset:63>> ->
io:format(" offset ~p~n", [Offset])
end,
printnode(Rest).
printcommit(Data, FileType, FileOffset) ->
OneCommit = case FileType of
index ->
printindex(Data, FileOffset);
data ->
printdata(Data, FileOffset)
end,
case OneCommit of
{{CommitLength, CommitChecksum, Rest}, FileOffset2, FileOffset3} ->
io:format("------- commit ~p bytes at ~p-~p -------~n", [CommitLength, FileOffset, FileOffset3]),
CalculatedChecksum = crypto:hash(sha256, binary:part(Data, 0, CommitLength)),
if
CommitChecksum /= CalculatedChecksum ->
io:format("incorrect checksum~n", []),
io:format("commit: length ~p checksum ~p~n", [CommitLength, CommitChecksum]),
io:format("calculated length ~p checksum ~p~n", [FileOffset2 - FileOffset, crypto:hash(sha256, binary:part(Data, 0, CommitLength))]),
io:format("checksummed data: ~p~n", [binary:part(Data, 0, CommitLength)]),
exit(assert);
CommitLength /= (FileOffset2 - FileOffset) ->
io:format("length and offset mismatch~n", []),
io:format("commit: length ~p checksum ~p~n", [CommitLength, CommitChecksum]),
io:format("calculated length ~p checksum ~p~n", [FileOffset2 - FileOffset, crypto:hash(sha256, binary:part(Data, 0, CommitLength))]),
io:format("checksummed data: ~p~n", [binary:part(Data, 0, CommitLength)]),
exit(assert);
true ->
ok
end,
printcommit(Rest, FileType, FileOffset3);
{ok, FileOffset2} ->
io:format("ending at offset ~p~n", [FileOffset]),
ok
end.
printindex(<<>>, FileOffset) ->
{ok, FileOffset};
printindex(<<?INDEX_NODE_COOKIE:64/native, Rest/binary>>, FileOffset) ->
FileOffset2 = FileOffset + 8,
Q = 2,
NChildren = 4,
ChildrenLength = NChildren * 8,
<<Children:ChildrenLength/binary, Rest2/binary>> = Rest,
io:format("node ~p~n", [FileOffset]),
printnode(Children),
printindex(Rest2, FileOffset2 + ChildrenLength);
printindex(<<CommitLength:64/native, CommitChecksum:32/binary, ?INDEX_COMMIT_END_COOKIE:64/native, Rest/binary>>, FileOffset) ->
{{CommitLength, CommitChecksum, Rest}, FileOffset + 8, FileOffset + 8 + 32 + 8};
printindex(<<Unknown:16/binary, _Rest/binary>>, FileOffset) ->
io:format("unknown byte: ~p at ~p~n", [Unknown, FileOffset]),
error.
printdata(<<>>, FileOffset) ->
{ok, FileOffset};
printdata(<<?DATA_ENTRY_COOKIE:64, Key:32/binary, 1:16, Length:16, Rest/binary>>, FileOffset) ->
FileOffset2 = FileOffset + 8 + 32 + 4,
io:format("data ~p key ~p length ~p~n", [FileOffset, Key, Length]),
<<Data:Length/binary, Rest2/binary>> = Rest,
printdata(Rest2, FileOffset2 + Length);
printdata(<<?DATA_COMMIT_START_COOKIE:64, Rest2/binary>> = Rest, FileOffset) ->
Padding = case FileOffset rem 4 of
0 ->
0;
1 ->
3;
2 ->
2;
3 ->
1
end,
io:format("printdata: ~p ~p~n", [Padding, FileOffset]),
<<0:Padding/unit:8, CommitLength:32, CommitChecksum:32/binary, ?DATA_COMMIT_END_COOKIE:64, Rest3/binary>> = Rest2,
{{CommitLength, CommitChecksum, Rest3}, FileOffset + 8 + Padding + 4, FileOffset + 8 + Padding + 4 + 32 + 8};
printdata(<<Unknown:16/binary, _Rest/binary>>, FileOffset) ->
io:format("unknown byte: ~p at ~p~n", [Unknown, FileOffset]),
error.
main([Filename]) ->
{ok, FileInfo} = file:read_file_info(Filename),
File = openfile(Filename),
{ok, Data} = file:read(File, FileInfo#file_info.size),
io:format("read ~p bytes~n", [size(Data)]),
ok = printfile(Data),
ok.
|