-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEsfsFileInfo.cs
133 lines (109 loc) · 4.33 KB
/
EsfsFileInfo.cs
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
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace EsfsLite
{
public enum EsfsFileAttributes
{
Normal,
System,
Directory
};
struct EsfsFileInfoPart
{
public EsfsFileAttributes Attribute;
public int TimestampCreated;
public int TimestampModifyed;
public Int64 Size;
public Int64 StartSector;
public Int64 EndSector;
public Int64 ParentDirectory;
}
public class EsfsFileInfo : ICloneable
{
private const int MaxFileNameLengthBytes = 256;
private EsfsFileInfoPart _partInfo;
private readonly byte[] _targetBuffer;
public EsfsFileAttributes Attribute;
public DateTime TimestampCreated;
public DateTime TimestampModifyed;
public Int64 Size;
public Int64 StartSector;
public Int64 EndSector;
public Int64 ParentDirectory;
public string FileName;
public byte[] Meta;
public EsfsFileInfo()
{
_targetBuffer = new byte[Esfs.SectorSizeContentBytes];
Meta = new byte[Esfs.SectorSizeContentBytes -
Marshal.SizeOf(typeof (EsfsFileInfoPart)) - MaxFileNameLengthBytes];
}
public void FromBytes(byte[] data, int offset)
{
var partInfoSize = Marshal.SizeOf(typeof(EsfsFileInfoPart));
var intermediateBuffer = Marshal.AllocHGlobal(partInfoSize);
try
{
Marshal.Copy(data, offset, intermediateBuffer, partInfoSize);
_partInfo = (EsfsFileInfoPart) Marshal.PtrToStructure(intermediateBuffer, typeof (EsfsFileInfoPart));
}
finally
{
Marshal.FreeHGlobal(intermediateBuffer);
}
var fileNameLengthBytes = 0;
while (data[offset + partInfoSize + fileNameLengthBytes] != 0 && fileNameLengthBytes < MaxFileNameLengthBytes)
{
fileNameLengthBytes++;
}
FileName = Encoding.UTF8.GetString(data, offset + partInfoSize, fileNameLengthBytes);
Array.Copy(data, Esfs.SectorSizeContentBytes - Meta.Length, Meta, 0, Meta.Length);
Attribute = _partInfo.Attribute;
TimestampCreated = _partInfo.TimestampCreated.FromUnixTimestamp();
TimestampModifyed = _partInfo.TimestampModifyed.FromUnixTimestamp();
Size = _partInfo.Size;
StartSector = _partInfo.StartSector;
EndSector = _partInfo.EndSector;
ParentDirectory = _partInfo.ParentDirectory;
}
public byte[] ToBytes()
{
_partInfo.Attribute = Attribute;
_partInfo.TimestampCreated = TimestampCreated.ToUnixTimestamp();
_partInfo.TimestampModifyed = TimestampModifyed.ToUnixTimestamp();
_partInfo.Size = Size;
_partInfo.StartSector = StartSector;
_partInfo.EndSector = EndSector;
_partInfo.ParentDirectory = ParentDirectory;
var partInfoSize = Marshal.SizeOf(typeof(EsfsFileInfoPart));
var intermediateBuffer = Marshal.AllocHGlobal(partInfoSize);
try
{
Marshal.StructureToPtr(_partInfo, intermediateBuffer, false);
Marshal.Copy(intermediateBuffer, _targetBuffer, 0, partInfoSize);
}
finally
{
Marshal.FreeHGlobal(intermediateBuffer);
}
var fileNameBytes = Encoding.UTF8.GetBytes(FileName);
for (var n = partInfoSize; n < _targetBuffer.Length; n++)
{
_targetBuffer[n] = 0;
}
var fileNameBytesLength = fileNameBytes.Length;
if (fileNameBytesLength > MaxFileNameLengthBytes)
{
fileNameBytesLength = MaxFileNameLengthBytes;
}
Array.Copy(fileNameBytes, 0, _targetBuffer, partInfoSize, fileNameBytesLength);
Array.Copy(Meta, 0, _targetBuffer, Esfs.SectorSizeContentBytes - Meta.Length, Meta.Length);
return _targetBuffer;
}
public object Clone()
{
return MemberwiseClone();
}
}
}