Esempio n. 1
0
        /// <summary>
        /// Checks if the caller has access to the inode
        /// </summary>
        /// <param name="path">The resource to check permissions for.</param>
        /// <param name="mode"></param>
        /// <returns>True if the requested access mode combination is available to the immediate caller. If any one requested access mode is not available, the result is false.</returns>
        public static bool Access(string path, AccessMode mode)
        {
            DirectoryEntry entry = PathResolver.Resolve(rootNode, ref path, PathResolutionFlags.DoNotThrowNotFoundException);

            if (null != entry)
            {
                return(AccessCheck.Perform(entry, mode, AccessCheckFlags.NoThrow));
            }

            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Deletes the named node from the filesystem.
        /// </summary>
        /// <param name="path">The path, which identifies a node.</param>
        public static void Delete(string path)
        {
            DirectoryEntry entry = PathResolver.Resolve(rootNode, ref path, PathResolutionFlags.DoNotThrowNotFoundException);

            if (null != entry)
            {
                AccessCheck.Perform(entry, AccessMode.Delete, AccessCheckFlags.None);

                //entry.Node.Delete();
                entry.Parent.Node.Delete(entry.Node, entry);
                entry.Release();
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Creates a new node in the (virtual) filesystem.
        /// </summary>
        /// <param name="path">The path to create.</param>
        /// <param name="type">The type of the node to create.</param>
        /// <param name="settings">Settings used to initialize the node.</param>
        /// <param name="access">Requests the specified access modes on the created object.</param>
        /// <param name="share">Requests the specified sharing settings on the object.</param>
        /// <returns>The created filesystem object.</returns>
        /// <remarks>
        /// This function creates new nodes in the virtual filesystem. In contrast to *nix this call
        /// creates all node types, e.g. files, directories, devices and more. Specific types may
        /// require additional settings, which are specified in a settings object passed as the third
        /// parameter.
        /// </remarks>
        public static object Create(string path, VfsNodeType type, object settings, System.IO.FileAccess access, System.IO.FileShare share)
        {
            // Retrieve the parent directory
            DirectoryEntry parent = PathResolver.Resolve(rootNode, ref path, PathResolutionFlags.RetrieveParent);

            // Check if the caller has write access in the directory
            AccessCheck.Perform(parent, AccessMode.Write, AccessCheckFlags.None);

            // Yes, we do have write access. Create the new vfs node
            IVfsNode node = parent.Node.Create(path, type, settings);

            // FIXME: Assert(null != node);
            DirectoryEntry entry = DirectoryEntry.Allocate(parent, path, node);

            // FIXME: Fix the permissions for this call. *nix does this using its bitmasks, Win32 through its huge CreateFile API.
            return(node.Open(access, share));
        }
Esempio n. 4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="access"></param>
        /// <param name="share"></param>
        /// <returns></returns>
        public static object Open(string path, System.IO.FileAccess access, System.IO.FileShare share)
        {
            DirectoryEntry entry = PathResolver.Resolve(rootNode, ref path);

            /* HINT:
             *
             * 1. Do we really need to pass the FileShare flags down to the inode?
             * 2. Shouldn't we have some sort of lock deamon governing shared access?
             *
             * Ansers:
             * 1. Yes.
             * 2. Yes and no. A lock deamon would only work for local filesystems. For imported
             *    ones we need to notify the server of the sharing lock anyway, so that the IVfsNode
             *    (acting as a client to the server) is the best place to do it without giving the
             *    lock deamon knowledge of all file sharing protocols (afp, smb, ftp, name it.)
             * 3. The inode may reject the file sharing requests. We do want to represent devices
             *    and sync objects in the VFS, which means *they* need to decide if the flags are
             *    applicable.
             *
             */

            // FIXME: Perform access checks on the DirectoryEntry/IVfsNode.
            AccessMode modeFlags = AccessMode.Exists;

            switch (access)
            {
            case System.IO.FileAccess.Read:
                modeFlags = AccessMode.Read;
                break;

            case System.IO.FileAccess.Write:
                modeFlags = AccessMode.Write;
                break;

            case System.IO.FileAccess.ReadWrite:
                modeFlags = AccessMode.Read | AccessMode.Write;
                break;
            }

            AccessCheck.Perform(entry, modeFlags, AccessCheckFlags.None);

            return(entry.Node.Open(access, share));
        }
Esempio n. 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="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);
        }