Exemple #1
0
        // Returns the directory path of a file path. This method effectively
        // removes the last element of the given file path, i.e. it returns a
        // string consisting of all characters up to but not including the last
        // backslash ("\") in the file path. The returned value is null if the file
        // path is null or if the file path denotes a root (such as "\", "C:", or
        // "\\server\share").
        public static string GetDirectoryName(string path)
        {
            if (path == null)
            {
                return(null);
            }

            if (PathInternal.IsEffectivelyEmpty(path))
            {
                throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
            }

            path = PathInternal.NormalizeDirectorySeparators(path);
            int root = PathInternal.GetRootLength(path);

            int i = path.Length;

            if (i > root)
            {
                while (i > root && !PathInternal.IsDirectorySeparator(path[--i]))
                {
                    ;
                }
                return(path.Substring(0, i));
            }

            return(null);
        }
Exemple #2
0
        // Returns the directory path of a file path. This method effectively
        // removes the last element of the given file path, i.e. it returns a
        // string consisting of all characters up to but not including the last
        // backslash ("\") in the file path. The returned value is null if the file
        // path is null or if the file path denotes a root (such as "\", "C:", or
        // "\\server\share").
        public static string GetDirectoryName(string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                if (path == null)
                {
                    return(null);
                }
                throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
            }

            PathInternal.CheckInvalidPathChars(path);
            path = PathInternal.NormalizeDirectorySeparators(path);
            int root = PathInternal.GetRootLength(path);

            int i = path.Length;

            if (i > root)
            {
                while (i > root && !PathInternal.IsDirectorySeparator(path[--i]))
                {
                    ;
                }
                return(path.Substring(0, i));
            }

            return(null);
        }
Exemple #3
0
        // Expands the given path to a fully qualified path.
        public static string GetFullPath(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (path.Length == 0)
            {
                throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
            }

            if (path.Contains('\0'))
            {
                throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
            }

            // Expand with current directory if necessary
            if (!IsPathRooted(path))
            {
                path = Combine(Interop.Sys.GetCwd(), path);
            }

            // We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist,
            // and turns it into a full path, which we only want if fullCheck is true.
            string collapsedString = PathInternal.RemoveRelativeSegments(path, PathInternal.GetRootLength(path));

            Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path,
                         "Either we've removed characters, or the string should be unmodified from the input path.");

            string result = collapsedString.Length == 0 ? PathInternal.DirectorySeparatorCharAsString : collapsedString;

            return(result);
        }
Exemple #4
0
        internal static void SplitDirectoryFile(string path, out string directory, out string file)
        {
            directory = null;
            file      = null;

            // assumes a validated full path
            if (path != null)
            {
                int length     = path.Length;
                int rootLength = PathInternal.GetRootLength(path);

                // ignore a trailing slash
                if (length > rootLength && EndsInDirectorySeparator(path))
                {
                    length--;
                }

                // find the pivot index between end of string and root
                for (int pivot = length - 1; pivot >= rootLength; pivot--)
                {
                    if (PathInternal.IsDirectorySeparator(path[pivot]))
                    {
                        directory = path.Substring(0, pivot);
                        file      = path.Substring(pivot + 1, length - pivot - 1);
                        return;
                    }
                }

                // no pivot, return just the trimmed directory
                directory = path.Substring(0, length);
            }
        }
Exemple #5
0
        private static SafeFileHandle OpenHandle(string fullPath, bool asDirectory)
        {
            string root = fullPath.Substring(0, PathInternal.GetRootLength(fullPath));

            if (root == fullPath && root[1] == Path.VolumeSeparatorChar)
            {
                // intentionally not fullpath, most upstack public APIs expose this as path.
                throw new ArgumentException(SR.Arg_PathIsVolume, "path");
            }

            SafeFileHandle handle = Interop.Kernel32.CreateFile(
                fullPath,
                Interop.Kernel32.GenericOperations.GENERIC_WRITE,
                FileShare.ReadWrite | FileShare.Delete,
                FileMode.Open,
                asDirectory ? Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS : 0);

            if (handle.IsInvalid)
            {
                int errorCode = Marshal.GetLastWin32Error();

                // NT5 oddity - when trying to open "C:\" as a File,
                // we usually get ERROR_PATH_NOT_FOUND from the OS.  We should
                // probably be consistent w/ every other directory.
                if (!asDirectory && errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && fullPath.Equals(Directory.GetDirectoryRoot(fullPath)))
                {
                    errorCode = Interop.Errors.ERROR_ACCESS_DENIED;
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            return(handle);
        }
Exemple #6
0
        // Returns the directory path of a file path. This method effectively
        // removes the last element of the given file path, i.e. it returns a
        // string consisting of all characters up to but not including the last
        // backslash ("\") in the file path. The returned value is null if the file
        // path is null or if the file path denotes a root (such as "\", "C:", or
        // "\\server\share").
        public static string GetDirectoryName(string path)
        {
            if (path != null)
            {
                PathInternal.CheckInvalidPathChars(path);
                path = NormalizePath(path, fullCheck: false);

                int root = PathInternal.GetRootLength(path);
                int i    = path.Length;
                if (i > root)
                {
                    i = path.Length;
                    if (i == root)
                    {
                        return(null);
                    }
                    while (i > root && !PathInternal.IsDirectorySeparator(path[--i]))
                    {
                        ;
                    }
                    return(path.Substring(0, i));
                }
            }
            return(null);
        }
Exemple #7
0
        public static unsafe ReadOnlySpan <char> GetDirectoryNameNoChecks(ReadOnlySpan <char> path)
        {
            if (path.Length == 0)
            {
                return(ReadOnlySpan <char> .Empty);
            }

            int root = PathInternal.GetRootLength(path);
            int i    = path.Length;

            fixed(char *pathPtr = &path.DangerousGetPinnableReference())
            {
                var pathSpan = new Span <char>(pathPtr, path.Length);

                if (i > root)
                {
                    while (i > root && !PathInternal.IsDirectorySeparator(pathSpan[--i]))
                    {
                        ;
                    }
                    return(pathSpan.Slice(0, i));
                }
            }

            return(ReadOnlySpan <char> .Empty);
        }
Exemple #8
0
 internal static uint GetRootLength(StringBuffer path)
 {
     if (path.Length == 0U)
     {
         return(0U);
     }
     return(PathInternal.GetRootLength(path.CharPointer, (ulong)path.Length));
 }
Exemple #9
0
 internal static String InternalGetDirectoryRoot(String path)
 {
     if (path == null)
     {
         return(null);
     }
     return(path.Substring(0, PathInternal.GetRootLength(path)));
 }
Exemple #10
0
 internal FileInfo(String fullPath, bool ignoreThis)
 {
     Contract.Assert(PathInternal.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
     _name        = Path.GetFileName(fullPath);
     OriginalPath = _name;
     FullPath     = fullPath;
     DisplayPath  = _name;
 }
Exemple #11
0
        internal DirectoryInfo(String fullPath, bool junk)
        {
            Debug.Assert(PathInternal.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
            // Fast path when we know a DirectoryInfo exists.
            OriginalPath = Path.GetFileName(fullPath);

            FullPath    = fullPath;
            DisplayPath = GetDisplayName(OriginalPath, FullPath);
        }
Exemple #12
0
 public static string GetPathRoot(string path)
 {
     if (path == null)
     {
         return(null);
     }
     path = NormalizePath(path, fullCheck: false);
     return(path.Substring(0, PathInternal.GetRootLength(path)));
 }
        internal static bool AreRootsEqual(
            string first,
            string second,
            StringComparison comparisonType)
        {
            int rootLength1 = PathInternal.GetRootLength(first.AsSpan());
            int rootLength2 = PathInternal.GetRootLength(second.AsSpan());

            return(rootLength1 == rootLength2 && string.Compare(first, 0, second, 0, rootLength1, comparisonType) == 0);
        }
Exemple #14
0
        internal DirectoryInfo(String fullPath, bool junk)
        {
            Contract.Assert(PathInternal.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
            // Fast path when we know a DirectoryInfo exists.
            OriginalPath = Path.GetFileName(fullPath);

            FullPath    = fullPath;
            DisplayPath = GetDisplayName(OriginalPath, FullPath);
            demandDir   = new String[] { Directory.GetDemandDir(fullPath, true) };
        }
Exemple #15
0
        internal unsafe static int GetRootLength(string path)
        {
            char *ptr = path;

            if (ptr != null)
            {
                ptr += RuntimeHelpers.OffsetToStringData / 2;
            }
            return((int)PathInternal.GetRootLength(ptr, (ulong)((long)path.Length)));
        }
Exemple #16
0
        /// <remarks>
        /// Unlike the string overload, this method will not normalize directory separators.
        /// </remarks>
        public static ReadOnlySpan <char> GetPathRoot(ReadOnlySpan <char> path)
        {
            if (PathInternal.IsEffectivelyEmpty(path))
            {
                return(ReadOnlySpan <char> .Empty);
            }

            int pathRoot = PathInternal.GetRootLength(path);

            return(pathRoot <= 0 ? ReadOnlySpan <char> .Empty : path.Slice(0, pathRoot));
        }
Exemple #17
0
        // Returns the root portion of the given path. The resulting string
        // consists of those rightmost characters of the path that constitute the
        // root of the path. Possible patterns for the resulting string are: An
        // empty string (a relative path on the current drive), "\" (an absolute
        // path on the current drive), "X:" (a relative path on a given drive,
        // where X is the drive letter), "X:\" (an absolute path on a given drive),
        // and "\\server\share" (a UNC path for a given server and share name).
        // The resulting string is null if path is null.
        public static string GetPathRoot(string path)
        {
            if (path == null)
            {
                return(null);
            }
            PathInternal.CheckInvalidPathChars(path);
            int pathRoot = PathInternal.GetRootLength(path);

            return(pathRoot <= 0 ? String.Empty : path.Substring(0, pathRoot));
        }
Exemple #18
0
        // Returns the root portion of the given path. The resulting string
        // consists of those rightmost characters of the path that constitute the
        // root of the path. Possible patterns for the resulting string are: An
        // empty string (a relative path on the current drive), "\" (an absolute
        // path on the current drive), "X:" (a relative path on a given drive,
        // where X is the drive letter), "X:\" (an absolute path on a given drive),
        // and "\\server\share" (a UNC path for a given server and share name).
        // The resulting string is null if path is null.
        public static string GetPathRoot(string path)
        {
            if (path == null)
            {
                return(null);
            }
            PathInternal.CheckInvalidPathChars(path);
            int pathRoot = PathInternal.GetRootLength(path);

            // Need to return the normalized directory separator
            return(pathRoot <= 0 ? string.Empty : path.Substring(0, pathRoot).Replace(AltDirectorySeparatorChar, DirectorySeparatorChar));
        }
Exemple #19
0
        public static string GetDirectoryRoot(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            string fullPath = Path.GetFullPath(path);
            string root     = fullPath.Substring(0, PathInternal.GetRootLength(fullPath));

            return(root);
        }
Exemple #20
0
        public static String GetDirectoryRoot(String path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            Contract.EndContractBlock();

            String fullPath = Path.GetFullPath(path);
            String root     = fullPath.Substring(0, PathInternal.GetRootLength(fullPath));

            return(root);
        }
Exemple #21
0
        // Returns the root portion of the given path. The resulting string
        // consists of those rightmost characters of the path that constitute the
        // root of the path. Possible patterns for the resulting string are: An
        // empty string (a relative path on the current drive), "\" (an absolute
        // path on the current drive), "X:" (a relative path on a given drive,
        // where X is the drive letter), "X:\" (an absolute path on a given drive),
        // and "\\server\share" (a UNC path for a given server and share name).
        // The resulting string is null if path is null. If the path is empty or
        // only contains whitespace characters an ArgumentException gets thrown.
        public static string GetPathRoot(string path)
        {
            if (path == null)
            {
                return(null);
            }
            if (PathInternal.IsEffectivelyEmpty(path))
            {
                throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
            }

            // Need to return the normalized directory separator
            path = PathInternal.NormalizeDirectorySeparators(path);

            int pathRoot = PathInternal.GetRootLength(path);

            return(pathRoot <= 0 ? string.Empty : path.Substring(0, pathRoot));
        }
        private static int GetDirectoryNameOffset(ReadOnlySpan <char> path)
        {
            int rootLength = PathInternal.GetRootLength(path);
            int length     = path.Length;

            if (length <= rootLength)
            {
                return(-1);
            }
            do
            {
                ;
            }while (length > rootLength && !PathInternal.IsDirectorySeparator(path[--length]));
            while (length > rootLength && PathInternal.IsDirectorySeparator(path[length - 1]))
            {
                --length;
            }
            return(length);
        }
Exemple #23
0
        // Returns the root portion of the given path. The resulting string
        // consists of those rightmost characters of the path that constitute the
        // root of the path. Possible patterns for the resulting string are: An
        // empty string (a relative path on the current drive), "\" (an absolute
        // path on the current drive), "X:" (a relative path on a given drive,
        // where X is the drive letter), "X:\" (an absolute path on a given drive),
        // and "\\server\share" (a UNC path for a given server and share name).
        // The resulting string is null if path is null. If the path is empty or
        // only contains whitespace characters an ArgumentException gets thrown.
        public static string GetPathRoot(string path)
        {
            if (path == null)
            {
                return(null);
            }
            if (string.IsNullOrWhiteSpace(path))
            {
                throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
            }

            PathInternal.CheckInvalidPathChars(path);

            // Need to return the normalized directory separator
            path = PathInternal.NormalizeDirectorySeparators(path);

            int pathRoot = PathInternal.GetRootLength(path);

            return(pathRoot <= 0 ? string.Empty : path.Substring(0, pathRoot));
        }
Exemple #24
0
        // Gets the full path without argument validation
        private static string GetFullPathInternal(string path)
        {
            Debug.Assert(!string.IsNullOrEmpty(path));
            Debug.Assert(!path.Contains('\0'));

            // Expand with current directory if necessary
            if (!IsPathRooted(path))
            {
                path = Combine(Interop.Sys.GetCwd(), path);
            }

            // We would ideally use realpath to do this, but it resolves symlinks and requires that the file actually exist.
            string collapsedString = PathInternal.RemoveRelativeSegments(path, PathInternal.GetRootLength(path));

            Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path,
                         "Either we've removed characters, or the string should be unmodified from the input path.");

            string result = collapsedString.Length == 0 ? PathInternal.DirectorySeparatorCharAsString : collapsedString;

            return(result);
        }
Exemple #25
0
        public static ReadOnlySpan <char> GetDirectoryNameNoChecks(ReadOnlySpan <char> path)
        {
            if (path.Length == 0)
            {
                return(ReadOnlySpan <char> .Empty);
            }

            int root = PathInternal.GetRootLength(path);
            int i    = path.Length;

            if (i > root)
            {
                while (i > root && !PathInternal.IsDirectorySeparator(path[--i]))
                {
                    ;
                }
                return(path.Slice(0, i));
            }

            return(ReadOnlySpan <char> .Empty);
        }
Exemple #26
0
        private static SafeFileHandle OpenHandleToWriteAttributes(string fullPath, bool asDirectory)
        {
            if (fullPath.Length == PathInternal.GetRootLength(fullPath) && fullPath[1] == Path.VolumeSeparatorChar)
            {
                // intentionally not fullpath, most upstack public APIs expose this as path.
                throw new ArgumentException(SR.Arg_PathIsVolume, "path");
            }

            int dwFlagsAndAttributes = Interop.Kernel32.FileOperations.FILE_FLAG_OPEN_REPARSE_POINT;

            if (asDirectory)
            {
                dwFlagsAndAttributes |= Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS;
            }

            SafeFileHandle handle = Interop.Kernel32.CreateFile(
                fullPath,
                Interop.Kernel32.FileOperations.FILE_WRITE_ATTRIBUTES,
                FileShare.ReadWrite | FileShare.Delete,
                FileMode.Open,
                dwFlagsAndAttributes);

            if (handle.IsInvalid)
            {
                int errorCode = Marshal.GetLastWin32Error();

                // NT5 oddity - when trying to open "C:\" as a File,
                // we usually get ERROR_PATH_NOT_FOUND from the OS.  We should
                // probably be consistent w/ every other directory.
                if (!asDirectory && errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && fullPath.Equals(Directory.GetDirectoryRoot(fullPath)))
                {
                    errorCode = Interop.Errors.ERROR_ACCESS_DENIED;
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }

            return(handle);
        }
Exemple #27
0
        internal static int GetDirectoryNameOffset(ReadOnlySpan <char> path)
        {
            int rootLength = PathInternal.GetRootLength(path);
            int end        = path.Length;

            if (end <= rootLength)
            {
                return(-1);
            }

            while (end > rootLength && !PathInternal.IsDirectorySeparator(path[--end]))
            {
                ;
            }

            // Trim off any remaining separators (to deal with C:\foo\\bar)
            while (end > rootLength && PathInternal.IsDirectorySeparator(path[end - 1]))
            {
                end--;
            }

            return(end);
        }
Exemple #28
0
        public override void CreateDirectory(string fullPath)
        {
            if (PathInternal.IsDirectoryTooLong(fullPath))
            {
                throw new PathTooLongException(SR.IO_PathTooLong);
            }

            // We can save a bunch of work if the directory we want to create already exists.  This also
            // saves us in the case where sub paths are inaccessible (due to ERROR_ACCESS_DENIED) but the
            // final path is accessable and the directory already exists.  For example, consider trying
            // to create c:\Foo\Bar\Baz, where everything already exists but ACLS prevent access to c:\Foo
            // and c:\Foo\Bar.  In that case, this code will think it needs to create c:\Foo, and c:\Foo\Bar
            // and fail to due so, causing an exception to be thrown.  This is not what we want.
            if (DirectoryExists(fullPath))
            {
                return;
            }

            List <string> stackDir = new List <string>();

            // Attempt to figure out which directories don't exist, and only
            // create the ones we need.  Note that InternalExists may fail due
            // to Win32 ACL's preventing us from seeing a directory, and this
            // isn't threadsafe.

            bool somepathexists = false;

            int length = fullPath.Length;

            // We need to trim the trailing slash or the code will try to create 2 directories of the same name.
            if (length >= 2 && PathHelpers.EndsInDirectorySeparator(fullPath))
            {
                length--;
            }

            int lengthRoot = PathInternal.GetRootLength(fullPath);

            if (length > lengthRoot)
            {
                // Special case root (fullpath = X:\\)
                int i = length - 1;
                while (i >= lengthRoot && !somepathexists)
                {
                    String dir = fullPath.Substring(0, i + 1);

                    if (!DirectoryExists(dir)) // Create only the ones missing
                    {
                        stackDir.Add(dir);
                    }
                    else
                    {
                        somepathexists = true;
                    }

                    while (i > lengthRoot && !PathInternal.IsDirectorySeparator(fullPath[i]))
                    {
                        i--;
                    }
                    i--;
                }
            }

            int count = stackDir.Count;

            // If we were passed a DirectorySecurity, convert it to a security
            // descriptor and set it in he call to CreateDirectory.
            Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES);

            bool   r           = true;
            int    firstError  = 0;
            String errorString = fullPath;

            // If all the security checks succeeded create all the directories
            while (stackDir.Count > 0)
            {
                String name = stackDir[stackDir.Count - 1];
                stackDir.RemoveAt(stackDir.Count - 1);

                r = Interop.mincore.CreateDirectory(name, ref secAttrs);
                if (!r && (firstError == 0))
                {
                    int currentError = Marshal.GetLastWin32Error();
                    // While we tried to avoid creating directories that don't
                    // exist above, there are at least two cases that will
                    // cause us to see ERROR_ALREADY_EXISTS here.  InternalExists
                    // can fail because we didn't have permission to the
                    // directory.  Secondly, another thread or process could
                    // create the directory between the time we check and the
                    // time we try using the directory.  Thirdly, it could
                    // fail because the target does exist, but is a file.
                    if (currentError != Interop.mincore.Errors.ERROR_ALREADY_EXISTS)
                    {
                        firstError = currentError;
                    }
                    else
                    {
                        // If there's a file in this directory's place, or if we have ERROR_ACCESS_DENIED when checking if the directory already exists throw.
                        if (File.InternalExists(name) || (!DirectoryExists(name, out currentError) && currentError == Interop.mincore.Errors.ERROR_ACCESS_DENIED))
                        {
                            firstError  = currentError;
                            errorString = name;
                        }
                    }
                }
            }

            // We need this check to mask OS differences
            // Handle CreateDirectory("X:\\") when X: doesn't exist. Similarly for n/w paths.
            if ((count == 0) && !somepathexists)
            {
                String root = Directory.InternalGetDirectoryRoot(fullPath);
                if (!DirectoryExists(root))
                {
                    throw Win32Marshal.GetExceptionForWin32Error(Interop.mincore.Errors.ERROR_PATH_NOT_FOUND, root);
                }
                return;
            }

            // Only throw an exception if creating the exact directory we
            // wanted failed to work correctly.
            if (!r && (firstError != 0))
            {
                throw Win32Marshal.GetExceptionForWin32Error(firstError, errorString);
            }
        }
Exemple #29
0
        public static void CreateDirectory(string fullPath)
        {
            // NOTE: This logic is primarily just carried forward from Win32FileSystem.CreateDirectory.

            int length = fullPath.Length;

            // We need to trim the trailing slash or the code will try to create 2 directories of the same name.
            if (length >= 2 && Path.EndsInDirectorySeparator(fullPath))
            {
                length--;
            }

            // For paths that are only // or ///
            if (length == 2 && PathInternal.IsDirectorySeparator(fullPath[1]))
            {
                throw new IOException(SR.Format(SR.IO_CannotCreateDirectory, fullPath));
            }

            // We can save a bunch of work if the directory we want to create already exists.
            if (DirectoryExists(fullPath))
            {
                return;
            }

            // Attempt to figure out which directories don't exist, and only create the ones we need.
            bool           somepathexists = false;
            Stack <string> stackDir       = new Stack <string>();
            int            lengthRoot     = PathInternal.GetRootLength(fullPath);

            if (length > lengthRoot)
            {
                int i = length - 1;
                while (i >= lengthRoot && !somepathexists)
                {
                    if (!DirectoryExists(fullPath.AsSpan(0, i + 1))) // Create only the ones missing
                    {
                        stackDir.Push(fullPath.Substring(0, i + 1));
                    }
                    else
                    {
                        somepathexists = true;
                    }

                    while (i > lengthRoot && !PathInternal.IsDirectorySeparator(fullPath[i]))
                    {
                        i--;
                    }
                    i--;
                }
            }

            int count = stackDir.Count;

            if (count == 0 && !somepathexists)
            {
                ReadOnlySpan <char> root = Path.GetPathRoot(fullPath.AsSpan());
                if (!DirectoryExists(root))
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Error.ENOENT.Info(), fullPath, isDirectory: true);
                }
                return;
            }

            // Create all the directories
            int result = 0;

            Interop.ErrorInfo firstError  = default(Interop.ErrorInfo);
            string            errorString = fullPath;

            while (stackDir.Count > 0)
            {
                string name = stackDir.Pop();

                // The mkdir command uses 0777 by default (it'll be AND'd with the process umask internally).
                // We do the same.
                result = Interop.Sys.MkDir(name, (int)Interop.Sys.Permissions.Mask);
                if (result < 0 && firstError.Error == 0)
                {
                    Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();

                    // While we tried to avoid creating directories that don't
                    // exist above, there are a few cases that can fail, e.g.
                    // a race condition where another process or thread creates
                    // the directory first, or there's a file at the location.
                    if (errorInfo.Error != Interop.Error.EEXIST)
                    {
                        firstError = errorInfo;
                    }
                    else if (FileExists(name) || (!DirectoryExists(name, out errorInfo) && errorInfo.Error == Interop.Error.EACCES))
                    {
                        // If there's a file in this directory's place, or if we have ERROR_ACCESS_DENIED when checking if the directory already exists throw.
                        firstError  = errorInfo;
                        errorString = name;
                    }
                }
            }

            // Only throw an exception if creating the exact directory we wanted failed to work correctly.
            if (result < 0 && firstError.Error != 0)
            {
                throw Interop.GetExceptionForIoErrno(firstError, errorString, isDirectory: true);
            }
        }
Exemple #30
0
        public static string GetFullPath(string path, string basePath)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (basePath == null)
            {
                throw new ArgumentNullException(nameof(basePath));
            }

            if (!IsPathFullyQualified(basePath))
            {
                throw new ArgumentException(SR.Arg_BasePathNotFullyQualified, nameof(basePath));
            }

            if (basePath.Contains('\0') || path.Contains('\0'))
            {
                throw new ArgumentException(SR.Argument_InvalidPathChars);
            }

            if (IsPathFullyQualified(path))
            {
                return(GetFullPath(path));
            }

            int    length       = path.Length;
            string combinedPath = null;

            if ((length >= 1 && PathInternal.IsDirectorySeparator(path[0])))
            {
                // Path is current drive rooted i.e. starts with \:
                // "\Foo" and "C:\Bar" => "C:\Foo"
                // "\Foo" and "\\?\C:\Bar" => "\\?\C:\Foo"
                combinedPath = Join(GetPathRoot(basePath.AsSpan()), path);
            }
            else if (length >= 2 && PathInternal.IsValidDriveChar(path[0]) && path[1] == PathInternal.VolumeSeparatorChar)
            {
                // Drive relative paths
                Debug.Assert(length == 2 || !PathInternal.IsDirectorySeparator(path[2]));

                if (StringSpanHelpers.Equals(GetVolumeName(path), GetVolumeName(basePath)))
                {
                    // Matching root
                    // "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
                    // "C:Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
                    combinedPath = Join(basePath, path.AsSpan().Slice(2));
                }
                else
                {
                    // No matching root, root to specified drive
                    // "D:Foo" and "C:\Bar" => "D:Foo"
                    // "D:Foo" and "\\?\C:\Bar" => "\\?\D:\Foo"
                    combinedPath = !PathInternal.IsDevice(basePath)
                        ? path.Insert(2, @"\")
                        : length == 2
                            ? JoinInternal(basePath.AsSpan().Slice(0, 4), path, @"\")
                            : JoinInternal(basePath.AsSpan().Slice(0, 4), path.AsSpan().Slice(0, 2), @"\", path.AsSpan().Slice(2));
                }
            }
            else
            {
                // "Simple" relative path
                // "Foo" and "C:\Bar" => "C:\Bar\Foo"
                // "Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
                combinedPath = JoinInternal(basePath, path);
            }

            // Device paths are normalized by definition, so passing something of this format
            // to GetFullPath() won't do anything by design. Additionally, GetFullPathName() in
            // Windows doesn't root them properly. As such we need to manually remove segments.
            return(PathInternal.IsDevice(combinedPath)
                ? RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath))
                : GetFullPath(combinedPath));
        }