Exemple #1
0
 internal static String InternalGetDirectoryRoot(String path)
 {
     if (path == null)
     {
         return(null);
     }
     return(path.Substring(0, PathHelpers.GetRootLength(path)));
 }
Exemple #2
0
        internal DirectoryInfo(String fullPath, IFileSystemObject fileSystemObject) : base(fileSystemObject)
        {
            Debug.Assert(PathHelpers.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 #3
0
        public static String GetDirectoryRoot(String path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            Contract.EndContractBlock();

            String fullPath = PathHelpers.GetFullPathInternal(path);
            String root     = fullPath.Substring(0, PathHelpers.GetRootLength(fullPath));

            return(root);
        }
Exemple #4
0
        private static SafeFileHandle OpenHandle(string fullPath, bool asDirectory)
        {
            String root = fullPath.Substring(0, PathHelpers.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");
            }

            Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES);
            SafeFileHandle handle = Helpers.SafeCreateFile(
                fullPath,
                (int)Interop.mincore.GenericOperations.GENERIC_WRITE,
                FileShare.ReadWrite | FileShare.Delete,
                ref secAttrs,
                FileMode.Open,
                asDirectory ? (int)Interop.mincore.FileOperations.FILE_FLAG_BACKUP_SEMANTICS : (int)FileOptions.None,
                IntPtr.Zero
                );

            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.mincore.Errors.ERROR_PATH_NOT_FOUND && fullPath.Equals(Directory.GetDirectoryRoot(fullPath)))
                {
                    errorCode = Interop.mincore.Errors.ERROR_ACCESS_DENIED;
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath);
            }
            return(handle);
        }
        public override void CreateDirectory(string fullPath)
        {
            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 = PathHelpers.GetRootLength(fullPath);

            // For UNC paths that are only // or ///
            if (length == 2 && PathHelpers.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.  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;

            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 && !PathHelpers.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.SECURITY_ATTRIBUTES secAttrs = default(Interop.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);
                if (name.Length >= Interop.MAX_DIRECTORY_PATH)
                {
                    throw new PathTooLongException(SR.IO_PathTooLong);
                }
                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.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.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.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 #6
0
        public override 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 && PathHelpers.EndsInDirectorySeparator(fullPath))
            {
                length--;
            }

            // For paths that are only // or ///
            if (length == 2 && PathHelpers.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     = PathHelpers.GetRootLength(fullPath);

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

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

            int count = stackDir.Count;

            if (count == 0 && !somepathexists)
            {
                string root = Directory.InternalGetDirectoryRoot(fullPath);
                if (!DirectoryExists(root))
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Errors.ENOENT, fullPath, isDirectory: true);
                }
                return;
            }

            // Create all the directories
            int    result      = 0;
            int    firstError  = 0;
            string errorString = fullPath;

            while (stackDir.Count > 0)
            {
                string name = stackDir.Pop();
                if (name.Length >= MaxDirectoryPath)
                {
                    throw new PathTooLongException(SR.IO_PathTooLong);
                }

                int errno = 0;
                while ((result = Interop.libc.mkdir(name, (int)Interop.libc.Permissions.S_IRWXU)) < 0 && (errno = Marshal.GetLastWin32Error()) == Interop.Errors.EINTR)
                {
                    ;
                }
                if (result < 0 && firstError == 0)
                {
                    // 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 (errno != Interop.Errors.EEXIST)
                    {
                        firstError = errno;
                    }
                    else if (FileExists(name) || (!DirectoryExists(name, out errno) && errno == Interop.Errors.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  = errno;
                        errorString = name;
                    }
                }
            }

            // Only throw an exception if creating the exact directory we wanted failed to work correctly.
            if (result < 0 && firstError != 0)
            {
                throw Interop.GetExceptionForIoErrno(firstError, errorString, isDirectory: true);
            }
        }
Exemple #7
0
        private async Task <FileStreamBase> OpenAsync(string fullPath, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent)
        {
            // When trying to open the root directory, we need to throw an Access Denied
            if (PathHelpers.GetRootLength(fullPath) == fullPath.Length)
            {
                throw Win32Marshal.GetExceptionForWin32Error(Interop.mincore.Errors.ERROR_ACCESS_DENIED, fullPath);
            }

            // Win32 CreateFile returns ERROR_PATH_NOT_FOUND when given a path that ends with '\'
            if (PathHelpers.EndsInDirectorySeparator(fullPath))
            {
                throw Win32Marshal.GetExceptionForWin32Error(Interop.mincore.Errors.ERROR_PATH_NOT_FOUND, fullPath);
            }

            StorageFile file = null;

            // FileMode
            if (mode == FileMode.Open || mode == FileMode.Truncate)
            {
                file = await StorageFile.GetFileFromPathAsync(fullPath).TranslateWinRTTask(fullPath);
            }
            else
            {
                CreationCollisionOption collisionOptions;

                switch (mode)
                {
                case FileMode.Create:
                    collisionOptions = CreationCollisionOption.ReplaceExisting;
                    break;

                case FileMode.CreateNew:
                    collisionOptions = CreationCollisionOption.FailIfExists;
                    break;

                case FileMode.Append:
                case FileMode.OpenOrCreate:
                default:
                    collisionOptions = CreationCollisionOption.OpenIfExists;
                    break;
                }

                string directoryPath, fileName;
                PathHelpers.SplitDirectoryFile(fullPath, out directoryPath, out fileName);

                StorageFolder directory = await StorageFolder.GetFolderFromPathAsync(directoryPath).TranslateWinRTTask(directoryPath, isDirectory: true);

                file = await directory.CreateFileAsync(fileName, collisionOptions).TranslateWinRTTask(fullPath);
            }

            // FileAccess: WinRT doesn't support FileAccessMode.Write so we upgrade to ReadWrite
            FileAccessMode accessMode = ((access & FileAccess.Write) != 0) ? FileAccessMode.ReadWrite : FileAccessMode.Read;

            // FileShare: cannot translate StorageFile uses a different sharing model (oplocks) that is controlled via FileAccessMode

            // FileOptions: ignore most values of FileOptions as they are hints and are not supported by WinRT.
            // FileOptions.Encrypted is not a hint, and not supported by WinRT, but there is precedent for ignoring this (FAT).
            // FileOptions.DeleteOnClose should result in an UnauthorizedAccessException when
            //   opening a file that can only be read, but we cannot safely reproduce that behavior
            //   in WinRT without actually deleting the file.
            //   Instead the failure will occur in the finalizer for WinRTFileStream and be ignored.

            // open our stream
            Stream stream = (await file.OpenAsync(accessMode).TranslateWinRTTask(fullPath)).AsStream(bufferSize);

            if (mode == FileMode.Append)
            {
                // seek to end.
                stream.Seek(0, SeekOrigin.End);
            }
            else if (mode == FileMode.Truncate)
            {
                // truncate stream to 0
                stream.SetLength(0);
            }

            return(new WinRTFileStream(stream, file, access, options, parent));
        }