Skip to content

Commit

Permalink
New storage for fileTree (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
dedmen authored and Dahlgren committed Nov 26, 2018
1 parent 6e902e7 commit dd79448
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 78 deletions.
2 changes: 1 addition & 1 deletion DokanPbo.Core/DokanPbo.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DokanPbo.Core</RootNamespace>
<AssemblyName>DokanPbo.Core</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
Expand Down
92 changes: 58 additions & 34 deletions DokanPbo.Core/PboFS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private PboFsFolder CreateOrFindDirectoryRecursive(string fullPath)
if (foundNode == null)
{
folder = new PboFsFolder(folderName, currentFolder);
fileTree.AddNode(currentPath, folder);
fileTree.AddNode(folder);
}
else
{
Expand Down Expand Up @@ -175,16 +175,17 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha
case FileMode.OpenOrCreate:
if (filename.Length == 0)
return NtStatus.Success;
var Directory = filename.Substring(0, filename.LastIndexOf('\\'));
if (Directory.Length == 0)
Directory = "\\";
string Directory = filename;
if (!info.IsDirectory) //Directory doesn't have a filename that we want to cut off
{
Directory = filename.Substring(0, filename.LastIndexOf('\\'));
if (Directory.Length == 0)
Directory = "\\";
}


var nodeDirectory = CreateOrFindDirectoryRecursive(Directory);

//Filename without folder path
var FileNameDirect = filename.Substring(filename.LastIndexOf('\\'));
var FileNameDirectNoLeadingSlash = filename.Substring(filename.LastIndexOf('\\') + 1);

if (!(nodeDirectory is PboFsRealFolder) && nodeDirectory is PboFsFolder virtualFolder)
{
nodeDirectory = fileTree.MakeDirectoryWriteable(virtualFolder);
Expand All @@ -195,16 +196,16 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha

if (info.IsDirectory)
{
System.IO.Directory.CreateDirectory(folder.path + FileNameDirect);//#TODO create directory recursively if needed

var rlFolder = new PboFsRealFolder(FileNameDirectNoLeadingSlash, folder.path + FileNameDirect, folder);

folder.Children[FileNameDirectNoLeadingSlash.ToLower()] = rlFolder;
fileTree.AddNode(filename.ToLower(), rlFolder);
info.Context = rlFolder;
info.Context = nodeDirectory;
//Nothing else to do as full path is already included in DirectoryPath
}
else
{

//Filename without folder path
var FileNameDirect = filename.Substring(filename.LastIndexOf('\\'));
var FileNameDirectNoLeadingSlash = filename.Substring(filename.LastIndexOf('\\') + 1);

FileStream newStream = null;
try
{
Expand All @@ -219,7 +220,7 @@ public NtStatus CreateFile(string filename, FileAccess access, System.IO.FileSha
var rlFile = new PboFsRealFile(new System.IO.FileInfo(folder.path + FileNameDirect), folder, newStream);

folder.Children[FileNameDirectNoLeadingSlash.ToLower()] = rlFile;
fileTree.AddNode(filename.ToLower(), rlFile);
fileTree.AddNode(rlFile);
info.Context = rlFile;
}

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

if (node is IPboFsFile file && (wantsRead || wantsWrite))
return file.Open(wantsWrite);
return file.Open(wantsWrite, mode);

return DokanResult.Success;
}

public NtStatus DeleteDirectory(string filename, DokanFileInfo info)
{
//This is called after Windows asked the user for confirmation.

if (!(GetNodeFast(filename, info) is PboFsRealFolder folder)) return DokanResult.NotImplemented;
var gnf = GetNodeFast(filename, info);
if (!(gnf is PboFsRealFolder folder)) return DokanResult.NotImplemented;

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


fileTree.AddNode(PrefixedFilename(newname), file);
fileTree.DeleteNode(PrefixedFilename(filename));
fileTree.DeleteNode(file);

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

file.file = new FileInfo(fileTree.writeableDirectory + newname);
file.FileInformation.FileName = targetFilenameDirect;
file.parent = nodeTargetDirectory;

fileTree.AddNode(file);

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

fileTree.AddNode(PrefixedFilename(newname), folder);
fileTree.DeleteNode(PrefixedFilename(filename));

System.IO.Directory.Move(folder.path, fileTree.writeableDirectory + newname);
folder.path = fileTree.writeableDirectory + newname;
folder.FileInformation.FileName = targetFilenameDirect;

void moveNodesRecursive(PboFsFolder folderIn, string basePath)
void doNodesRecursive(PboFsFolder folderIn, bool remove)
{
foreach (var entry in folderIn.Children)
{
var curFullPath = basePath + "\\" + entry.Key;
fileTree.AddNode(newname + curFullPath.Substring(filename.Length), entry.Value);
fileTree.DeleteNode(curFullPath);
if (remove)
{
fileTree.DeleteNode(entry.Value);
if (entry.Value is PboFsRealFile file)
{
file.Close();
}
}

else
{
fileTree.AddNode(entry.Value);
if (entry.Value is PboFsRealFile file)
{
file.file = new FileInfo(file.file.FullName.Replace(filename,newname));
}

}

if (entry.Value is PboFsFolder nextFolder)
moveNodesRecursive(nextFolder, curFullPath);
doNodesRecursive(nextFolder, remove);
}
}

moveNodesRecursive(folder, filename);


fileTree.DeleteNode(folder);
doNodesRecursive(folder, true);

System.IO.Directory.Move(folder.path, fileTree.writeableDirectory + newname);
folder.path = fileTree.writeableDirectory + newname;
folder.FileInformation.FileName = targetFilenameDirect;
folder.parent = nodeTargetDirectory;

fileTree.AddNode(folder);

doNodesRecursive(folder, false);

return DokanResult.Success;
default:
Expand Down
122 changes: 115 additions & 7 deletions DokanPbo.Core/PboFSNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,111 @@ namespace DokanPbo
public abstract class IPboFsNode
{
public FileInformation FileInformation;
public PboFsFolder parent;

public override int GetHashCode()
{

int hashCode = FileInformation.FileName?.ToLower().GetHashCode() ?? "".GetHashCode();
var element = parent;
while (element != null)
{
if (element.FileInformation.FileName != null && element.FileInformation.FileName != "")
hashCode = hashCode * 23 + element.FileInformation.FileName.ToLower().GetHashCode();
element = element.parent;
}

return hashCode;
}

public override bool Equals(object obj)
{

if (obj is PboFsLookupDummy dummy)
return dummy.Equals(this);

if (obj is IPboFsNode node)
{
if (!FileInformation.FileName.Equals(node.FileInformation.FileName, StringComparison.CurrentCultureIgnoreCase)) return false;

var lparent = parent;
var rparent = node.parent;
while (lparent != null && rparent != null)
{
if ((lparent.FileInformation.FileName == null || rparent.FileInformation.FileName == null))
return rparent.FileInformation.FileName == lparent.FileInformation.FileName;

if (!lparent.FileInformation.FileName.Equals(rparent.FileInformation.FileName, StringComparison.CurrentCultureIgnoreCase)) return false;
lparent = lparent.parent;
rparent = rparent.parent;
}

return rparent == lparent; //one of them is null. If the other isn't also null then they didn't match.
}

return false;
}
}

public class PboFsLookupDummy : IPboFsNode
{
private List<string> path = new List<string>();


public PboFsLookupDummy(string inputPath)
{
var splitPath = inputPath.Split('\\');
foreach (var it in splitPath)
path.Add(it.ToLower());

path.RemoveAll((x) => x == "");
if (path.Count == 0) return;

path.Reverse();
}


public override int GetHashCode()
{
if (path.Count == 0) return "".GetHashCode();

bool first = true;
int hashCode = 0;

foreach (var it in path)
{
if (first)
{
hashCode = it.GetHashCode();
first = false;
} else
hashCode = hashCode * 23 + it.GetHashCode();
}

return hashCode;
}

public override bool Equals(object obj)
{
if (obj is IPboFsNode node)
{

if (parent == null && node.parent == null) return true; //Both are root node. Done here because root node doesn't have a path

var rparent = node;
foreach (var it in path)
{
if (rparent == null) return false;
if (!it.Equals(rparent.FileInformation.FileName, StringComparison.CurrentCultureIgnoreCase)) return false;
rparent = rparent.parent;
}

return rparent?.parent == null; //If it is not null. We didn't arrive at root node which we should've
}


return false;
}
}

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

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

public class PboFsFolder : IPboFsFolder
{
public PboFsFolder parent;
public Dictionary<string, IPboFsNode> Children;

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

public PboFsFile(string name, FileEntry file) : base()
public PboFsFile(string name, FileEntry file, PboFsFolder inputParent) : base()
{
File = file;
var fileTimestamp = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime().AddSeconds(file.TimeStamp);
parent = inputParent;
FileInformation = new DokanNet.FileInformation()
{
Attributes = System.IO.FileAttributes.Normal | FileAttributes.ReadOnly | FileAttributes.Temporary | FileAttributes.Archive,
Expand Down Expand Up @@ -108,7 +213,7 @@ public class PboFsDebinarizedFile : PboFsFile
{
public System.IO.Stream debinarizedStream = null;

public PboFsDebinarizedFile(string name, FileEntry file) : base(name, file)
public PboFsDebinarizedFile(string name, FileEntry file, PboFsFolder inputParent) : base(name, file, inputParent)
{
}

Expand Down Expand Up @@ -170,9 +275,9 @@ public string GetRealPath()

public class PboFsRealFile : IPboFsFile, IPboFsRealObject
{
public PboFsFolder parent;
public System.IO.FileInfo file;
private bool? wantsOpenWrite;
private FileMode openMode;
private System.IO.FileStream readStream = null;
private System.IO.FileStream writeStream = null;

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

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

public override NtStatus Open(bool write)
public override NtStatus Open(bool write, FileMode mode)
{
wantsOpenWrite = write;
openMode = mode;
return NtStatus.Success;
}

Expand Down Expand Up @@ -325,6 +431,8 @@ public NtStatus SetEof(long length)

if (!streamFromCache)
stream.Close(); //#TODO cache
file.Refresh();
FileInformation.Length = length;
return DokanResult.Success;
}
catch (FileNotFoundException e)
Expand Down
Loading

0 comments on commit dd79448

Please sign in to comment.