Beispiel #1
0
 public SMBItem(FileDirectoryInformation fdi, string parentPath)
 {
     Name        = fdi.FileName;
     Path        = System.IO.Path.Combine(parentPath, fdi.FileName);
     IsDirectory = fdi.FileAttributes.HasFlag(FileAttributes.Directory);
     Size        = fdi.EndOfFile;
     Info        = fdi;
 }
 /// <summary>
 /// Verify FileDirectoryInformation entry
 /// </summary>
 private void VerifyFileInformation(FileDirectoryInformation entry, int index, string fileName, FileAttribute fileAttribute, long endOfFile, long allocationSize)
 {
     Site.Log.Add(LogEntryKind.Debug, $"Start to verify entry {index}.");
     VerifyFileCommonDirectoryInformation(entry.FileCommonDirectoryInformation, fileAttribute);
     Site.Assert.AreEqual(fileName, Encoding.Unicode.GetString(entry.FileName), $"FileName of the entry should be {fileName}.");
     Site.Assert.AreEqual(endOfFile, entry.FileCommonDirectoryInformation.EndOfFile, "The EndOfFile of the entry should be 0.");
     Site.Assert.AreEqual(allocationSize, entry.FileCommonDirectoryInformation.AllocationSize, "The AllocationSize of the entry should be 0.");
 }
Beispiel #3
0
        public override bool Exists(string path)
        {
            if (!path.IsSharePath())
            {
                return(base.Exists(path));
            }

            try
            {
                if (!path.TryResolveHostnameFromPath(out var ipAddress))
                {
                    throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\"");
                }

                NTStatus status = NTStatus.STATUS_SUCCESS;

                var credential = _credentialProvider.GetSMBCredential(path);

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    var shareName     = path.ShareName();
                    var directoryPath = _fileSystem.Path.GetDirectoryName(path);
                    var fileName      = _fileSystem.Path.GetFileName(path);

                    ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                    status.HandleStatus();

                    status = fileStore.CreateFile(out object handle, out FileStatus fileStatus, directoryPath, AccessMask.GENERIC_READ, 0, ShareAccess.Read,
                                                  CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);

                    status.HandleStatus();

                    fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(fileName) ? "*" : fileName, FileInformationClass.FileDirectoryInformation);

                    foreach (var file in queryDirectoryFileInformation)
                    {
                        if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                        {
                            FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                            if (fileDirectoryInformation.FileName == fileName)
                            {
                                fileStore.CloseFile(handle);
                                return(true);
                            }
                        }
                    }

                    fileStore.CloseFile(handle);
                }

                return(false);
            }
            catch
            {
                return(false);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Get Child Node from Path and Smb2-Result.
        /// </summary>
        /// <param name="parentNode"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        public static Node GetChild(
            Node parentNode,
            FileDirectoryInformation info
            )
        {
            if (parentNode == null)
            {
                throw new ArgumentException("Required parentNode.");
            }
            if (info == null)
            {
                throw new ArgumentException("Required info.");
            }

            var pathSet = PathSet.Parse($@"{parentNode.FullPath}\{info.FileName}");

            if (info.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory))
            {
                // Folder
                var result = NodeFactory.InnerGet(
                    NodeType.Folder,
                    pathSet,
                    parentNode.ParamSet
                    );
                result.Created      = info.CreationTime;
                result.Updated      = info.LastWriteTime;
                result.LastAccessed = info.LastAccessTime;

                return(result);
            }
            else
            {
                // File
                var result = NodeFactory.InnerGet(
                    NodeType.File,
                    pathSet,
                    parentNode.ParamSet
                    );
                result.Size         = info.EndOfFile;
                result.Created      = info.CreationTime;
                result.Updated      = info.LastWriteTime;
                result.LastAccessed = info.LastAccessTime;

                return(result);
            }
        }
        public static IDirectoryInformation CreateDirectoryInformation()
        {
            IDirectoryInformation info;

            string mode = ConfigurationManager.AppSettings["mode"].ToString();

            switch (mode.ToUpper())
            {

                case "TEST":
                    info = new MockDirectoryInformation();
                    break;
                case "PROD":
                    info = new FileDirectoryInformation();
                    break;
                default:
                    new ErrorLoger("Go into app.config and set mode either to PROD or TEST");
                    throw new Exception("You did something wrong");
            }
            return info;
        }
Beispiel #6
0
        public override bool Exists(string path)
        {
            if (!path.IsSharePath())
            {
                return(base.Exists(path));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

            try
            {
                if (!path.TryResolveHostnameFromPath(out var ipAddress))
                {
                    throw new SMBException($"Failed to determine if {path} exists", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
                }

                NTStatus status = NTStatus.STATUS_SUCCESS;

                var credential = _credentialProvider.GetSMBCredential(path);

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    var shareName     = path.ShareName();
                    var directoryPath = _fileSystem.Path.GetDirectoryName(path).Replace(path.SharePath(), "").RemoveLeadingAndTrailingSeperators();
                    var fileName      = _fileSystem.Path.GetFileName(path);

                    _logger?.LogTrace($"Trying to determine if {{DirectoryPath: {directoryPath}}} {{FileName: {fileName}}} Exists for {{ShareName: {shareName}}}");

                    fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                    status.HandleStatus();

                    AccessMask        accessMask    = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ;
                    ShareAccess       shareAccess   = ShareAccess.Read;
                    CreateDisposition disposition   = CreateDisposition.FILE_OPEN;
                    CreateOptions     createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DIRECTORY_FILE;

                    status = fileStore.CreateFile(out handle, out FileStatus fileStatus, directoryPath, accessMask, 0, shareAccess,
                                                  disposition, createOptions, null);

                    status.HandleStatus();

                    fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(fileName) ? "*" : fileName, FileInformationClass.FileDirectoryInformation);

                    foreach (var file in queryDirectoryFileInformation)
                    {
                        if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                        {
                            FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                            if (fileDirectoryInformation.FileName == fileName)
                            {
                                FileStoreUtilities.CloseFile(fileStore, ref handle);
                                return(true);
                            }
                        }
                    }

                    FileStoreUtilities.CloseFile(fileStore, ref handle);
                }

                return(false);
            }
            catch (Exception ex)
            {
                _logger?.LogTrace(ex, $"Failed to determine if {path} exists.");
                return(false);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
 /// <exception cref="SmbLibraryStd.UnsupportedInformationLevelException"></exception>
 public static FindInformation ToFindInformation(QueryDirectoryFileInformation fileInformation)
 {
     if (fileInformation is FileDirectoryInformation)
     {
         FileDirectoryInformation fileDirectoryInfo = (FileDirectoryInformation)fileInformation;
         FindFileDirectoryInfo    result            = new FindFileDirectoryInfo();
         result.FileIndex          = fileDirectoryInfo.FileIndex;
         result.CreationTime       = fileDirectoryInfo.CreationTime;
         result.LastAccessTime     = fileDirectoryInfo.LastAccessTime;
         result.LastWriteTime      = fileDirectoryInfo.LastWriteTime;
         result.LastAttrChangeTime = fileDirectoryInfo.LastWriteTime;
         result.EndOfFile          = fileDirectoryInfo.EndOfFile;
         result.AllocationSize     = fileDirectoryInfo.AllocationSize;
         result.ExtFileAttributes  = (ExtendedFileAttributes)fileDirectoryInfo.FileAttributes;
         result.FileName           = fileDirectoryInfo.FileName;
         return(result);
     }
     else if (fileInformation is FileFullDirectoryInformation)
     {
         FileFullDirectoryInformation fileFullDirectoryInfo = (FileFullDirectoryInformation)fileInformation;
         FindFileFullDirectoryInfo    result = new FindFileFullDirectoryInfo();
         result.FileIndex          = fileFullDirectoryInfo.FileIndex;
         result.CreationTime       = fileFullDirectoryInfo.CreationTime;
         result.LastAccessTime     = fileFullDirectoryInfo.LastAccessTime;
         result.LastWriteTime      = fileFullDirectoryInfo.LastWriteTime;
         result.LastAttrChangeTime = fileFullDirectoryInfo.LastWriteTime;
         result.EndOfFile          = fileFullDirectoryInfo.EndOfFile;
         result.AllocationSize     = fileFullDirectoryInfo.AllocationSize;
         result.ExtFileAttributes  = (ExtendedFileAttributes)fileFullDirectoryInfo.FileAttributes;
         result.EASize             = fileFullDirectoryInfo.EaSize;
         result.FileName           = fileFullDirectoryInfo.FileName;
         return(result);
     }
     else if (fileInformation is FileNamesInformation)
     {
         FileNamesInformation fileNamesInfo = (FileNamesInformation)fileInformation;
         FindFileNamesInfo    result        = new FindFileNamesInfo();
         result.FileIndex = fileNamesInfo.FileIndex;
         result.FileName  = fileNamesInfo.FileName;
         return(result);
     }
     else if (fileInformation is FileBothDirectoryInformation)
     {
         FileBothDirectoryInformation fileBothDirectoryInfo = (FileBothDirectoryInformation)fileInformation;
         FindFileBothDirectoryInfo    result = new FindFileBothDirectoryInfo();
         result.FileIndex         = fileBothDirectoryInfo.FileIndex;
         result.CreationTime      = fileBothDirectoryInfo.CreationTime;
         result.LastAccessTime    = fileBothDirectoryInfo.LastAccessTime;
         result.LastWriteTime     = fileBothDirectoryInfo.LastWriteTime;
         result.LastChangeTime    = fileBothDirectoryInfo.LastWriteTime;
         result.EndOfFile         = fileBothDirectoryInfo.EndOfFile;
         result.AllocationSize    = fileBothDirectoryInfo.AllocationSize;
         result.ExtFileAttributes = (ExtendedFileAttributes)fileBothDirectoryInfo.FileAttributes;
         result.EASize            = fileBothDirectoryInfo.EaSize;
         result.Reserved          = fileBothDirectoryInfo.Reserved;
         result.ShortName         = fileBothDirectoryInfo.ShortName;
         result.FileName          = fileBothDirectoryInfo.FileName;
         return(result);
     }
     else if (fileInformation is FileIdFullDirectoryInformation)
     {
         FileIdFullDirectoryInformation fileIDFullDirectoryInfo = (FileIdFullDirectoryInformation)fileInformation;
         FindFileIDFullDirectoryInfo    result = new FindFileIDFullDirectoryInfo();
         result.FileIndex          = fileIDFullDirectoryInfo.FileIndex;
         result.CreationTime       = fileIDFullDirectoryInfo.CreationTime;
         result.LastAccessTime     = fileIDFullDirectoryInfo.LastAccessTime;
         result.LastWriteTime      = fileIDFullDirectoryInfo.LastWriteTime;
         result.LastAttrChangeTime = fileIDFullDirectoryInfo.LastWriteTime;
         result.EndOfFile          = fileIDFullDirectoryInfo.EndOfFile;
         result.AllocationSize     = fileIDFullDirectoryInfo.AllocationSize;
         result.ExtFileAttributes  = (ExtendedFileAttributes)fileIDFullDirectoryInfo.FileAttributes;
         result.EASize             = fileIDFullDirectoryInfo.EaSize;
         result.Reserved           = fileIDFullDirectoryInfo.Reserved;
         result.FileID             = fileIDFullDirectoryInfo.FileId;
         result.FileName           = fileIDFullDirectoryInfo.FileName;
         return(result);
     }
     else if (fileInformation is FileIdBothDirectoryInformation)
     {
         FileIdBothDirectoryInformation fileIDBothDirectoryInfo = (FileIdBothDirectoryInformation)fileInformation;
         FindFileIDBothDirectoryInfo    result = new FindFileIDBothDirectoryInfo();
         result.FileIndex         = fileIDBothDirectoryInfo.FileIndex;
         result.CreationTime      = fileIDBothDirectoryInfo.CreationTime;
         result.LastAccessTime    = fileIDBothDirectoryInfo.LastAccessTime;
         result.LastWriteTime     = fileIDBothDirectoryInfo.LastWriteTime;
         result.LastChangeTime    = fileIDBothDirectoryInfo.LastWriteTime;
         result.EndOfFile         = fileIDBothDirectoryInfo.EndOfFile;
         result.AllocationSize    = fileIDBothDirectoryInfo.AllocationSize;
         result.ExtFileAttributes = (ExtendedFileAttributes)fileIDBothDirectoryInfo.FileAttributes;
         result.EASize            = fileIDBothDirectoryInfo.EaSize;
         result.Reserved          = fileIDBothDirectoryInfo.Reserved1;
         result.ShortName         = fileIDBothDirectoryInfo.ShortName;
         result.Reserved2         = fileIDBothDirectoryInfo.Reserved2;
         result.FileID            = fileIDBothDirectoryInfo.FileId;
         result.FileName          = fileIDBothDirectoryInfo.FileName;
         return(result);
     }
     else
     {
         throw new NotImplementedException();
     }
 }
Beispiel #8
0
        private IEnumerable <string> EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.EnumerateFileSystemEntries(path, searchPattern, searchOption));
            }

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\"");
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            if (credential == null)
            {
                credential = _credentialProvider.GetSMBCredential(path);
            }

            using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
            {
                var shareName    = path.ShareName();
                var relativePath = path.RelativeSharePath();

                ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                status.HandleStatus();

                status = fileStore.CreateFile(out object handle, out FileStatus fileStatus, relativePath, AccessMask.GENERIC_READ, 0, ShareAccess.Read,
                                              CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);

                status.HandleStatus();

                fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, searchPattern, FileInformationClass.FileDirectoryInformation);


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

                foreach (var file in queryDirectoryFileInformation)
                {
                    if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                    {
                        FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                        if (fileDirectoryInformation.FileName == "." || fileDirectoryInformation.FileName == ".." || fileDirectoryInformation.FileName == ".DS_Store")
                        {
                            continue;
                        }


                        if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory))
                        {
                            if (searchOption == SearchOption.AllDirectories)
                            {
                                files.AddRange(EnumerateFileSystemEntries(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName), searchPattern, searchOption, credential));
                            }
                        }

                        files.Add(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName));
                    }
                }
                fileStore.CloseFile(handle);

                return(files);
            }
        }
Beispiel #9
0
        public void Delete(string path, bool recursive, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                base.Delete(path, recursive);
                return;
            }

            if (recursive)
            {
                if (!path.TryResolveHostnameFromPath(out var ipAddress))
                {
                    throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\"");
                }

                NTStatus status = NTStatus.STATUS_SUCCESS;

                if (credential == null)
                {
                    credential = _credentialProvider.GetSMBCredential(path);
                }

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    var shareName    = path.ShareName();
                    var relativePath = path.RelativeSharePath();

                    ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                    status.HandleStatus();

                    int    attempts      = 0;
                    int    allowedRetrys = 3;
                    object handle;

                    do
                    {
                        attempts++;

                        status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, AccessMask.GENERIC_READ, 0, ShareAccess.Delete,
                                                      CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);
                    }while (status == NTStatus.STATUS_PENDING && attempts < allowedRetrys);

                    status.HandleStatus();

                    fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, "*", FileInformationClass.FileDirectoryInformation);

                    foreach (var file in queryDirectoryFileInformation)
                    {
                        if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                        {
                            FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                            if (fileDirectoryInformation.FileName == "." ||
                                fileDirectoryInformation.FileName == ".." ||
                                fileDirectoryInformation.FileName == ".DS_Store")
                            {
                                continue;
                            }
                            else if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory))
                            {
                                Delete(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName), recursive, credential);
                            }

                            _fileSystem.File.Delete(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName));
                        }
                    }
                    fileStore.CloseFile(handle);

                    Delete(path, credential);
                }
            }
            else
            {
                Delete(path);
            }
        }
Beispiel #10
0
        private static QueryDirectoryFileInformation FromFileSystemEntry(FileSystemEntry entry, FileInformationClass informationClass)
        {
            switch (informationClass)
            {
            case FileInformationClass.FileBothDirectoryInformation:
            {
                FileBothDirectoryInformation result = new FileBothDirectoryInformation();
                result.CreationTime   = entry.CreationTime;
                result.LastAccessTime = entry.LastAccessTime;
                result.LastWriteTime  = entry.LastWriteTime;
                result.ChangeTime     = entry.LastWriteTime;
                result.EndOfFile      = (long)entry.Size;
                result.AllocationSize = (long)GetAllocationSize(entry.Size);
                result.FileAttributes = GetFileAttributes(entry);
                result.EaSize         = 0;
                result.FileName       = entry.Name;
                return(result);
            }

            case FileInformationClass.FileDirectoryInformation:
            {
                FileDirectoryInformation result = new FileDirectoryInformation();
                result.CreationTime   = entry.CreationTime;
                result.LastAccessTime = entry.LastAccessTime;
                result.LastWriteTime  = entry.LastWriteTime;
                result.ChangeTime     = entry.LastWriteTime;
                result.EndOfFile      = (long)entry.Size;
                result.AllocationSize = (long)GetAllocationSize(entry.Size);
                result.FileAttributes = GetFileAttributes(entry);
                result.FileName       = entry.Name;
                return(result);
            }

            case FileInformationClass.FileFullDirectoryInformation:
            {
                FileFullDirectoryInformation result = new FileFullDirectoryInformation();
                result.CreationTime   = entry.CreationTime;
                result.LastAccessTime = entry.LastAccessTime;
                result.LastWriteTime  = entry.LastWriteTime;
                result.ChangeTime     = entry.LastWriteTime;
                result.EndOfFile      = (long)entry.Size;
                result.AllocationSize = (long)GetAllocationSize(entry.Size);
                result.FileAttributes = GetFileAttributes(entry);
                result.EaSize         = 0;
                result.FileName       = entry.Name;
                return(result);
            }

            case FileInformationClass.FileIdBothDirectoryInformation:
            {
                FileIdBothDirectoryInformation result = new FileIdBothDirectoryInformation();
                result.CreationTime   = entry.CreationTime;
                result.LastAccessTime = entry.LastAccessTime;
                result.LastWriteTime  = entry.LastWriteTime;
                result.ChangeTime     = entry.LastWriteTime;
                result.EndOfFile      = (long)entry.Size;
                result.AllocationSize = (long)GetAllocationSize(entry.Size);
                result.FileAttributes = GetFileAttributes(entry);
                result.EaSize         = 0;
                result.FileId         = 0;
                result.FileName       = entry.Name;
                return(result);
            }

            case FileInformationClass.FileIdFullDirectoryInformation:
            {
                FileIdFullDirectoryInformation result = new FileIdFullDirectoryInformation();
                result.CreationTime   = entry.CreationTime;
                result.LastAccessTime = entry.LastAccessTime;
                result.LastWriteTime  = entry.LastWriteTime;
                result.ChangeTime     = entry.LastWriteTime;
                result.EndOfFile      = (long)entry.Size;
                result.AllocationSize = (long)GetAllocationSize(entry.Size);
                result.FileAttributes = GetFileAttributes(entry);
                result.EaSize         = 0;
                result.FileId         = 0;
                result.FileName       = entry.Name;
                return(result);
            }

            case FileInformationClass.FileNamesInformation:
            {
                FileNamesInformation result = new FileNamesInformation();
                result.FileName = entry.Name;
                return(result);
            }

            default:
            {
                throw new UnsupportedInformationLevelException();
            }
            }
        }
Beispiel #11
0
        /// <exception cref="SMBLibrary.UnsupportedInformationLevelException"></exception>
        public static FindInformation GetFindInformation(QueryDirectoryFileInformation entry, FindInformationLevel informationLevel, bool isUnicode, bool returnResumeKeys)
        {
            switch (informationLevel)
            {
            case FindInformationLevel.SMB_FIND_FILE_DIRECTORY_INFO:
            {
                FileDirectoryInformation fileDirectoryInfo = (FileDirectoryInformation)entry;

                FindFileDirectoryInfo result = new FindFileDirectoryInfo();
                result.FileIndex          = fileDirectoryInfo.FileIndex;
                result.CreationTime       = fileDirectoryInfo.CreationTime;
                result.LastAccessTime     = fileDirectoryInfo.LastAccessTime;
                result.LastWriteTime      = fileDirectoryInfo.LastWriteTime;
                result.LastAttrChangeTime = fileDirectoryInfo.LastWriteTime;
                result.EndOfFile          = fileDirectoryInfo.EndOfFile;
                result.AllocationSize     = fileDirectoryInfo.AllocationSize;
                result.ExtFileAttributes  = (ExtendedFileAttributes)fileDirectoryInfo.FileAttributes;
                result.FileName           = fileDirectoryInfo.FileName;
                return(result);
            }

            case FindInformationLevel.SMB_FIND_FILE_FULL_DIRECTORY_INFO:
            {
                FileFullDirectoryInformation fileFullDirectoryInfo = (FileFullDirectoryInformation)entry;

                FindFileFullDirectoryInfo result = new FindFileFullDirectoryInfo();
                result.FileIndex          = fileFullDirectoryInfo.FileIndex;
                result.CreationTime       = fileFullDirectoryInfo.CreationTime;
                result.LastAccessTime     = fileFullDirectoryInfo.LastAccessTime;
                result.LastWriteTime      = fileFullDirectoryInfo.LastWriteTime;
                result.LastAttrChangeTime = fileFullDirectoryInfo.LastWriteTime;
                result.EndOfFile          = fileFullDirectoryInfo.EndOfFile;
                result.AllocationSize     = fileFullDirectoryInfo.AllocationSize;
                result.ExtFileAttributes  = (ExtendedFileAttributes)fileFullDirectoryInfo.FileAttributes;
                result.EASize             = fileFullDirectoryInfo.EaSize;
                result.FileName           = fileFullDirectoryInfo.FileName;
                return(result);
            }

            case FindInformationLevel.SMB_FIND_FILE_NAMES_INFO:
            {
                FileNamesInformation fileNamesInfo = (FileNamesInformation)entry;

                FindFileNamesInfo result = new FindFileNamesInfo();
                result.FileIndex = fileNamesInfo.FileIndex;
                result.FileName  = fileNamesInfo.FileName;
                return(result);
            }

            case FindInformationLevel.SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
            {
                FileBothDirectoryInformation fileBothDirectoryInfo = (FileBothDirectoryInformation)entry;

                FindFileBothDirectoryInfo result = new FindFileBothDirectoryInfo();
                result.FileIndex         = fileBothDirectoryInfo.FileIndex;
                result.CreationTime      = fileBothDirectoryInfo.CreationTime;
                result.LastAccessTime    = fileBothDirectoryInfo.LastAccessTime;
                result.LastWriteTime     = fileBothDirectoryInfo.LastWriteTime;
                result.LastChangeTime    = fileBothDirectoryInfo.LastWriteTime;
                result.EndOfFile         = fileBothDirectoryInfo.EndOfFile;
                result.AllocationSize    = fileBothDirectoryInfo.AllocationSize;
                result.ExtFileAttributes = (ExtendedFileAttributes)fileBothDirectoryInfo.FileAttributes;
                result.EASize            = fileBothDirectoryInfo.EaSize;
                result.Reserved          = fileBothDirectoryInfo.Reserved;
                result.ShortName         = fileBothDirectoryInfo.ShortName;
                result.FileName          = fileBothDirectoryInfo.FileName;
                return(result);
            }

            default:
            {
                throw new UnsupportedInformationLevelException();
            }
            }
        }
        public override bool Exists(string path)
        {
            if (!path.IsSharePath())
            {
                return(base.Exists(path));
            }

            // For some reason Directory.Exists is returning true if a file exists at that path.
            // File.Exists works properly so as long as we check it here we are fine.
            if (_fileSystem.File.Exists(path))
            {
                return(false);
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

            try
            {
                if (!path.TryResolveHostnameFromPath(out var ipAddress))
                {
                    throw new SMBException($"Failed to determine if {path} exists", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
                }

                NTStatus status = NTStatus.STATUS_SUCCESS;

                var credential = _credentialProvider.GetSMBCredential(path);

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    var shareName    = path.ShareName();
                    var relativePath = path.RelativeSharePath();

                    _logger?.LogTrace(
                        $"Trying to determine if {{RelativePath: {relativePath}}} Exists for {{ShareName: {shareName}}}");

                    if (string.IsNullOrEmpty(relativePath))
                    {
                        return(true);
                    }

                    var parentFullPath = path.GetParentPath();
                    var parentPath     = parentFullPath.RelativeSharePath();
                    var directoryName  = path.GetLastPathSegment().RemoveLeadingAndTrailingSeperators();

                    fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                    status.HandleStatus();

                    status = fileStore.CreateFile(out handle, out FileStatus fileStatus, parentPath, AccessMask.GENERIC_READ, 0, ShareAccess.Read,
                                                  CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);

                    status.HandleStatus();

                    fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(directoryName) ? "*" : directoryName, FileInformationClass.FileDirectoryInformation);

                    foreach (var file in queryDirectoryFileInformation)
                    {
                        if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                        {
                            FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                            if (fileDirectoryInformation.FileName == directoryName)
                            {
                                return(true);
                            }
                        }
                    }
                }

                return(false);
            }
            catch (Exception ex)
            {
                _logger?.LogTrace(ex, $"Failed to determine if {path} exists.");
                return(false);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
        private IEnumerable <string> EnumerateFiles(string path, string searchPattern, SearchOption searchOption, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.EnumerateFiles(path, searchPattern, searchOption));
            }

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed to EnumerateFiles for {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            if (credential == null)
            {
                credential = _credentialProvider.GetSMBCredential(path);
            }

            if (credential == null)
            {
                throw new SMBException($"Failed to EnumerateFiles for {path}", new InvalidCredentialException($"Unable to find credential in SMBCredentialProvider for path: {path}"));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

            try
            {
                var shareName    = path.ShareName();
                var relativePath = path.RelativeSharePath();

                _logger?.LogTrace($"Trying to EnumerateFiles for {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}");

                using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                {
                    fileStore = connection.SMBClient.TreeConnect(shareName, out status);

                    status.HandleStatus();

                    status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, AccessMask.GENERIC_READ, 0, ShareAccess.Read,
                                                  CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);

                    status.HandleStatus();

                    fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, searchPattern, FileInformationClass.FileDirectoryInformation);

                    _logger?.LogTrace($"Found {queryDirectoryFileInformation.Count} FileDirectoryInformation for {path}");

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

                    foreach (var file in queryDirectoryFileInformation)
                    {
                        if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                        {
                            FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                            if (fileDirectoryInformation.FileName == "." ||
                                fileDirectoryInformation.FileName == ".." ||
                                fileDirectoryInformation.FileName == ".DS_Store")
                            {
                                continue;
                            }

                            if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory))
                            {
                                if (searchOption == SearchOption.AllDirectories)
                                {
                                    files.AddRange(EnumerateFiles(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName), searchPattern, searchOption, credential));
                                }
                            }
                            else
                            {
                                files.Add(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName.RemoveLeadingAndTrailingSeperators()));
                            }
                        }
                    }
                    FileStoreUtilities.CloseFile(fileStore, ref handle);

                    return(files);
                }
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed to EnumerateFiles {path}", ex);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
        public void Delete(string path, bool recursive, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                base.Delete(path, recursive);
                return;
            }

            if (recursive)
            {
                if (!path.TryResolveHostnameFromPath(out var ipAddress))
                {
                    throw new SMBException($"Failed to Delete {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
                }

                if (credential == null)
                {
                    credential = _credentialProvider.GetSMBCredential(path);
                }

                if (credential == null)
                {
                    throw new SMBException($"Failed to Delete {path}", new InvalidCredentialException("Unable to find credential in SMBCredentialProvider for path: {path}"));
                }

                ISMBFileStore fileStore = null;
                object        handle    = null;

                try
                {
                    var shareName    = path.ShareName();
                    var relativePath = path.RelativeSharePath();

                    _logger?.LogTrace($"Trying to Delete {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}");

                    using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize))
                    {
                        fileStore = connection.SMBClient.TreeConnect(shareName, out var status);

                        status.HandleStatus();

                        AccessMask        accessMask    = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ;
                        ShareAccess       shareAccess   = ShareAccess.Delete;
                        CreateDisposition disposition   = CreateDisposition.FILE_OPEN;
                        CreateOptions     createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DIRECTORY_FILE;

                        var stopwatch = new Stopwatch();

                        stopwatch.Start();
                        do
                        {
                            if (status == NTStatus.STATUS_PENDING)
                            {
                                _logger.LogTrace($"STATUS_PENDING while trying to delete directory {path}. {stopwatch.Elapsed.TotalSeconds}/{_smbFileSystemSettings.ClientSessionTimeout} seconds elapsed.");
                            }

                            status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess,
                                                          disposition, createOptions, null);
                        } while (status == NTStatus.STATUS_PENDING && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout);

                        stopwatch.Stop();

                        status.HandleStatus();

                        fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, "*", FileInformationClass.FileDirectoryInformation);

                        foreach (var file in queryDirectoryFileInformation)
                        {
                            if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation)
                            {
                                FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file;
                                if (fileDirectoryInformation.FileName == "." ||
                                    fileDirectoryInformation.FileName == ".." ||
                                    fileDirectoryInformation.FileName == ".DS_Store")
                                {
                                    continue;
                                }
                                else if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory))
                                {
                                    Delete(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName), recursive, credential);
                                }

                                _fileSystem.File.Delete(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName));
                            }
                        }

                        FileStoreUtilities.CloseFile(fileStore, ref handle);

                        Delete(path, credential);
                    }
                }
                catch (Exception ex)
                {
                    throw new SMBException($"Failed to Delete {path}", ex);
                }
                finally
                {
                    FileStoreUtilities.CloseFile(fileStore, ref handle);
                }
            }
            else
            {
                Delete(path);
            }
        }