/// <summary> /// Initializes a new instance of the virtual file system. /// </summary> public static void Setup() { rootDirectory = new DirectoryNode(null); rootNode = DirectoryEntry.AllocateRoot(rootDirectory); // FIXME: Add an entry of the virtual file system to /system/filesystems }
/// <summary> /// Performs a standard path lookup. /// </summary> /// <param name="rootDirectory">The root directory.</param> /// <param name="path">The path to resolve.</param> /// <returns>The directory entry of the resolved path.</returns> /// <exception cref="System.Security.SecurityException">The caller does not have access to the path or a component. For example the caller does not have the right to traverse the path.</exception> /// <exception cref="System.IO.PathTooLongException">The path is too long to traverse. This can be the result of circular symbolic links in the path.</exception> /// <exception cref="System.IO.FileNotFoundException">The file or folder path not found.</exception> /// <exception cref="System.IO.DirectoryNotFoundException">A path component was not found.</exception> /// <remarks> /// This call my result in other exceptions not specified in the above list. Other exceptions can be thrown by IVfsNode implementations, which are visited during the traversal /// process. For example a network file system node may throw an exception, if the server is unreachable. /// </remarks> public static DirectoryEntry Resolve (DirectoryEntry rootDirectory, ref string path) { // FIXME: Remove the root argument. The filesystem root should be unique for a process as part of a security model similar to jails, e.g. give apps from // untrusted sources their private filesystem regions. // FIXME: Get the root from the thread execution block DirectoryEntry current = rootDirectory; PathResolver resolver = new PathResolver (rootDirectory, current); return resolver.Resolve (ref path, PathResolutionFlags.None); }
public override void Delete (IVfsNode child, DirectoryEntry dentry) { FAT fs = this.FileSystem as FAT; uint childBlock = (child as VfsDirectory).directoryCluster; FAT.DirectoryEntryLocation location = fs.FindEntry (new FAT.FatMatchClusterComparer (childBlock), this.directoryCluster); if (!location.Valid) throw new System.ArgumentException (); //throw new IOException ("Unable to delete directory because it is not empty"); fs.Delete (childBlock, directoryCluster, location.DirectoryIndex); }
private PathResolver (DirectoryEntry rootDirectory, DirectoryEntry currentDirectory) { this.rootDirectory = rootDirectory; this.currentDirectory = currentDirectory; depth = PathResolver.MAX_SYMLINKS_TO_FOLLOW; }
/// <summary> /// Performs an iterative lookup of the given path starting from the root and obeying to the specified flags. /// </summary> /// <param name="path">The path to lookup. This can be a relative or absolute path. Path.DirectorySeparatorChar or Path.AltDirectorySeparatorChar are valid delimiters.</param> /// <param name="root">The root directory to start lookup from.</param> /// <param name="flags">The lookup flags, which control the lookup process.</param> /// <returns>The directory entry of the resolved path.</returns> /// <exception cref="System.Security.SecurityException">The caller does not have access to the path or a component. For example the caller does not have the right to traverse the path.</exception> /// <exception cref="System.IO.PathTooLongException">The path is too long to traverse. This can be the result of circular symbolic links in the path.</exception> /// <exception cref="System.IO.FileNotFoundException">The path or a component was not found. This exception can be prevented by specifying PathResolutionFlags.DoNotThrowNotFoundException.</exception> /// <exception cref="System.IO.DirectoryNotFoundException">A path component was not found. This exception can be prevented by specifying PathResolutionFlags.DoNotThrowNotFoundException.</exception> /// <remarks> /// This call may result in other exceptions not specified in the above list. Other exceptions can be thrown by IVfsNode implementations, which are visited during the traversal /// process. For example a network file system node may throw an exception, if the server is unreachable. /// </remarks> private DirectoryEntry Resolve (ref string path, PathResolutionFlags flags) { // DirectoryNode entry found by stepping through the path DirectoryEntry entry = null; // Split the given path to its components PathSplitter dirs = new PathSplitter (path); // Determine the number of path components int max = dirs.Length; // Current path component string item; // Loop index int index = 0; // Perform an access check on the root directory AccessCheck.Perform (currentDirectory, AccessMode.Traverse, AccessCheckFlags.None); // Do not resolve the last name, if we want the parent directory. if (PathResolutionFlags.RetrieveParent == (flags & PathResolutionFlags.RetrieveParent)) { path = dirs[dirs.Length - 1]; max--; } // Check if this is an absolute path? if (dirs[0].Length == 0) { // Yes, replace the current directory currentDirectory = rootDirectory; index++; } // Iterate over the remaining path components while ((currentDirectory != null) && (index < max)) { item = dirs[index]; entry = null; if (currentDirectory.Node.NodeType == VfsNodeType.SymbolicLink) { SymbolicLinkNode link = (SymbolicLinkNode)currentDirectory.Node; if (0 != depth--) { // The symlink stores a relative path, use it for a current relative lookup. string target = link.Target; // Build a new flags set for symlink lookups, as we do not want all of them. PathResolutionFlags symflags = (flags & PathResolutionFlags.SymLinkLookupSafe); entry = Resolve (ref target, symflags); } else { if (PathResolutionFlags.DoNotThrowNotFoundException != (PathResolutionFlags.DoNotThrowNotFoundException & flags)) { // FIXME: Provide a MUI resource string for the exception #if VFS_EXCEPTIONS throw new PathTooLongException(); #endif // #if !VFS_EXCEPTIONS } } } else { // Pass the lookup to the DirectoryEntry (and ultimately to the inode itself.) entry = currentDirectory.Lookup (item); // If lookup in the directory entry failed, ask the real INode to perform the lookup. if (entry == null) { IVfsNode node = currentDirectory.Node.Lookup (item); if (node != null) { entry = DirectoryEntry.Allocate (currentDirectory, item, node); } } } // Increment the path component index index++; // Check if we have a new path component? if ((entry == null) && (PathResolutionFlags.DoNotThrowNotFoundException != (PathResolutionFlags.DoNotThrowNotFoundException & flags))) { // FIXME: Move exception messages to MUI resources #if VFS_EXCEPTIONS if (index == max) throw new FileNotFoundException(@"Failed to resolve the path.", path); else throw new DirectoryNotFoundException(@"Failed to resolve the path."); #endif // #if VFS_EXCEPTIONS } // Set the current resolution directory currentDirectory = entry; // Check if the caller has traverse access to the directory AccessCheck.Perform (currentDirectory, AccessMode.Traverse, AccessCheckFlags.None); } return currentDirectory; }
/// <summary> /// Performs a path lookup obeying to the passed flags. /// </summary> /// <param name="rootDirectory">The root directory.</param> /// <param name="path">The path to resolve.</param> /// <param name="flags">Controls aspects of the path lookup process.</param> /// <returns>The directory entry of the resolved path.</returns> /// <exception cref="System.Security.SecurityException">The caller does not have access to the path or a component. For example the caller does not have the right to traverse the path.</exception> /// <exception cref="System.IO.PathTooLongException">The path is too long to traverse. This can be the result of circular symbolic links in the path.</exception> /// <exception cref="System.IO.FileNotFoundException">The file or folder path was not found. This exception can be prevented by specifying PathResolutionFlags.DoNotThrowNotFoundException.</exception> /// <exception cref="System.IO.DirectoryNotFoundException">A path component was not found. This exception can be prevented by specifying PathResolutionFlags.DoNotThrowNotFoundException.</exception> /// <remarks> /// This call my result in other exceptions not specified in the above list. Other exceptions can be thrown by IVfsNode implementations, which are visited during the traversal /// process. For example a network file system node may throw an exception, if the server is unreachable. /// </remarks> public static DirectoryEntry Resolve (DirectoryEntry rootDirectory, ref string path, PathResolutionFlags flags) { // FIXME: Get the root from the thread execution block DirectoryEntry current = rootDirectory; PathResolver resolver = new PathResolver (rootDirectory, current); return resolver.Resolve (ref path, flags); }
public override void Delete (IVfsNode child, DirectoryEntry dentry) { throw new System.ArgumentException (); // Delete() method doesn't make sense here }
/// <summary> /// Allocates a new DirectoryEntry object for the given settings. /// </summary> /// <param name="parent">The parent directory entry.</param> /// <param name="name">The name of the entry to create.</param> /// <param name="node">The vfs node referenced by the directory entry.</param> /// <returns>The allocated directory entry.</returns> /// <exception cref="System.ArgumentNullException">If any one of the parameters is null.</exception> /// <exception cref="System.ArgumentException">If the name is zero-length.</exception> /// <remarks> /// This method is used to control the DirectoryEntry allocation and maintain a cache of them. Also used to /// prevent infinite name allocations. /// </remarks> public static DirectoryEntry Allocate (DirectoryEntry parent, string name, IVfsNode node) { //#if VFS_NO_EXCEPTIONS if (parent == null) throw new ArgumentNullException (@"parent"); if (name == null) throw new ArgumentNullException (@"name"); if (node == null) throw new ArgumentNullException (@"node"); if (name.Length == 0) throw new ArgumentException (@"Invalid directory entry name."); // , @"name" // FIXME: Add precondition check for invalid characters // FIXME: Localize exception messages //#endif // #if VFS_NO_EXCEPTIONS DirectoryEntry directory = new DirectoryEntry (); directory.Setup (parent, name, node); return directory; }
/// <summary> /// Allocates a vfs root directory entry. /// </summary> /// <param name="node">The vfs node, which corresponds to the root directory.</param> /// <returns>The created directory entry.</returns> /// <exception cref="System.ArgumentNullException">The specified node is invalid.</exception> /// <remarks> /// This method creates a directory entry, which has some special properties. The first one is, that /// its parent is itself. This provides for the ability to cd .. on the root to stay on the root. /// <para/> /// The next ability is to create specialized root directories to isolate processes from the remainder /// of the filesystem. Setting a root directory created using this method effectively limits the process /// to access inside of the newly created namespace. /// </remarks> public static DirectoryEntry AllocateRoot (IVfsNode node) { #if VFS_NO_EXCEPTIONS if (node == null) throw new ArgumentNullException(@"node"); #endif // #if VFS_NO_EXCEPTIONS DirectoryEntry result = new DirectoryEntry (); result.Setup (result, String.Empty, node); return result; }
private void InsertChild (DirectoryEntry child) { /* DirectoryEntry entry = null; int idx = 0, rmin = 0, rmax = _children.Count - 1; // Iterative binary lookup into the _children list while (rmin <= rmax) { idx = (rmax + rmin) / 2; entry = _children[idx]; if (child.Name.Equals(entry.Name)) { #if VFS_NO_EXCEPTIONS throw new InvalidOperationException("Duplicate name."); #endif // #if VFS_NO_EXCEPTIONS } if (0 < entry.Name.CompareTo(child.Name)) { rmax = idx - 1; } else { rmin = idx + 1; } } _children.Insert(rmin, child); */ // FIXME: Thread safety child.next = this.child; this.child = child; }
private void RemoveChild (DirectoryEntry child) { // FIXME: Thread safety if (Object.ReferenceEquals (this.child, child)) { this.child = child.next; } else { DirectoryEntry e = this.child; while (!Object.ReferenceEquals (e.next, child)) e = e.next; e.next = child.next; } child.next = null; // _children.Remove(child); }
/// <summary> /// Releases the DirectoryEntry from the parent DirectoryEntry. This is *not* a delete operation. /// </summary> /// <remarks> /// This function is used to remove a DirectoryEntry from the cache. Some (networked) file systems may want to use /// this function to remove "known" directories from the lookup cache when they loose server connection. /// </remarks> public void Release () { // FIXME: Remove the entry from the parent and release it to the // entry cache in the vfs service. if (!Object.ReferenceEquals (this, Parent)) parent.RemoveChild (this); inode = null; name = null; parent = null; }
private void Setup (DirectoryEntry parent, string name, IVfsNode node) { if (!Object.ReferenceEquals (this, parent)) parent.InsertChild (this); this.parent = parent; this.name = name; inode = node; }
public abstract void Delete(IVfsNode child, DirectoryEntry entry);
public override void Delete (IVfsNode child, DirectoryEntry dentry) { // FIXME: throw new NotImplementedException(); }
public override void Delete(IVfsNode child, DirectoryEntry dentry) { // FIXME: Delete the symbolic link from the filesystem, after all names have been dropped. throw new NotSupportedException(); }
/// <summary> /// This method performs an access check on the given dentry. /// </summary> /// <param name="dentry">The directory entry to perform the access check on.</param> /// <param name="mode">The access mode to check.</param> /// <param name="flags">Flags, which control the operation.</param> /// <returns>True if the caller has the requested permissions on the given directory entry.</returns> /// <exception cref="System.Security.SecurityException">This exception is thrown for failed access checks unless the caller has specified AccessCheckFlags.NoThrow.</exception> /// <remarks> /// This function only checks the permissions on the dentry itself. It does not traverse the directory tree towards the root /// to check the entire tree. Tree checking is automatically performed by Lookup and related functions. /// </remarks> public static bool Perform(DirectoryEntry dentry, AccessMode mode, AccessCheckFlags flags) { // FIXME: Implement the access checking return true; }