Beispiel #1
0
		/// <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
        }
Beispiel #2
0
		/// <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);
		}
Beispiel #3
0
		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);
		}
Beispiel #4
0
		private PathResolver (DirectoryEntry rootDirectory, DirectoryEntry currentDirectory)
		{
			this.rootDirectory = rootDirectory;
			this.currentDirectory = currentDirectory;
			depth = PathResolver.MAX_SYMLINKS_TO_FOLLOW;
		}
Beispiel #5
0
		/// <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;
		}
Beispiel #6
0
		/// <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);
		}
Beispiel #7
0
		public override void Delete (IVfsNode child, DirectoryEntry dentry)
		{
			throw new System.ArgumentException (); // Delete() method doesn't make sense here
		}
Beispiel #8
0
		/// <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;
		}
Beispiel #9
0
		/// <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;
		}
Beispiel #10
0
		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;
		}
Beispiel #11
0
		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);
		}
Beispiel #12
0
		/// <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;
		}
Beispiel #13
0
		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;
		}
Beispiel #14
0
 public abstract void Delete(IVfsNode child, DirectoryEntry entry);
Beispiel #15
0
		public override void Delete (IVfsNode child, DirectoryEntry dentry)
		{
			// FIXME: throw new NotImplementedException();
		}
Beispiel #16
0
		public abstract void Delete(IVfsNode child, DirectoryEntry entry);
Beispiel #17
0
		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();
		}
Beispiel #18
0
		/// <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;
		}