tst: memfs-dotnet: WIP

This commit is contained in:
Bill Zissimopoulos 2017-05-05 14:47:48 -07:00
parent 4278cec465
commit f36cacaf84

View File

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
using System.Security.AccessControl; using System.Security.AccessControl;
using Fsp; using Fsp;
@ -315,7 +316,11 @@ namespace memfs
FileNode.FileSecurity = SecurityDescriptor; FileNode.FileSecurity = SecurityDescriptor;
FileNode.FileInfo.AllocationSize = AllocationSize; FileNode.FileInfo.AllocationSize = AllocationSize;
if (0 != AllocationSize) if (0 != AllocationSize)
FileNode.FileData = new byte[AllocationSize]; {
Result = SetFileSizeInternal(FileNode, AllocationSize, true);
if (0 > Result)
return Result;
}
FileNodeMap.Insert(FileNode); FileNodeMap.Insert(FileNode);
InsertOpenNode(FileNode); InsertOpenNode(FileNode);
@ -461,18 +466,34 @@ namespace memfs
} }
public override Int32 Read( public override Int32 Read(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
IntPtr Buffer, IntPtr Buffer,
UInt64 Offset, UInt64 Offset,
UInt32 Length, UInt32 Length,
out UInt32 BytesTransferred) out UInt32 BytesTransferred)
{ {
BytesTransferred = default(UInt32); FileNode FileNode = (FileNode)FileNode0;
return STATUS_INVALID_DEVICE_REQUEST; UInt64 EndOffset;
if (Offset >= FileNode.FileInfo.FileSize)
{
BytesTransferred = default(UInt32);
return STATUS_END_OF_FILE;
}
EndOffset = Offset + Length;
if (EndOffset > FileNode.FileInfo.FileSize)
EndOffset = FileNode.FileInfo.FileSize;
BytesTransferred = (UInt32)(EndOffset - Offset);
Marshal.Copy(FileNode.FileData, 0, Buffer, (int)BytesTransferred);
return STATUS_SUCCESS;
} }
public override Int32 Write( public override Int32 Write(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
IntPtr Buffer, IntPtr Buffer,
UInt64 Offset, UInt64 Offset,
@ -482,28 +503,73 @@ namespace memfs
out UInt32 BytesTransferred, out UInt32 BytesTransferred,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
BytesTransferred = default(UInt32); FileNode FileNode = (FileNode)FileNode0;
FileInfo = default(FileInfo); UInt64 EndOffset;
return STATUS_INVALID_DEVICE_REQUEST;
if (ConstrainedIo)
{
if (Offset >= FileNode.FileInfo.FileSize)
{
BytesTransferred = default(UInt32);
FileInfo = default(FileInfo);
return STATUS_SUCCESS;
}
EndOffset = Offset + Length;
if (EndOffset > FileNode.FileInfo.FileSize)
EndOffset = FileNode.FileInfo.FileSize;
}
else
{
if (WriteToEndOfFile)
Offset = FileNode.FileInfo.FileSize;
EndOffset = Offset + Length;
if (EndOffset > FileNode.FileInfo.FileSize)
{
Int32 Result = SetFileSizeInternal(FileNode, EndOffset, false);
if (0 > Result)
{
BytesTransferred = default(UInt32);
FileInfo = default(FileInfo);
return Result;
}
}
}
BytesTransferred = (UInt32)(EndOffset - Offset);
Marshal.Copy(Buffer, FileNode.FileData, 0, (int)BytesTransferred);
FileInfo = FileNode.GetFileInfo();
return STATUS_SUCCESS;
} }
public override Int32 Flush( public override Int32 Flush(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
FileInfo = default(FileInfo); FileNode FileNode = (FileNode)FileNode0;
return STATUS_INVALID_DEVICE_REQUEST;
/* nothing to flush, since we do not cache anything */
FileInfo = null != FileNode ? FileNode.GetFileInfo() : default(FileInfo);
return STATUS_SUCCESS;
} }
public override Int32 GetFileInfo( public override Int32 GetFileInfo(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
FileInfo = default(FileInfo); FileNode FileNode = (FileNode)FileNode0;
return STATUS_INVALID_DEVICE_REQUEST;
FileInfo = FileNode.GetFileInfo();
return STATUS_SUCCESS;
} }
public override Int32 SetBasicInfo( public override Int32 SetBasicInfo(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
UInt32 FileAttributes, UInt32 FileAttributes,
UInt64 CreationTime, UInt64 CreationTime,
@ -512,59 +578,184 @@ namespace memfs
UInt64 ChangeTime, UInt64 ChangeTime,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
FileInfo = default(FileInfo); FileNode FileNode = (FileNode)FileNode0;
return STATUS_INVALID_DEVICE_REQUEST;
if (null != FileNode.MainFileNode)
FileNode = FileNode.MainFileNode;
if (unchecked((UInt32)(-1)) != FileAttributes)
FileNode.FileInfo.FileAttributes = FileAttributes;
if (0 != CreationTime)
FileNode.FileInfo.CreationTime = CreationTime;
if (0 != LastAccessTime)
FileNode.FileInfo.LastAccessTime = LastAccessTime;
if (0 != LastWriteTime)
FileNode.FileInfo.LastWriteTime = LastWriteTime;
if (0 != ChangeTime)
FileNode.FileInfo.ChangeTime = ChangeTime;
FileInfo = FileNode.GetFileInfo();
return STATUS_SUCCESS;
} }
public override Int32 SetFileSize( public override Int32 SetFileSize(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
UInt64 NewSize, UInt64 NewSize,
Boolean SetAllocationSize, Boolean SetAllocationSize,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
FileInfo = default(FileInfo); FileNode FileNode = (FileNode)FileNode0;
return STATUS_INVALID_DEVICE_REQUEST; Int32 Result;
Result = SetFileSizeInternal(FileNode, NewSize, SetAllocationSize);
FileInfo = 0 <= Result ? FileNode.GetFileInfo() : default(FileInfo);
return STATUS_SUCCESS;
} }
private Int32 SetFileSizeInternal( private Int32 SetFileSizeInternal(
FileNode FileNode, FileNode FileNode,
UInt64 NewSize, UInt64 NewSize,
Boolean SetAllocationSize) Boolean SetAllocationSize)
{ {
return STATUS_INVALID_DEVICE_REQUEST; if (SetAllocationSize)
{
if (FileNode.FileInfo.AllocationSize != NewSize)
{
if (NewSize > MaxFileSize)
return STATUS_DISK_FULL;
byte[] FileData = null;
if (0 != NewSize)
try
{
FileData = new byte[NewSize];
}
catch
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Array.Copy(FileNode.FileData, FileData,
(int)Math.Min(FileNode.FileInfo.AllocationSize, NewSize));
FileNode.FileData = FileData;
FileNode.FileInfo.AllocationSize = NewSize;
if (FileNode.FileInfo.FileSize > NewSize)
FileNode.FileInfo.FileSize = NewSize;
}
}
else
{
if (FileNode.FileInfo.FileSize != NewSize)
{
if (FileNode.FileInfo.AllocationSize < NewSize)
{
UInt64 AllocationUnit = MEMFS_SECTOR_SIZE * MEMFS_SECTORS_PER_ALLOCATION_UNIT;
UInt64 AllocationSize = (NewSize + AllocationUnit - 1) / AllocationUnit * AllocationUnit;
Int32 Result = SetFileSizeInternal(FileNode, AllocationSize, true);
if (0 > Result)
return Result;
}
if (FileNode.FileInfo.FileSize < NewSize)
Array.Clear(FileNode.FileData,
(int)FileNode.FileInfo.FileSize, (int)(NewSize - FileNode.FileInfo.FileSize));
FileNode.FileInfo.FileSize = NewSize;
}
}
return STATUS_SUCCESS;
} }
public override Int32 CanDelete( public override Int32 CanDelete(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
String FileName) String FileName)
{ {
return STATUS_INVALID_DEVICE_REQUEST; FileNode FileNode = (FileNode)FileNode0;
if (FileNodeMap.HasChild(FileNode))
return STATUS_DIRECTORY_NOT_EMPTY;
return STATUS_SUCCESS;
} }
public override Int32 Rename( public override Int32 Rename(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
String FileName, String FileName,
String NewFileName, String NewFileName,
Boolean ReplaceIfExists) Boolean ReplaceIfExists)
{ {
return STATUS_INVALID_DEVICE_REQUEST; FileNode FileNode = (FileNode)FileNode0;
FileNode NewFileNode;
NewFileNode = FileNodeMap.Get(NewFileName);
if (null != NewFileNode && FileNode != NewFileNode)
{
if (!ReplaceIfExists)
return STATUS_OBJECT_NAME_COLLISION;
if (0 != (NewFileNode.FileInfo.FileAttributes & (UInt32)FileAttributes.Directory))
return STATUS_ACCESS_DENIED;
}
if (null != NewFileNode)
FileNodeMap.Remove(NewFileNode);
List<String> DescendantFileNames = new List<String>(FileNodeMap.GetDescendantFileNames(FileNode));
foreach (String DescendantFileName in DescendantFileNames)
{
FileNode DescendantFileNode = FileNodeMap.Get(DescendantFileName);
if (null == DescendantFileNode)
continue; /* should not happen */
FileNodeMap.Remove(DescendantFileNode);
DescendantFileNode.FileName =
NewFileName + DescendantFileNode.FileName.Substring(FileName.Length);
FileNodeMap.Insert(DescendantFileNode);
}
return STATUS_SUCCESS;
} }
public override Int32 GetSecurity( public override Int32 GetSecurity(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
ref Byte[] SecurityDescriptor) ref Byte[] SecurityDescriptor)
{ {
return STATUS_INVALID_DEVICE_REQUEST; FileNode FileNode = (FileNode)FileNode0;
if (null != FileNode.MainFileNode)
FileNode = FileNode.MainFileNode;
SecurityDescriptor = FileNode.FileSecurity;
return STATUS_SUCCESS;
} }
public override Int32 SetSecurity( public override Int32 SetSecurity(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
AccessControlSections Sections, AccessControlSections Sections,
Byte[] SecurityDescriptor) Byte[] SecurityDescriptor)
{ {
return STATUS_INVALID_DEVICE_REQUEST; FileNode FileNode = (FileNode)FileNode0;
if (null != FileNode.MainFileNode)
FileNode = FileNode.MainFileNode;
ObjectSecurity ObjectSecurity =
0 != (FileNode.FileInfo.FileAttributes & (UInt32)FileAttributes.Directory) ?
(ObjectSecurity)new DirectorySecurity() : (ObjectSecurity)new FileSecurity();
ObjectSecurity.SetSecurityDescriptorBinaryForm(FileNode.FileSecurity);
ObjectSecurity.SetSecurityDescriptorBinaryForm(SecurityDescriptor, Sections);
FileNode.FileSecurity = ObjectSecurity.GetSecurityDescriptorBinaryForm();
return STATUS_SUCCESS;
} }
public override Boolean ReadDirectoryEntry( public override Boolean ReadDirectoryEntry(
Object FileNode, Object FileNode0,
Object FileDesc, Object FileDesc,
String Pattern, String Pattern,
String Marker, String Marker,
@ -572,6 +763,51 @@ namespace memfs
out String FileName, out String FileName,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
FileNode FileNode = (FileNode)FileNode0;
IEnumerator<String> Enumerator = (IEnumerator<String>)Context;
if (null == Enumerator)
{
List<String> ChildrenFileNames = new List<String>();
if ("\\" != FileNode.FileName)
{
/* if this is not the root directory add the dot entries */
ChildrenFileNames.Add(".");
ChildrenFileNames.Add("..");
}
ChildrenFileNames.AddRange(FileNodeMap.GetChildrenFileNames(FileNode));
Context = Enumerator = ChildrenFileNames.GetEnumerator();
}
while (Enumerator.MoveNext())
{
FileName = Enumerator.Current;
if ("." == FileName)
{
FileInfo = FileNode.GetFileInfo();
return true;
}
else if (".." == FileName)
{
Int32 Result;
FileNode ParentNode = FileNodeMap.GetParent(FileNode.FileName, out Result);
if (null != ParentNode)
{
FileInfo = ParentNode.GetFileInfo();
return true;
}
}
else
{
FileNode ChildFileNode = FileNodeMap.Get(FileName);
if (null != ChildFileNode)
{
FileInfo = ChildFileNode.GetFileInfo();
return true;
}
}
}
FileName = default(String); FileName = default(String);
FileInfo = default(FileInfo); FileInfo = default(FileInfo);
return false; return false;
@ -1246,15 +1482,15 @@ namespace memfs
IntPtr Buffer, IntPtr Buffer,
UInt64 Offset, UInt64 Offset,
UInt32 Length, UInt32 Length,
out UInt32 PBytesTransferred) out UInt32 BytesTransferred)
{ {
FileDesc FileDesc = (FileDesc)FileDesc0; FileDesc FileDesc = (FileDesc)FileDesc0;
if (Offset >= (UInt64)FileDesc.Stream.Length) if (Offset >= (UInt64)FileDesc.Stream.Length)
ThrowIoExceptionWithNtStatus(STATUS_END_OF_FILE); ThrowIoExceptionWithNtStatus(STATUS_END_OF_FILE);
Byte[] Bytes = new byte[Length]; Byte[] Bytes = new byte[Length];
FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin); FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin);
PBytesTransferred = (UInt32)FileDesc.Stream.Read(Bytes, 0, Bytes.Length); BytesTransferred = (UInt32)FileDesc.Stream.Read(Bytes, 0, Bytes.Length);
Marshal.Copy(Bytes, 0, Buffer, Bytes.Length); Marshal.Copy(Bytes, 0, Buffer, BytesTransferred);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
public override Int32 Write( public override Int32 Write(
@ -1265,7 +1501,7 @@ namespace memfs
UInt32 Length, UInt32 Length,
Boolean WriteToEndOfFile, Boolean WriteToEndOfFile,
Boolean ConstrainedIo, Boolean ConstrainedIo,
out UInt32 PBytesTransferred, out UInt32 BytesTransferred,
out FileInfo FileInfo) out FileInfo FileInfo)
{ {
FileDesc FileDesc = (FileDesc)FileDesc0; FileDesc FileDesc = (FileDesc)FileDesc0;
@ -1273,7 +1509,7 @@ namespace memfs
{ {
if (Offset >= (UInt64)FileDesc.Stream.Length) if (Offset >= (UInt64)FileDesc.Stream.Length)
{ {
PBytesTransferred = default(UInt32); BytesTransferred = default(UInt32);
FileInfo = default(FileInfo); FileInfo = default(FileInfo);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -1285,7 +1521,7 @@ namespace memfs
if (!WriteToEndOfFile) if (!WriteToEndOfFile)
FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin); FileDesc.Stream.Seek((Int64)Offset, SeekOrigin.Begin);
FileDesc.Stream.Write(Bytes, 0, Bytes.Length); FileDesc.Stream.Write(Bytes, 0, Bytes.Length);
PBytesTransferred = (UInt32)Bytes.Length; BytesTransferred = (UInt32)Bytes.Length;
return FileDesc.GetFileInfo(out FileInfo); return FileDesc.GetFileInfo(out FileInfo);
} }
public override Int32 Flush( public override Int32 Flush(