//////////////////////////////////////////////////////////////////////////////// // // 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! m_epNS = new TRef(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"); } } }