220 lines
7.5 KiB
Plaintext
220 lines
7.5 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: PathOpen.sg
|
|
//
|
|
// Note:
|
|
//
|
|
// These methods exist because the core Directory class operations for
|
|
// opening, reading, deleting, files and directories only work for files
|
|
// and directories contained with the directory instance. These methods
|
|
// provide a means to recurse down to right spot to operate at.
|
|
//
|
|
|
|
using Microsoft.Singularity.Channels;
|
|
using Microsoft.Singularity.Directory;
|
|
using Microsoft.SingSharp;
|
|
|
|
using System;
|
|
|
|
namespace Microsoft.Singularity.Services.Fat.Fs
|
|
{
|
|
internal class PathOpen
|
|
{
|
|
internal static ErrorCode
|
|
GetTargetAndDirectory(Directory! root,
|
|
[Claims] char[]! in ExHeap targetPath,
|
|
out char[] in ExHeap theTarget,
|
|
out Directory theDirectory)
|
|
{
|
|
char [] in ExHeap dirPath = null;
|
|
theTarget = null;
|
|
theDirectory = null;
|
|
|
|
targetPath = PathUtils.CleanSeparators(targetPath);
|
|
try {
|
|
PathUtils.SplitPathBottomUp(targetPath,
|
|
out dirPath,
|
|
out theTarget);
|
|
}
|
|
catch (OutOfMemoryException) {
|
|
delete dirPath;
|
|
delete theTarget;
|
|
theTarget = null;
|
|
return ErrorCode.InsufficientResources;
|
|
}
|
|
|
|
if (theTarget == null) {
|
|
delete dirPath;
|
|
return ErrorCode.BadArguments;
|
|
}
|
|
else if (dirPath == null) {
|
|
theDirectory = root.OpenDirectory();
|
|
return ErrorCode.NoError;
|
|
}
|
|
else {
|
|
ErrorCode error = GetDirectory(root, dirPath,
|
|
out theDirectory);
|
|
if (error != ErrorCode.NoError) {
|
|
delete theTarget;
|
|
theTarget = null;
|
|
}
|
|
return error;
|
|
}
|
|
}
|
|
|
|
internal static ErrorCode
|
|
GetFsObject(Directory! root,
|
|
[Claims] char[]! in ExHeap path,
|
|
out FsObject fsObject)
|
|
{
|
|
fsObject = null;
|
|
|
|
path = PathUtils.CleanSeparators(path);
|
|
path = PathUtils.Trim(path);
|
|
|
|
if (path.Length == 0) {
|
|
delete path;
|
|
return ErrorCode.BadArguments;
|
|
}
|
|
|
|
char[] in ExHeap objName = null;
|
|
char[] in ExHeap dirPath = null;
|
|
try {
|
|
PathUtils.SplitPathBottomUp(path, out dirPath, out objName);
|
|
}
|
|
catch (OutOfMemoryException) {
|
|
delete dirPath;
|
|
delete objName;
|
|
return ErrorCode.InsufficientResources;
|
|
}
|
|
|
|
assert !(dirPath == null && objName == null);
|
|
try {
|
|
if (objName == null) {
|
|
// Trying to open root directory.
|
|
assert dirPath != null;
|
|
Directory d;
|
|
ErrorCode error = GetDirectory(root, dirPath, out d);
|
|
fsObject = d;
|
|
return error;
|
|
}
|
|
else if (dirPath == null) {
|
|
// Trying to open object within root directory.
|
|
assert objName != null;
|
|
return root.OpenFsObject(objName, out fsObject);
|
|
}
|
|
else {
|
|
// Trying to open an object below root directory.
|
|
Directory parent;
|
|
ErrorCode error = GetDirectory(root, dirPath, out parent);
|
|
assert error == ErrorCode.NoError || parent == null;
|
|
if (error == ErrorCode.NoError) {
|
|
assert parent != null;
|
|
error = parent.OpenFsObject(objName, out fsObject);
|
|
parent.Close();
|
|
}
|
|
return error;
|
|
}
|
|
}
|
|
finally {
|
|
delete objName;
|
|
}
|
|
}
|
|
|
|
internal static ErrorCode
|
|
GetDirectory(Directory! root,
|
|
[Claims] char []! in ExHeap dirPath,
|
|
out Directory theDirectory)
|
|
{
|
|
char[] in ExHeap top = null;
|
|
char[] in ExHeap remainder = null;
|
|
|
|
theDirectory = null;
|
|
|
|
remainder = PathUtils.CleanSeparators(dirPath);
|
|
remainder = PathUtils.Trim(remainder);
|
|
|
|
if (remainder.Length == 0) {
|
|
delete remainder;
|
|
remainder = null;
|
|
return ErrorCode.BadArguments;
|
|
}
|
|
|
|
ErrorCode error = ErrorCode.NoError;
|
|
int pass = 0;
|
|
|
|
theDirectory = root.OpenDirectory();
|
|
|
|
while (remainder != null) {
|
|
try {
|
|
PathUtils.SplitPathTopDown(remainder,
|
|
out top,
|
|
out remainder);
|
|
}
|
|
catch (OutOfMemoryException) {
|
|
delete top;
|
|
top = null;
|
|
delete remainder;
|
|
remainder = null;
|
|
theDirectory.Close();
|
|
theDirectory = null;
|
|
error = ErrorCode.InsufficientResources;
|
|
break;
|
|
}
|
|
|
|
assert top != null;
|
|
|
|
if (pass++ == 0 && top.Length == 1 &&
|
|
top[0] == PathUtils.Separator) {
|
|
// No action needed. theDirectory is already local root.
|
|
}
|
|
else {
|
|
Directory next;
|
|
assert top.Length >= 1 && top[0] != PathUtils.Separator;
|
|
|
|
assert theDirectory != null;
|
|
error = theDirectory.OpenDirectory(top, out next);
|
|
assert (next == null) != (error == ErrorCode.NoError);
|
|
|
|
if (error != ErrorCode.NoError) {
|
|
delete remainder;
|
|
remainder = null;
|
|
}
|
|
theDirectory.Close();
|
|
theDirectory = next;
|
|
}
|
|
delete top;
|
|
top = null;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
internal static ErrorCode
|
|
GetFile(Directory! root,
|
|
[Claims] char[]! in ExHeap path,
|
|
out File theFile)
|
|
{
|
|
theFile = null;
|
|
FsObject tmp = null;
|
|
|
|
ErrorCode error = GetFsObject(root, path, out tmp);
|
|
if (error == ErrorCode.NoError) {
|
|
assert tmp != null;
|
|
theFile = tmp as File;
|
|
if (theFile == null) {
|
|
((Directory)tmp).Close();
|
|
return ErrorCode.NotFile;
|
|
}
|
|
}
|
|
else {
|
|
assert tmp == null;
|
|
}
|
|
return error;
|
|
}
|
|
}
|
|
}
|