Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoMount fails when ACLs on directory are note set correctly #1811

Open
GabeDeBacker opened this issue Apr 11, 2024 · 0 comments
Open

AutoMount fails when ACLs on directory are note set correctly #1811

GabeDeBacker opened this issue Apr 11, 2024 · 0 comments

Comments

@GabeDeBacker
Copy link

The GVFS.Service service is running as local system.

If a directory is cloned into a directory that only has ACLs (full control) for a specific user... say:
D:\os.2>ICACLS .
. REDMOND\gabrield:(OI)(CI)(F)

Then auto-mount fails because the service cannot open the directory when it tries to fix the path casing.

This can be corrected in two ways..

First, use .net to fix the path casing instead of PInvoking into native APIs. (I have confirmed this works with ACL changse).
Second, GVFS clone should ensure that the ACLs on the clone directory are properly set for the access rights it needs.

For the first issue, the fix is using the following code in WindowsFileSystem.Shared.cs

using GVFS.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;

namespace GVFS.Platform.Windows
{
    public partial class WindowsFileSystem
    {
        /// <summary>
        /// Getting the logical drives isn't exactly super fast (it isn't super slow either).
        /// It is super unlikely that the drive set will change while the server is running.
        /// </summary>
        private static readonly Lazy<IReadOnlyDictionary<string, string>> LogicalDrives = new Lazy<IReadOnlyDictionary<string, string>>(() =>
        {
            var logicalDrives = Directory.GetLogicalDrives();
            var dictionary = new Dictionary<string, string>(logicalDrives.Length, StringComparer.OrdinalIgnoreCase);
            foreach (var logicalDrive in logicalDrives)
            {
                dictionary.Add(logicalDrive, logicalDrive);
            }

            return dictionary;
        });

        public static bool TryGetNormalizedPathImplementation(string path, out string normalizedPath, out string errorMessage)
        {
            normalizedPath = null;
            errorMessage = null;
            try
            {
                if (!(File.Exists(path) || Directory.Exists(path)))
                {
                    errorMessage = "Path does not exist: " + path;
                    return false;
                }

                // We don't want ".." etc in our file paths.
                path = Path.GetFullPath(path);

                // Build a list of DirectoryInfo objects so we can use them to retrieve
                // the "file system info".
                var directoryInfoList = new List<DirectoryInfo>();
                for (var di = new DirectoryInfo(path); di != null; di = di.Parent)
                {
                    // Always insert at the head to make sure the path parts are in the correct order.
                    directoryInfoList.Insert(0, di);
                }

                // Now, create a IEnumerable<string> from them.
                normalizedPath = Path.Combine(directoryInfoList.Select((foundEntry) =>
                {
                    // If we have a parent "directory info" (which is true for every path part except the root - i.e. drive letter)
                    // then ask the parent to get the "File System Info" for ourselves, and THAT gives us the correct casing.
                    if (foundEntry.Parent != null)
                    {
                        return foundEntry.Parent.GetFileSystemInfos(foundEntry.Name).First().Name;
                    }

                    // Now, for the root, well, we will ask the file system to give us the logical
                    // drives and then when we find a match, return what it gave us.
                    if (LogicalDrives.Value.TryGetValue(foundEntry.Name, out var fixedDriveCasing))
                    {
                        return fixedDriveCasing;
                    }

                    // Finally, if we couldn't find that, just return to upper on the entry, which makes this work for UNC shares.
                    return foundEntry.Name.ToUpperInvariant();
                }).ToArray());
            }
            catch (Win32Exception e)
            {
                errorMessage = "Could not get path root. Failed to determine volume: " + e.Message;
                return false;
            }

            return true;
        }
    }
}

I have not yet had time to investigate the clone code to add "full control" to the clone directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant