382 lines
12 KiB
Plaintext
382 lines
12 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: FileUtils.sg
|
|
//
|
|
// Note:
|
|
//
|
|
|
|
using System;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using Microsoft.SingSharp;
|
|
using Microsoft.Singularity;
|
|
using Microsoft.Singularity.Directory;
|
|
using Microsoft.Singularity.Channels;
|
|
using Microsoft.Singularity.FileSystem;
|
|
using Microsoft.Singularity.V1.Services;
|
|
|
|
namespace FileSystem.Utils
|
|
{
|
|
public class FileUtils
|
|
{
|
|
public static object lockTarget = new object();
|
|
public static bool recording = false;
|
|
public static TimeSpan bindTime = new TimeSpan(0);
|
|
public static long bindCount = 0;
|
|
|
|
private static TRef<DirectoryServiceContract.Imp:Ready>! m_epNS =
|
|
new TRef<DirectoryServiceContract.Imp:Ready>(DirectoryService.NewClientEndpoint());
|
|
|
|
private static DirectoryServiceContract.Imp:Ready! GetDirectoryServiceContract()
|
|
{
|
|
return m_epNS.Acquire();
|
|
}
|
|
|
|
private static void ReleaseDirectoryServiceContract([Claims] DirectoryServiceContract.Imp:Ready! imp)
|
|
{
|
|
m_epNS.Release(imp);
|
|
}
|
|
|
|
|
|
public static FileContract.Imp:Ready OpenFile(string! filePath)
|
|
{
|
|
DirectoryServiceContract.Imp! rootNS = GetDirectoryServiceContract();
|
|
try {
|
|
return OpenFile(filePath, rootNS);
|
|
}
|
|
finally {
|
|
ReleaseDirectoryServiceContract(rootNS);
|
|
}
|
|
}
|
|
|
|
public static FileContract.Imp:Ready OpenFile(string! filePath, out ErrorCode error)
|
|
{
|
|
DirectoryServiceContract.Imp! rootNS = GetDirectoryServiceContract();
|
|
try {
|
|
return OpenFile(filePath, rootNS, out error);
|
|
}
|
|
finally {
|
|
ReleaseDirectoryServiceContract(rootNS);
|
|
}
|
|
}
|
|
|
|
public static FileContract.Imp:Ready OpenFile(string! filePath, DirectoryServiceContract.Imp! rootNS)
|
|
{
|
|
ErrorCode error;
|
|
return OpenFile(filePath, rootNS, out error);
|
|
}
|
|
|
|
public static FileContract.Imp:Ready OpenFile(string! filePath,
|
|
DirectoryServiceContract.Imp! rootNS,
|
|
out ErrorCode errorOut)
|
|
{
|
|
FileContract.Imp! fileClient;
|
|
FileContract.Exp! fileServer;
|
|
FileContract.NewChannel(out fileClient, out fileServer);
|
|
|
|
bool ok = SdsUtils.Bind(filePath, rootNS, fileServer, out errorOut);
|
|
if (!ok) {
|
|
//Console.WriteLine(" bind failed (error={0}) for {1}",
|
|
// SdsUtils.ErrorCodeToString(errorOut), filePath);
|
|
delete fileClient;
|
|
return null;
|
|
}
|
|
else {
|
|
}
|
|
fileClient.RecvSuccess();
|
|
|
|
return fileClient;
|
|
}
|
|
|
|
public static bool FileExists(DirectoryServiceContract.Imp:Ready! dsRoot,string! filePath)
|
|
{
|
|
ErrorCode error;
|
|
FileAttributesRecord fileAttributes;
|
|
|
|
return GetAttributes(filePath, dsRoot, out fileAttributes, out error);
|
|
}
|
|
|
|
#if !REMOVE
|
|
// REMOVE
|
|
public static int CreateFile(string! filePath)
|
|
{
|
|
ErrorCode errorCode;
|
|
DirectoryServiceContract.Imp! rootNS = DirectoryService.NewClientEndpoint();
|
|
|
|
try {
|
|
if (!CreateFile(filePath, rootNS, out errorCode)) return -1;
|
|
return 0;
|
|
}
|
|
finally {
|
|
delete rootNS;
|
|
}
|
|
}
|
|
|
|
// REMOVE
|
|
public static int CreateFile(string! filePath, out ErrorCode errorCode)
|
|
{
|
|
DirectoryServiceContract.Imp! rootNS = DirectoryService.NewClientEndpoint();
|
|
|
|
try {
|
|
if (!CreateFile(filePath, rootNS, out errorCode)) return -1;
|
|
return 0;
|
|
}
|
|
finally {
|
|
delete rootNS;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
public static int CreateFile(string! filePath, DirectoryServiceContract.Imp! ds)
|
|
{
|
|
ErrorCode err;
|
|
if (!CreateFile(filePath,ds, out err)) return -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
public static bool CreateFile(string! filePath, DirectoryServiceContract.Imp! ds, out ErrorCode errorCode)
|
|
{
|
|
errorCode = ErrorCode.Unknown;
|
|
|
|
string fileName = PathUtils.FileFromPath(filePath);
|
|
|
|
if (fileName == null) {
|
|
// No trailing file part
|
|
return false;
|
|
}
|
|
|
|
DirectoryServiceContract.Imp dirClient = DirectoryUtils.FindDir(filePath, ds);
|
|
|
|
if (dirClient == null) {
|
|
// Couldn't open enclosing directory
|
|
return false;
|
|
}
|
|
|
|
dirClient.SendCreateFile(Bitter.FromString2(fileName));
|
|
|
|
switch receive {
|
|
case dirClient.NakCreateFile(error):
|
|
// Failure
|
|
errorCode = error;
|
|
delete dirClient;
|
|
return false;
|
|
|
|
case dirClient.AckCreateFile():
|
|
errorCode = ErrorCode.NoError;
|
|
// Success
|
|
break;
|
|
|
|
case dirClient.ChannelClosed():
|
|
// Channel closed unexpectedly
|
|
errorCode = ErrorCode.ChannelClosed;
|
|
delete dirClient;
|
|
return false;
|
|
}
|
|
|
|
delete dirClient;
|
|
return true;
|
|
} //createFile
|
|
|
|
// 0 is success
|
|
public static bool GetAttributes(string! filePath,
|
|
DirectoryServiceContract.Imp! ds,
|
|
out FileAttributesRecord fileAttributes,
|
|
out ErrorCode errorOut)
|
|
{
|
|
bool ok = SdsUtils.GetAttributes(filePath, ds, out fileAttributes, out errorOut);
|
|
return ok;
|
|
}
|
|
|
|
// 0 is success
|
|
public static bool GetAttributes(string! filePath,
|
|
out FileAttributesRecord fileAttributes,
|
|
out ErrorCode errorOut)
|
|
{
|
|
// make the complier happy and assign fileAttributes
|
|
fileAttributes = new FileAttributesRecord();
|
|
bool ok = false;
|
|
errorOut = ErrorCode.Unknown;
|
|
DirectoryServiceContract.Imp! rootNS = GetDirectoryServiceContract();
|
|
try {
|
|
ok = GetAttributes(filePath, rootNS, out fileAttributes, out errorOut);
|
|
}
|
|
catch (Exception e) {
|
|
DebugStub.WriteLine("FileUtils.GetAttributes exception: {0}", __arglist(e.Message));
|
|
}
|
|
finally {
|
|
ReleaseDirectoryServiceContract(rootNS);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
#if !REMOVE
|
|
// REMOVE version that does not have ep
|
|
public static int DeleteFile(string! filePath)
|
|
{
|
|
DirectoryServiceContract.Imp! ds = GetDirectoryServiceContract();
|
|
ErrorCode errorOut = ErrorCode.Unknown;
|
|
try {
|
|
DeleteFile(filePath, ds, out errorOut);
|
|
}
|
|
catch (Exception e) {
|
|
DebugStub.WriteLine("FileUtils.DeleteFile exception: {0}", __arglist(e.Message));
|
|
}
|
|
finally {
|
|
ReleaseDirectoryServiceContract(ds);
|
|
}
|
|
return (int) errorOut;
|
|
}
|
|
#endif
|
|
public static int DeleteFile(string! filePath, DirectoryServiceContract.Imp! ds, out ErrorCode errorOut )
|
|
{
|
|
string fileName = PathUtils.FileFromPath(filePath);
|
|
errorOut = ErrorCode.Unknown;
|
|
|
|
if (fileName == null) {
|
|
// No trailing filename
|
|
errorOut = ErrorCode.NotFound;
|
|
return -1;
|
|
}
|
|
|
|
DirectoryServiceContract.Imp dirClient = DirectoryUtils.FindDir(filePath, ds);
|
|
|
|
if (dirClient == null) {
|
|
// Couldn't open enclosing directory
|
|
errorOut = ErrorCode.NotFound;
|
|
return -1;
|
|
}
|
|
|
|
dirClient.SendDeleteFile(Bitter.FromString2(fileName));
|
|
|
|
switch receive {
|
|
case dirClient.NakDeleteFile(error):
|
|
errorOut = error;
|
|
// Failed; no such file?
|
|
delete dirClient;
|
|
return (int) errorOut;
|
|
|
|
case dirClient.AckDeleteFile():
|
|
errorOut = ErrorCode.NoError;
|
|
// Success
|
|
break;
|
|
|
|
case dirClient.ChannelClosed():
|
|
// Channel closed unexpectedly
|
|
errorOut = ErrorCode.ChannelClosed;
|
|
delete dirClient;
|
|
return (int) errorOut;
|
|
}
|
|
|
|
delete dirClient;
|
|
return 0;
|
|
} //DeleteFile
|
|
|
|
public static byte[] ReadEntireFile(
|
|
string! filePath,
|
|
DirectoryServiceContract.Imp! ds)
|
|
{
|
|
FileContract.Imp:Ready fileEP = OpenFile(filePath, ds);
|
|
|
|
if (fileEP == null) {
|
|
delete fileEP;
|
|
return null;
|
|
}
|
|
|
|
ErrorCode err;
|
|
FileAttributesRecord fileAttributes;
|
|
|
|
if (!GetAttributes(filePath, ds, out fileAttributes, out err)) {
|
|
delete fileEP;
|
|
return null;
|
|
}
|
|
|
|
byte[] data = new byte[fileAttributes.FileSize];
|
|
|
|
if (Read(fileEP, 0, (int)fileAttributes.FileSize, 0, data) != fileAttributes.FileSize) {
|
|
delete fileEP;
|
|
return null;
|
|
}
|
|
|
|
delete fileEP;
|
|
return data;
|
|
}
|
|
|
|
public static long Read(
|
|
FileContract.Imp:Ready! fileClient,
|
|
int bufOffset,
|
|
int readSize,
|
|
long fileOffset,
|
|
byte[]! buf)
|
|
{
|
|
long readCount = 0;
|
|
int error;
|
|
byte[]! in ExHeap readBytes = new[ExHeap] byte[readSize];
|
|
fileClient.SendRead(readBytes, 0, fileOffset, readBytes.Length);
|
|
fileClient.RecvAckRead(out readBytes, out readCount, out error);
|
|
|
|
if (error == 0) {
|
|
Bitter.ToByteArray(readBytes, 0, (int)readCount, buf, (int)bufOffset);
|
|
}
|
|
else {
|
|
readCount = 0;
|
|
}
|
|
|
|
delete readBytes;
|
|
return readCount;
|
|
}
|
|
|
|
public static long Write(
|
|
FileContract.Imp:Ready! fileClient,
|
|
int bufOffset,
|
|
int writeSize,
|
|
long fileOffset,
|
|
byte[]! buf)
|
|
{
|
|
long writeCount = 0;
|
|
int error;
|
|
byte[]! in ExHeap writeBytes = new[ExHeap] byte[writeSize];
|
|
|
|
Bitter.FromByteArray(writeBytes, 0, writeSize, buf, bufOffset);
|
|
fileClient.SendWrite(writeBytes, 0, fileOffset, writeSize);
|
|
fileClient.RecvAckWrite(out writeBytes, out writeCount, out error);
|
|
|
|
if (error != 0) {
|
|
writeCount = 0;
|
|
}
|
|
|
|
delete writeBytes;
|
|
return writeCount;
|
|
}
|
|
|
|
public static long Write(
|
|
FileContract.Imp:Ready! fileClient,
|
|
long offset,
|
|
byte[]! data)
|
|
{
|
|
return Write(fileClient, 0, data.Length, offset, data);
|
|
}
|
|
|
|
// we'll do something more intelligent than this later
|
|
public static long Write(
|
|
FileContract.Imp:Ready! fileClient,
|
|
long offset,
|
|
string! line) {
|
|
|
|
return Write(fileClient, offset, Encoding.UTF8.GetBytes(line));
|
|
}
|
|
|
|
public static long WriteLine(
|
|
FileContract.Imp:Ready! fileClient,
|
|
long offset,
|
|
string line) {
|
|
|
|
return Write(fileClient, offset, line+"\r\n");
|
|
}
|
|
}
|
|
}
|