Skip to content

Commit dd79448

Browse files
dedmenDahlgren
authored andcommitted
New storage for fileTree (#7)
1 parent 6e902e7 commit dd79448

File tree

9 files changed

+217
-78
lines changed

9 files changed

+217
-78
lines changed

DokanPbo.Core/DokanPbo.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<AppDesignerFolder>Properties</AppDesignerFolder>
1010
<RootNamespace>DokanPbo.Core</RootNamespace>
1111
<AssemblyName>DokanPbo.Core</AssemblyName>
12-
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
12+
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
1313
<FileAlignment>512</FileAlignment>
1414
<TargetFrameworkProfile />
1515
</PropertyGroup>

DokanPbo.Core/PboFS.cs

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ private PboFsFolder CreateOrFindDirectoryRecursive(string fullPath)
140140
if (foundNode == null)
141141
{
142142
folder = new PboFsFolder(folderName, currentFolder);
143-
fileTree.AddNode(currentPath, folder);
143+
fileTree.AddNode(folder);
144144
}
145145
else
146146
{
@@ -175,16 +175,17 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha
175175
case FileMode.OpenOrCreate:
176176
if (filename.Length == 0)
177177
return NtStatus.Success;
178-
var Directory = filename.Substring(0, filename.LastIndexOf('\\'));
179-
if (Directory.Length == 0)
180-
Directory = "\\";
178+
string Directory = filename;
179+
if (!info.IsDirectory) //Directory doesn't have a filename that we want to cut off
180+
{
181+
Directory = filename.Substring(0, filename.LastIndexOf('\\'));
182+
if (Directory.Length == 0)
183+
Directory = "\\";
184+
}
185+
181186

182187
var nodeDirectory = CreateOrFindDirectoryRecursive(Directory);
183188

184-
//Filename without folder path
185-
var FileNameDirect = filename.Substring(filename.LastIndexOf('\\'));
186-
var FileNameDirectNoLeadingSlash = filename.Substring(filename.LastIndexOf('\\') + 1);
187-
188189
if (!(nodeDirectory is PboFsRealFolder) && nodeDirectory is PboFsFolder virtualFolder)
189190
{
190191
nodeDirectory = fileTree.MakeDirectoryWriteable(virtualFolder);
@@ -195,16 +196,16 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha
195196

196197
if (info.IsDirectory)
197198
{
198-
System.IO.Directory.CreateDirectory(folder.path + FileNameDirect);//#TODO create directory recursively if needed
199-
200-
var rlFolder = new PboFsRealFolder(FileNameDirectNoLeadingSlash, folder.path + FileNameDirect, folder);
201-
202-
folder.Children[FileNameDirectNoLeadingSlash.ToLower()] = rlFolder;
203-
fileTree.AddNode(filename.ToLower(), rlFolder);
204-
info.Context = rlFolder;
199+
info.Context = nodeDirectory;
200+
//Nothing else to do as full path is already included in DirectoryPath
205201
}
206202
else
207203
{
204+
205+
//Filename without folder path
206+
var FileNameDirect = filename.Substring(filename.LastIndexOf('\\'));
207+
var FileNameDirectNoLeadingSlash = filename.Substring(filename.LastIndexOf('\\') + 1);
208+
208209
FileStream newStream = null;
209210
try
210211
{
@@ -219,7 +220,7 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha
219220
var rlFile = new PboFsRealFile(new System.IO.FileInfo(folder.path + FileNameDirect), folder, newStream);
220221

221222
folder.Children[FileNameDirectNoLeadingSlash.ToLower()] = rlFile;
222-
fileTree.AddNode(filename.ToLower(), rlFile);
223+
fileTree.AddNode(rlFile);
223224
info.Context = rlFile;
224225
}
225226

@@ -262,16 +263,16 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha
262263
return DokanResult.AccessDenied;
263264

264265
if (node is IPboFsFile file && (wantsRead || wantsWrite))
265-
return file.Open(wantsWrite);
266+
return file.Open(wantsWrite, mode);
266267

267268
return DokanResult.Success;
268269
}
269270

270271
public NtStatus DeleteDirectory(string filename, DokanFileInfo info)
271272
{
272273
//This is called after Windows asked the user for confirmation.
273-
274-
if (!(GetNodeFast(filename, info) is PboFsRealFolder folder)) return DokanResult.NotImplemented;
274+
var gnf = GetNodeFast(filename, info);
275+
if (!(gnf is PboFsRealFolder folder)) return DokanResult.NotImplemented;
275276

276277
try
277278
{
@@ -415,14 +416,15 @@ public NtStatus MoveFile(string filename, string newname, bool replace, DokanFil
415416
nodeTargetDirectory.Children.Add(targetFilenameDirect.ToLower(), nodeSourceDirectory.Children[sourceFilenameDirect.ToLower()]);
416417
nodeSourceDirectory.Children.Remove(sourceFilenameDirect.ToLower());
417418

418-
419-
fileTree.AddNode(PrefixedFilename(newname), file);
420-
fileTree.DeleteNode(PrefixedFilename(filename));
419+
fileTree.DeleteNode(file);
421420

422421
System.IO.File.Move(file.GetRealPath(), fileTree.writeableDirectory + newname);
423422

424423
file.file = new FileInfo(fileTree.writeableDirectory + newname);
425424
file.FileInformation.FileName = targetFilenameDirect;
425+
file.parent = nodeTargetDirectory;
426+
427+
fileTree.AddNode(file);
426428

427429
return DokanResult.Success;
428430
case PboFsRealFolder folder:
@@ -433,26 +435,48 @@ public NtStatus MoveFile(string filename, string newname, bool replace, DokanFil
433435
nodeTargetDirectory.Children.Add(targetFilenameDirect.ToLower(), nodeSourceDirectory.Children[sourceFilenameDirect.ToLower()]);
434436
nodeSourceDirectory.Children.Remove(sourceFilenameDirect.ToLower());
435437

436-
fileTree.AddNode(PrefixedFilename(newname), folder);
437-
fileTree.DeleteNode(PrefixedFilename(filename));
438-
439-
System.IO.Directory.Move(folder.path, fileTree.writeableDirectory + newname);
440-
folder.path = fileTree.writeableDirectory + newname;
441-
folder.FileInformation.FileName = targetFilenameDirect;
442438

443-
void moveNodesRecursive(PboFsFolder folderIn, string basePath)
439+
void doNodesRecursive(PboFsFolder folderIn, bool remove)
444440
{
445441
foreach (var entry in folderIn.Children)
446442
{
447-
var curFullPath = basePath + "\\" + entry.Key;
448-
fileTree.AddNode(newname + curFullPath.Substring(filename.Length), entry.Value);
449-
fileTree.DeleteNode(curFullPath);
443+
if (remove)
444+
{
445+
fileTree.DeleteNode(entry.Value);
446+
if (entry.Value is PboFsRealFile file)
447+
{
448+
file.Close();
449+
}
450+
}
451+
452+
else
453+
{
454+
fileTree.AddNode(entry.Value);
455+
if (entry.Value is PboFsRealFile file)
456+
{
457+
file.file = new FileInfo(file.file.FullName.Replace(filename,newname));
458+
}
459+
460+
}
461+
450462
if (entry.Value is PboFsFolder nextFolder)
451-
moveNodesRecursive(nextFolder, curFullPath);
463+
doNodesRecursive(nextFolder, remove);
452464
}
453465
}
454466

455-
moveNodesRecursive(folder, filename);
467+
468+
469+
fileTree.DeleteNode(folder);
470+
doNodesRecursive(folder, true);
471+
472+
System.IO.Directory.Move(folder.path, fileTree.writeableDirectory + newname);
473+
folder.path = fileTree.writeableDirectory + newname;
474+
folder.FileInformation.FileName = targetFilenameDirect;
475+
folder.parent = nodeTargetDirectory;
476+
477+
fileTree.AddNode(folder);
478+
479+
doNodesRecursive(folder, false);
456480

457481
return DokanResult.Success;
458482
default:

DokanPbo.Core/PboFSNode.cs

Lines changed: 115 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,111 @@ namespace DokanPbo
1212
public abstract class IPboFsNode
1313
{
1414
public FileInformation FileInformation;
15+
public PboFsFolder parent;
16+
17+
public override int GetHashCode()
18+
{
19+
20+
int hashCode = FileInformation.FileName?.ToLower().GetHashCode() ?? "".GetHashCode();
21+
var element = parent;
22+
while (element != null)
23+
{
24+
if (element.FileInformation.FileName != null && element.FileInformation.FileName != "")
25+
hashCode = hashCode * 23 + element.FileInformation.FileName.ToLower().GetHashCode();
26+
element = element.parent;
27+
}
28+
29+
return hashCode;
30+
}
31+
32+
public override bool Equals(object obj)
33+
{
34+
35+
if (obj is PboFsLookupDummy dummy)
36+
return dummy.Equals(this);
37+
38+
if (obj is IPboFsNode node)
39+
{
40+
if (!FileInformation.FileName.Equals(node.FileInformation.FileName, StringComparison.CurrentCultureIgnoreCase)) return false;
41+
42+
var lparent = parent;
43+
var rparent = node.parent;
44+
while (lparent != null && rparent != null)
45+
{
46+
if ((lparent.FileInformation.FileName == null || rparent.FileInformation.FileName == null))
47+
return rparent.FileInformation.FileName == lparent.FileInformation.FileName;
48+
49+
if (!lparent.FileInformation.FileName.Equals(rparent.FileInformation.FileName, StringComparison.CurrentCultureIgnoreCase)) return false;
50+
lparent = lparent.parent;
51+
rparent = rparent.parent;
52+
}
53+
54+
return rparent == lparent; //one of them is null. If the other isn't also null then they didn't match.
55+
}
56+
57+
return false;
58+
}
59+
}
60+
61+
public class PboFsLookupDummy : IPboFsNode
62+
{
63+
private List<string> path = new List<string>();
64+
65+
66+
public PboFsLookupDummy(string inputPath)
67+
{
68+
var splitPath = inputPath.Split('\\');
69+
foreach (var it in splitPath)
70+
path.Add(it.ToLower());
71+
72+
path.RemoveAll((x) => x == "");
73+
if (path.Count == 0) return;
74+
75+
path.Reverse();
76+
}
77+
78+
79+
public override int GetHashCode()
80+
{
81+
if (path.Count == 0) return "".GetHashCode();
82+
83+
bool first = true;
84+
int hashCode = 0;
85+
86+
foreach (var it in path)
87+
{
88+
if (first)
89+
{
90+
hashCode = it.GetHashCode();
91+
first = false;
92+
} else
93+
hashCode = hashCode * 23 + it.GetHashCode();
94+
}
95+
96+
return hashCode;
97+
}
98+
99+
public override bool Equals(object obj)
100+
{
101+
if (obj is IPboFsNode node)
102+
{
103+
104+
if (parent == null && node.parent == null) return true; //Both are root node. Done here because root node doesn't have a path
105+
106+
var rparent = node;
107+
foreach (var it in path)
108+
{
109+
if (rparent == null) return false;
110+
if (!it.Equals(rparent.FileInformation.FileName, StringComparison.CurrentCultureIgnoreCase)) return false;
111+
rparent = rparent.parent;
112+
}
113+
114+
return rparent?.parent == null; //If it is not null. We didn't arrive at root node which we should've
115+
}
116+
117+
118+
return false;
119+
}
15120
}
16121

17122
public abstract class IPboFsFolder : IPboFsNode
@@ -24,7 +129,7 @@ public abstract class IPboFsFile : IPboFsNode
24129
public abstract NtStatus ReadFile(byte[] buffer, out int readBytes, long offset);
25130

26131
//Can be used to prepare the Stream and keep it in cache
27-
public virtual NtStatus Open(bool write = false)
132+
public virtual NtStatus Open(bool write = false, FileMode mode = FileMode.Open)
28133
{
29134
return NtStatus.Success;
30135
}
@@ -44,7 +149,6 @@ public interface IPboFsRealObject
44149

45150
public class PboFsFolder : IPboFsFolder
46151
{
47-
public PboFsFolder parent;
48152
public Dictionary<string, IPboFsNode> Children;
49153

50154
public PboFsFolder(string name, PboFsFolder inputParent) : base()
@@ -66,10 +170,11 @@ public class PboFsFile : IPboFsFile
66170
{
67171
public FileEntry File;
68172

69-
public PboFsFile(string name, FileEntry file) : base()
173+
public PboFsFile(string name, FileEntry file, PboFsFolder inputParent) : base()
70174
{
71175
File = file;
72176
var fileTimestamp = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime().AddSeconds(file.TimeStamp);
177+
parent = inputParent;
73178
FileInformation = new DokanNet.FileInformation()
74179
{
75180
Attributes = System.IO.FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Temporary | FileAttributes.Archive,
@@ -108,7 +213,7 @@ public class PboFsDebinarizedFile : PboFsFile
108213
{
109214
public System.IO.Stream debinarizedStream = null;
110215

111-
public PboFsDebinarizedFile(string name, FileEntry file) : base(name, file)
216+
public PboFsDebinarizedFile(string name, FileEntry file, PboFsFolder inputParent) : base(name, file, inputParent)
112217
{
113218
}
114219

@@ -170,9 +275,9 @@ public string GetRealPath()
170275

171276
public class PboFsRealFile : IPboFsFile, IPboFsRealObject
172277
{
173-
public PboFsFolder parent;
174278
public System.IO.FileInfo file;
175279
private bool? wantsOpenWrite;
280+
private FileMode openMode;
176281
private System.IO.FileStream readStream = null;
177282
private System.IO.FileStream writeStream = null;
178283

@@ -204,7 +309,7 @@ public PboFsRealFile(System.IO.FileInfo inputFile, PboFsFolder inputParent, Syst
204309
//Might throw FileNotFoundException
205310
private System.IO.FileStream OpenStream(bool write)
206311
{
207-
return file.Open(FileMode.Open, write ? FileAccess.ReadWrite : FileAccess.Read, FileShare.ReadWrite);
312+
return file.Open(openMode, write ? FileAccess.ReadWrite : FileAccess.Read, FileShare.ReadWrite);
208313
}
209314

210315
//Might throw FileNotFoundException
@@ -235,9 +340,10 @@ private System.IO.FileStream OpenStream(bool write)
235340
return write ? (OpenStream(true), false) : (OpenStream(false), false);
236341
}
237342

238-
public override NtStatus Open(bool write)
343+
public override NtStatus Open(bool write, FileMode mode)
239344
{
240345
wantsOpenWrite = write;
346+
openMode = mode;
241347
return NtStatus.Success;
242348
}
243349

@@ -325,6 +431,8 @@ public NtStatus SetEof(long length)
325431

326432
if (!streamFromCache)
327433
stream.Close(); //#TODO cache
434+
file.Refresh();
435+
FileInformation.Length = length;
328436
return DokanResult.Success;
329437
}
330438
catch (FileNotFoundException e)

0 commit comments

Comments
 (0)