//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: SymLinkNode.sg // // Note: // using System; using System.Text; using System.Collections; using System.Threading; using Microsoft.SingSharp; using Microsoft.Singularity; using Microsoft.Singularity.Channels; using Microsoft.Singularity.Directory; using Microsoft.Singularity.Security; using Microsoft.Singularity.Security.SDS; #if !SINGULARITY_PROCESS namespace Microsoft.Singularity.Directory #else using Microsoft.Singularity; using Microsoft.Singularity.V1.Services; namespace Microsoft.Application.DSP #endif { // There are no access checks on symbolic links. // In order to read a link, traverse access to the parent is sufficient. // Although one might think that read access to the parent would be more // appropriate here, the nature of the DirectoryService protocol allows anyone // traversing a link to find the link value, hence there is no benefit to // making "reading" of a link more strict. public class SymLinkNode : Node { private string symbolicLink; public SymLinkNode(string value, string! name, Node! parent) { symbolicLink = value; base(NodeType.SymLink, name, parent); } /// /// null on success, the service argument if it failed. /// public override ServiceContract.Exp Bind(StringBuilder! p, string! fullPath, Principal pr, int curpos, out int position, out bool success, out bool linkFound, out ErrorCode error, out bool reparse, out string link, out string linkPrefix, [Claims] ServiceContract.Exp! service) { Kernel.Waypoint(3500); reparse = true; success = true; linkFound = true; position = curpos; error = ErrorCode.NoError; string rest; StringBuilder x; StringBuilder y; if (! (p.Length == 0)) { rest = SbUtils.PathString(p); assert rest != null; link = symbolicLink + rest; int prefixIndex = fullPath.IndexOf(rest); if (-1 == prefixIndex) { DebugStub.WriteLine("Error processing a link"); DebugStub.Break(); linkPrefix = null; } else { x = new StringBuilder(fullPath.Substring(0,prefixIndex)); y = x; y = SbUtils.StripLast(y); DebugStub.WriteLine(" symlink node: full={0}, partial={1}, stripped={2}", __arglist(fullPath, x.ToString(), y.ToString())); linkPrefix = y.ToString(); } } else { link = symbolicLink; #if old int pos = SbUtils.LastIndexOf(sb,'/',0); if ( pos == -1 ) pos = 0; linkPrefix = fullPath.Substring(0,pos); DebugStub.WriteLine(" symlink node: full={0}, stripped={1}", __arglist(fullPath, linkPrefix)); #else x = new StringBuilder(fullPath); y = SbUtils.StripLast(x); DebugStub.WriteLine(" symlink node: full={0}, stripped={1}", __arglist(fullPath, y.ToString())); linkPrefix = y.ToString(); #endif } Kernel.Waypoint(3501); return service; } /// /// null on success, the sp argument if it failed. /// public override ServiceProviderContract.Imp Register(StringBuilder! p, Principal pr, [Claims]ServiceProviderContract.Imp! sp, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { // cannot register over an existing name reparse = false; linkFound = false; link = null; error = ErrorCode.AlreadyExists; position = curpos; return sp; } /// /// The endpoint on success, null, if it fails. /// public override ServiceProviderContract.Imp:Start Deregister(StringBuilder! path, Principal pr, DirectoryServiceContract.Exp! ep, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { error = ErrorCode.NotSupported; link = null; linkFound = false; reparse = false; position = curpos; if (!(path.Length == 0) ) { return null; } // cannot be removed return null; } /// /// if true returns length and node type, otherwise error /// public override bool GetAttributes(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link, out long length, out NodeType nodeType ) { Kernel.Waypoint(3700); reparse = true; linkFound = true; length = 0; position = curpos; nodeType = NodeType.SymLink; error = ErrorCode.NoError; // this is a traverse operation. There is more left on the path if (! (p.Length == 0)) { link = symbolicLink + SbUtils.PathString(p); return false; } // stop here reparse = false; link = symbolicLink; Kernel.Waypoint(3701); return true; } /// /// true on success, false, if it fails. /// public override NotifyContract.Imp Notify(StringBuilder! pathSpec, Principal pr, string! pattern, bool sendExisting, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link, [Claims] NotifyContract.Imp! notifyImp) { // this method should never be called error = ErrorCode.NotSupported; reparse = false; link = symbolicLink; linkFound = true; position = curpos; return notifyImp; } public override FileContract.Imp CreateAndBindFile(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { linkFound = false; error = ErrorCode.NotImplemented; reparse = false; link = null; position = curpos; return null; } public override bool CreateDirectory(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { position = curpos; //DebugStub.Break(); reparse = true; linkFound = true; link = null; error = ErrorCode.NoError; if (! (p.Length == 0) ) link = symbolicLink + SbUtils.PathString(p); else link = symbolicLink ; return false; } public override bool CreateFile(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { linkFound = false; error = ErrorCode.NotImplemented; reparse = false; link = null; position = curpos; return false; } public override bool CreateLink(StringBuilder! p, Principal pr, string! value, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { reparse = true; linkFound = true; error = ErrorCode.NoError; position = curpos; if (! (p.Length == 0) ) link = symbolicLink + SbUtils.PathString(p); else link = symbolicLink ; return false; } public override bool DeleteDirectory(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { reparse = true; linkFound = true; error = ErrorCode.NoError; position = curpos; if (! (p.Length == 0) ) { link = symbolicLink + SbUtils.PathString(p); return false; } link = symbolicLink ; error = ErrorCode.NotDirectory; reparse = false; return false; } public override bool DeleteFile(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { reparse = true; linkFound = true; error = ErrorCode.NoError; position = curpos; if (! (p.Length == 0) ) link = symbolicLink + SbUtils.PathString(p); else link = symbolicLink ; return false; } public override bool DeleteLink(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { reparse = true; linkFound = true; error = ErrorCode.NoError; position = curpos; if (! (p.Length == 0) ) link = symbolicLink + SbUtils.PathString(p); else link = symbolicLink ; return false; } public override bool GetLinkValue(StringBuilder! p, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { reparse = true; linkFound = true; error = ErrorCode.NoError; position = curpos; // this is a traverse operation if (! (p.Length == 0) ) { link = symbolicLink + SbUtils.PathString(p); return false; } link = symbolicLink; return true; } public override bool QueryACL(StringBuilder! p, bool effective, Principal pr, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link, out Acl acl ) { reparse = true; linkFound = true; error = ErrorCode.NoError; reparse = true; acl = new Acl(); position = curpos; if (! (p.Length == 0)) link = symbolicLink + SbUtils.PathString(p); else link = symbolicLink; return false; } public override bool StoreACL(StringBuilder! p, Principal pr, Acl acl, int curpos, out int position, out bool linkFound, out ErrorCode error, out bool reparse, out string link ) { reparse = true; linkFound = true; error = ErrorCode.NoError; position = curpos; if (! (p.Length == 0)) link = symbolicLink + SbUtils.PathString(p); else link = symbolicLink; return false; } } }