Exemplo n.º 1
0
        internal SMBFileInfo(string path,
                             IFileSystem fileSystem,
                             FileBasicInformation fileBasicInformation,
                             FileStandardInformation fileStandardInformation,
                             ISMBCredential credential) : this(path, fileSystem)
        {
            if (fileBasicInformation.CreationTime.Time.HasValue)
            {
                _creationTime    = fileBasicInformation.CreationTime.Time.Value;
                _creationTimeUtc = CreationTime.ToUniversalTime();
            }
            if (fileBasicInformation.LastAccessTime.Time.HasValue)
            {
                _lastAccessTime    = fileBasicInformation.LastAccessTime.Time.Value;
                _lastAccessTimeUtc = LastAccessTime.ToUniversalTime();
            }
            if (fileBasicInformation.LastWriteTime.Time.HasValue)
            {
                _lastWriteTime    = fileBasicInformation.LastWriteTime.Time.Value;
                _lastWriteTimeUtc = LastWriteTime.ToUniversalTime();
            }

            _attributes = (System.IO.FileAttributes)fileBasicInformation.FileAttributes;

            var parentPath = _fileSystem.Path.GetDirectoryName(path);


            _directory     = _dirInfoFactory.FromDirectoryName(parentPath, credential);
            _directoryName = parentPath;
            _exists        = _file.Exists(path);
            _isReadOnly    = fileBasicInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.ReadOnly);
            _length        = fileStandardInformation.EndOfFile;
        }
Exemplo n.º 2
0
 public void AddSMBCredential(ISMBCredential credential)
 {
     lock (_credentialsLock)
     {
         credentials.Add(credential);
     }
 }
Exemplo n.º 3
0
        internal SMBFileInfo(string path,
                             IFileSystem fileSystem,
                             FileBasicInformation fileBasicInformation,
                             FileStandardInformation fileStandardInformation,
                             ISMBCredential credential) : this(path, fileSystem)
        {
            if (fileBasicInformation.CreationTime.Time.HasValue)
            {
                _creationTime    = fileBasicInformation.CreationTime.Time.Value;
                _creationTimeUtc = CreationTime.ToUniversalTime();
            }
            if (fileBasicInformation.LastAccessTime.Time.HasValue)
            {
                _lastAccessTime    = fileBasicInformation.LastAccessTime.Time.Value;
                _lastAccessTimeUtc = LastAccessTime.ToUniversalTime();
            }
            if (fileBasicInformation.LastWriteTime.Time.HasValue)
            {
                _lastWriteTime    = fileBasicInformation.LastWriteTime.Time.Value;
                _lastWriteTimeUtc = LastWriteTime.ToUniversalTime();
            }

            _attributes = (System.IO.FileAttributes)fileBasicInformation.FileAttributes;

            var pathUri          = new Uri(path);
            var parentUri        = pathUri.AbsoluteUri.EndsWith('/') ? new Uri(pathUri, "..") : new Uri(pathUri, ".");
            var parentPathString = parentUri.IsUnc ? parentUri.LocalPath : parentUri.AbsoluteUri;

            _directory     = _dirInfoFactory.FromDirectoryName(parentPathString, credential);
            _directoryName = Directory?.Name;
            _exists        = _file.Exists(path);
            _isReadOnly    = fileBasicInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.ReadOnly);
            _length        = fileStandardInformation.EndOfFile;
        }
        internal IDriveInfo FromDriveName(string shareName, ISMBCredential credential)
        {
            if (credential == null)
            {
                credential = _smbCredentialProvider.GetSMBCredentials().Where(c => c.Path.ShareName().Equals(shareName)).FirstOrDefault();

                if (credential == null)
                {
                    return(null);
                }
            }

            var path = credential.Path;

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

            NTStatus status = NTStatus.STATUS_SUCCESS;

            using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

            var relativePath = path.RelativeSharePath();

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

            status.HandleStatus();

            var smbFileSystemInformation = new SMBFileSystemInformation(fileStore, path, status);

            var smbDriveInfo = new SMBDriveInfo(path, _fileSystem, smbFileSystemInformation, credential);

            return(smbDriveInfo);
        }
Exemplo n.º 5
0
 public void RemoveSMBCredential(ISMBCredential credential)
 {
     lock (_credentialsLock)
     {
         credentials.Remove(credential);
     }
 }
Exemplo n.º 6
0
        private void Move(string sourceDirName, string destDirName, ISMBCredential sourceCredential, ISMBCredential destinationCredential)
        {
            if (sourceCredential == null)
            {
                sourceCredential = _credentialProvider.GetSMBCredential(sourceDirName);
            }

            if (destinationCredential == null)
            {
                destinationCredential = _credentialProvider.GetSMBCredential(destDirName);
            }

            CreateDirectory(destDirName, destinationCredential);

            var dirs = EnumerateDirectories(sourceDirName, "*", SearchOption.TopDirectoryOnly, sourceCredential);

            foreach (var dir in dirs)
            {
                var destDirPath = _fileSystem.Path.Combine(destDirName, new Uri(dir).Segments.Last());
                Move(dir, destDirPath, sourceCredential, destinationCredential);
            }

            var files = EnumerateFiles(sourceDirName, "*", SearchOption.TopDirectoryOnly, sourceCredential);

            foreach (var file in files)
            {
                var     destFilePath = _fileSystem.Path.Combine(destDirName, new Uri(file).Segments.Last());
                SMBFile smbFile      = _fileSystem.File as SMBFile;
                smbFile.Move(file, destFilePath, sourceCredential, destinationCredential);
            }
        }
Exemplo n.º 7
0
        internal IDirectoryInfo GetParent(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.GetParent(path));
            }

            return(_directoryInfoFactory.FromDirectoryName(path.GetParentPath(), credential));
        }
Exemplo n.º 8
0
        private Stream Open(string path, FileMode mode, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.Open(path, mode));
            }

            return(Open(path, mode, FileAccess.ReadWrite, credential));
        }
Exemplo n.º 9
0
        private Stream Open(string path, FileMode mode, FileAccess access, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.Open(path, mode, access));
            }

            return(Open(path, mode, access, FileShare.None, credential));
        }
Exemplo n.º 10
0
        private Stream OpenRead(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.OpenRead(path));
            }

            return(Open(path, FileMode.Open, FileAccess.Read, credential));
        }
Exemplo n.º 11
0
        private Stream OpenWrite(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.OpenWrite(path));
            }

            return(Open(path, FileMode.OpenOrCreate, FileAccess.Write, credential));
        }
Exemplo n.º 12
0
        internal void SaveDirectoryInfo(SMBDirectoryInfo dirInfo, ISMBCredential credential = null)
        {
            var path = dirInfo.FullName;

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed to SaveDirectoryInfo 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 SaveDirectoryInfo for {path}", new InvalidCredentialException($"Unable to find credential for path: {path}"));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

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

                _logger?.LogTrace($"Trying to SaveDirectoryInfo {{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_WRITE, 0, ShareAccess.Read,
                                              CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);

                status.HandleStatus();

                var fileInfo = dirInfo.ToSMBFileInformation(credential);
                status = fileStore.SetFileInformation(handle, fileInfo);

                status.HandleStatus();
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed to SaveDirectoryInfo for {path}", ex);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
Exemplo n.º 13
0
 private SMBConnection(ISMBClientFactory smbClientFactory, IPAddress address, SMBTransportType transport,
                       ISMBCredential credential, int threadId, uint maxBufferSize)
 {
     SMBClient       = smbClientFactory.CreateClient(maxBufferSize);
     _address        = address;
     _transport      = transport;
     _credential     = credential;
     _referenceCount = 1;
     _threadId       = threadId;
 }
Exemplo n.º 14
0
 internal void Move(string sourceFileName, string destFileName, ISMBCredential sourceCredential, ISMBCredential destinationCredential)
 {
     using (Stream sourceStream = OpenRead(sourceFileName, sourceCredential))
     {
         using (Stream destStream = OpenWrite(destFileName, destinationCredential))
         {
             sourceStream.CopyTo(destStream, Convert.ToInt32(_maxBufferSize));
         }
     }
 }
Exemplo n.º 15
0
        internal void Delete(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                base.Delete(path);
                return;
            }

            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);
            }

            if (EnumerateFileSystemEntries(path).Count() > 0)
            {
                throw new IOException("Cannot delete directory. Directory is not empty.");
            }

            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.DELETE, 0, ShareAccess.Delete,
                                                  CreateDisposition.FILE_OPEN, CreateOptions.FILE_DELETE_ON_CLOSE, null);
                }while (status == NTStatus.STATUS_PENDING && attempts < allowedRetrys);

                status.HandleStatus();

                // This is the correct delete command, but it doesn't work for some reason. You have to use FILE_DELETE_ON_CLOSE
                // fileStore.SetFileInformation(handle, new FileDispositionInformation());

                fileStore.CloseFile(handle);
            }
        }
Exemplo n.º 16
0
 private void ValidateCredential(ISMBCredential credential)
 {
     if (credential.Domain == null)
     {
         throw new InvalidCredentialException($"SMB credential is not valid. {nameof(credential.Domain)} cannot be null.");
     }
     else if (credential.UserName == null)
     {
         throw new InvalidCredentialException($"SMB credential is not valid. {nameof(credential.UserName)} cannot be null.");
     }
     else if (credential.Password == null)
     {
         throw new InvalidCredentialException($"SMB credential is not valid. {nameof(credential.Password)} cannot be null.");
     }
 }
        internal IDirectoryInfo FromDirectoryName(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath() || !path.IsValidSharePath())
            {
                return(null);
            }

            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);
            }

            if (credential == null)
            {
                throw new Exception($"Unable to find credential for path: {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();

            status = fileStore.GetFileInformation(out FileInformation fileInfo, handle, FileInformationClass.FileBasicInformation); // If you call this with any other FileInformationClass value
                                                                                                                                    // it doesn't work for some reason
            if (status != NTStatus.STATUS_SUCCESS)
            {
                return(null);
            }

            return(new SMBDirectoryInfo(path, fileInfo, _fileSystem, _credentialProvider, credential));
        }
Exemplo n.º 18
0
        internal SMBDirectoryInfo(string fileName,
                                  FileInformation fileInfo,
                                  IFileSystem fileSystem,
                                  ISMBCredentialProvider credentialProvider,
                                  ISMBCredential credential) : this(fileName, fileSystem, credentialProvider)
        {
            FileBasicInformation fileDirectoryInformation = (FileBasicInformation)fileInfo;

            if (fileDirectoryInformation.CreationTime.Time.HasValue)
            {
                _creationTime    = fileDirectoryInformation.CreationTime.Time.Value;
                _creationTimeUtc = CreationTime.ToUniversalTime();
            }
            if (fileDirectoryInformation.LastAccessTime.Time.HasValue)
            {
                _lastAccessTime    = fileDirectoryInformation.LastAccessTime.Time.Value;
                _lastAccessTimeUtc = LastAccessTime.ToUniversalTime();
            }
            if (fileDirectoryInformation.LastWriteTime.Time.HasValue)
            {
                _lastWriteTime    = fileDirectoryInformation.LastWriteTime.Time.Value;
                _lastWriteTimeUtc = LastWriteTime.ToUniversalTime();
            }

            _parent     = _smbDirectory.GetParent(fileName, credential);
            _fileSystem = fileSystem;
            var pathRoot = _fileSystem.Path.GetPathRoot(fileName);

            if (pathRoot != fileName)
            {
                _root = _directoryInfoFactory.FromDirectoryName(pathRoot, credential);
            }
            else
            {
                _root = this;
            }

            _exists    = _fileSystem.Directory.Exists(FullName);
            _extension = string.Empty;
            _name      = _fullName.GetLastPathSegment().RemoveLeadingAndTrailingSeperators();
        }
        internal void SaveDirectoryInfo(SMBDirectoryInfo dirInfo, ISMBCredential credential = null)
        {
            var path = dirInfo.FullName;

            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);
            }

            if (credential == null)
            {
                throw new Exception($"Unable to find credential for path: {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_WRITE, 0, ShareAccess.Read,
                                          CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null);

            status.HandleStatus();

            var fileInfo = dirInfo.ToSMBFileInformation(credential);

            status = fileStore.SetFileInformation(handle, fileInfo);

            status.HandleStatus();
        }
Exemplo n.º 20
0
        internal Stream Open(string path, FileMode mode, FileAccess access, FileShare share, FileOptions fileOptions, ISMBCredential credential)
        {
            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\"");
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            AccessMask        accessMask  = AccessMask.MAXIMUM_ALLOWED;
            ShareAccess       shareAccess = ShareAccess.None;
            CreateDisposition disposition = CreateDisposition.FILE_OPEN;
            CreateOptions     createOptions;

            switch (fileOptions)
            {
            case FileOptions.DeleteOnClose:
                createOptions = CreateOptions.FILE_DELETE_ON_CLOSE;
                break;

            case FileOptions.RandomAccess:
                createOptions = CreateOptions.FILE_RANDOM_ACCESS;
                break;

            case FileOptions.SequentialScan:
                createOptions = CreateOptions.FILE_SEQUENTIAL_ONLY;
                break;

            case FileOptions.WriteThrough:
                createOptions = CreateOptions.FILE_WRITE_THROUGH;
                break;

            case FileOptions.None:
            case FileOptions.Encrypted:         // These two are not suported unless I am missing something
            case FileOptions.Asynchronous:      //
            default:
                createOptions = CreateOptions.FILE_NON_DIRECTORY_FILE;
                break;
            }

            switch (access)
            {
            case FileAccess.Read:
                accessMask  = AccessMask.GENERIC_READ;
                shareAccess = ShareAccess.Read;
                break;

            case FileAccess.Write:
                accessMask  = AccessMask.GENERIC_WRITE;
                shareAccess = ShareAccess.Write;
                break;

            case FileAccess.ReadWrite:
                accessMask  = AccessMask.GENERIC_ALL;
                shareAccess = ShareAccess.Write;
                break;
            }

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

            if (credential == null)
            {
                throw new Exception($"Unable to find credential for path: {path}");
            }

            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();

            switch (mode)
            {
            case FileMode.Create:
                disposition = CreateDisposition.FILE_CREATE;
                break;

            case FileMode.CreateNew:
                disposition = CreateDisposition.FILE_OVERWRITE;
                break;

            case FileMode.Open:
                disposition = CreateDisposition.FILE_OPEN;
                break;

            case FileMode.OpenOrCreate:
                disposition = Exists(path) ? CreateDisposition.FILE_OPEN : CreateDisposition.FILE_CREATE;
                break;
            }

            int getInfoAttempts      = 0;
            int getInfoAllowedRetrys = 5;

            object          handle;
            FileInformation fileInfo;

            do
            {
                getInfoAttempts++;
                int openAttempts      = 0;
                int openAllowedRetrys = 5;

                do
                {
                    openAttempts++;

                    status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess,
                                                  disposition, createOptions, null);
                }while (status == NTStatus.STATUS_PENDING && openAttempts < openAllowedRetrys);

                status.HandleStatus();
                status = fileStore.GetFileInformation(out fileInfo, handle, FileInformationClass.FileStandardInformation);
            }while (status == NTStatus.STATUS_NETWORK_NAME_DELETED && getInfoAttempts < getInfoAllowedRetrys);

            status.HandleStatus();

            var fileStandardInfo = (FileStandardInformation)fileInfo;

            Stream s = new SMBStream(fileStore, handle, connection, fileStandardInfo.EndOfFile);

            if (mode == FileMode.Append)
            {
                s.Seek(0, SeekOrigin.End);
            }

            return(s);
        }
Exemplo n.º 21
0
        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);
            }
        }
Exemplo n.º 22
0
        internal IFileInfo FromFileName(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(null);
            }

            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed FromFileName 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 FromFileName for {path}", new InvalidCredentialException($"Unable to find credential for path: {path}"));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

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

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

                using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

                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_NON_DIRECTORY_FILE;

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

                status.HandleStatus();

                status = fileStore.GetFileInformation(out FileInformation fileBasicInfo, handle, FileInformationClass.FileBasicInformation);
                status.HandleStatus();
                status = fileStore.GetFileInformation(out FileInformation fileStandardInfo, handle, FileInformationClass.FileStandardInformation);
                status.HandleStatus();

                FileStoreUtilities.CloseFile(fileStore, ref handle);

                return(new SMBFileInfo(path, _fileSystem, (FileBasicInformation)fileBasicInfo, (FileStandardInformation)fileStandardInfo, credential));
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed FromFileName for {path}", ex);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
Exemplo n.º 23
0
        internal Stream Open(string path, FileMode mode, FileAccess access, FileShare share, FileOptions fileOptions, ISMBCredential credential)
        {
            if (!path.TryResolveHostnameFromPath(out var ipAddress))
            {
                throw new SMBException($"Failed to Open {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            AccessMask        accessMask  = AccessMask.MAXIMUM_ALLOWED;
            ShareAccess       shareAccess = ShareAccess.None;
            CreateDisposition disposition = CreateDisposition.FILE_OPEN;
            CreateOptions     createOptions;

            switch (fileOptions)
            {
            case FileOptions.DeleteOnClose:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DELETE_ON_CLOSE;
                break;

            case FileOptions.RandomAccess:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_RANDOM_ACCESS;
                break;

            case FileOptions.SequentialScan:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_SEQUENTIAL_ONLY;
                break;

            case FileOptions.WriteThrough:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_WRITE_THROUGH;
                break;

            case FileOptions.None:
            case FileOptions.Encrypted:         // These two are not suported unless I am missing something
            case FileOptions.Asynchronous:      //
            default:
                createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_NON_DIRECTORY_FILE;
                break;
            }

            switch (access)
            {
            case FileAccess.Read:
                accessMask  = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ;
                shareAccess = ShareAccess.Read;
                break;

            case FileAccess.Write:
                accessMask  = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_WRITE;
                shareAccess = ShareAccess.Write;
                break;

            case FileAccess.ReadWrite:
                accessMask  = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE;
                shareAccess = ShareAccess.Read | ShareAccess.Write;
                break;
            }

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

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

            SMBConnection connection = null;

            try
            {
                connection = SMBConnection.CreateSMBConnectionForStream(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

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

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

                status.HandleStatus();

                switch (mode)
                {
                case FileMode.Create:
                    disposition = CreateDisposition.FILE_OVERWRITE_IF;
                    break;

                case FileMode.CreateNew:
                    disposition = CreateDisposition.FILE_CREATE;
                    break;

                case FileMode.Open:
                    disposition = CreateDisposition.FILE_OPEN;
                    break;

                case FileMode.OpenOrCreate:
                    disposition = CreateDisposition.FILE_OPEN_IF;
                    break;
                }

                object handle;
                var    stopwatch = new Stopwatch();

                stopwatch.Start();
                do
                {
                    if (status == NTStatus.STATUS_PENDING)
                    {
                        _logger.LogTrace($"STATUS_PENDING while trying to open file {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();

                FileInformation fileInfo;

                stopwatch.Reset();
                stopwatch.Start();
                do
                {
                    status = fileStore.GetFileInformation(out fileInfo, handle, FileInformationClass.FileStandardInformation);
                }while (status == NTStatus.STATUS_NETWORK_NAME_DELETED && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout);
                stopwatch.Stop();

                status.HandleStatus();

                var fileStandardInfo = (FileStandardInformation)fileInfo;

                Stream s = new SMBStream(fileStore, handle, connection, fileStandardInfo.EndOfFile, _smbFileSystemSettings);

                if (mode == FileMode.Append)
                {
                    s.Seek(0, SeekOrigin.End);
                }

                return(s);
            }
            catch (Exception ex)
            {
                // Dispose connection if fail to open stream
                connection?.Dispose();
                throw new SMBException($"Failed to Open {path}", ex);
            }
        }
Exemplo n.º 24
0
        public static SMBConnection CreateSMBConnection(ISMBClientFactory smbClientFactory,
                                                        IPAddress address, SMBTransportType transport, ISMBCredential credential, uint maxBufferSize)
        {
            var threadId = Thread.CurrentThread.ManagedThreadId;

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

            lock (_connectionLock)
            {
                if (!instances.ContainsKey(threadId))
                {
                    instances.Add(threadId, new Dictionary <IPAddress, SMBConnection>());
                }

                if (instances[threadId].ContainsKey(address))
                {
                    var instance = instances[threadId][address];
                    instance._referenceCount += 1;
                    return(instance);
                }
                else
                {
                    var instance = new SMBConnection(smbClientFactory, address, transport, credential, threadId, maxBufferSize);
                    instance.Connect();
                    instances[threadId].Add(address, instance);
                    return(instance);
                }
            }
        }
Exemplo n.º 25
0
        public static SMBConnection CreateSMBConnectionForStream(ISMBClientFactory smbClientFactory,
                                                                 IPAddress address, SMBTransportType transport, ISMBCredential credential, uint maxBufferSize)
        {
            if (credential == null)
            {
                throw new ArgumentNullException(nameof(credential));
            }

            // Create new connection
            var instance = new SMBConnection(smbClientFactory, address, transport, credential, -1,
                                             maxBufferSize);

            instance.Connect();
            return(instance);
        }
Exemplo n.º 26
0
        public SMBDriveInfo(string path, IFileSystem fileSystem, SMBFileSystemInformation smbFileSystemInformation, ISMBCredential credential)
        {
            FileSystem    = fileSystem;
            DriveFormat   = smbFileSystemInformation.AttributeInformation.FileSystemName;
            Name          = path.ShareName();
            RootDirectory = _dirInfoFactory.FromDirectoryName(path, credential);
            var actualAvailableAllocationUnits = smbFileSystemInformation.SizeInformation.ActualAvailableAllocationUnits;
            var sectorsPerUnit           = smbFileSystemInformation.SizeInformation.SectorsPerAllocationUnit;
            var bytesPerSector           = smbFileSystemInformation.SizeInformation.BytesPerSector;
            var totalAllocationUnits     = smbFileSystemInformation.SizeInformation.TotalAllocationUnits;
            var availableAllocationUnits = smbFileSystemInformation.SizeInformation.CallerAvailableAllocationUnits;

            AvailableFreeSpace = availableAllocationUnits * sectorsPerUnit * bytesPerSector;
            TotalFreeSpace     = actualAvailableAllocationUnits * sectorsPerUnit * bytesPerSector;
            TotalSize          = totalAllocationUnits * sectorsPerUnit * bytesPerSector;
            _volumeLabel       = smbFileSystemInformation.VolumeInformation.VolumeLabel;
        }
        internal IDriveInfo[] GetDrives(ISMBCredential smbCredential)
        {
            var credentialsToCheck = new List <ISMBCredential>();

            credentialsToCheck = _smbCredentialProvider.GetSMBCredentials().ToList();

            List <IDriveInfo> driveInfos = new List <IDriveInfo>();

            if (smbCredential == null && credentialsToCheck.Count == 0)
            {
                _logger?.LogTrace($"No provided credentials and no credentials stored credentials in SMBCredentialProvider.");
                return(driveInfos.ToArray());
            }

            NTStatus status = NTStatus.STATUS_SUCCESS;

            var shareHostNames = new List <string>();

            if (smbCredential != null)
            {
                credentialsToCheck.Add(smbCredential);
            }
            else
            {
                credentialsToCheck = _smbCredentialProvider.GetSMBCredentials().ToList();
            }

            shareHostNames = credentialsToCheck.Select(smbCredential => smbCredential.Path.Hostname()).Distinct().ToList();

            var shareHostShareNames = new Dictionary <string, IEnumerable <string> >();

            foreach (var shareHost in shareHostNames)
            {
                var credential = credentialsToCheck.Where(smbCredential => smbCredential.Path.Hostname().Equals(shareHost)).First();
                try
                {
                    var path = credential.Path;
                    if (!path.TryResolveHostnameFromPath(out var ipAddress))
                    {
                        throw new SMBException($"Failed to connect to {path.Hostname()}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\""));
                    }

                    using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize);

                    var shareNames = connection.SMBClient.ListShares(out status);
                    var shareDirectoryInfoFactory = new SMBDirectoryInfoFactory(_fileSystem, _smbCredentialProvider, _smbClientFactory, _maxBufferSize);

                    foreach (var shareName in shareNames)
                    {
                        var sharePath         = path.BuildSharePath(shareName);
                        var relativeSharePath = sharePath.RelativeSharePath();

                        _logger?.LogTrace($"Trying to get drive info for {shareName}");

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

                            status.HandleStatus();

                            var smbFileSystemInformation = new SMBFileSystemInformation(fileStore, sharePath, status);

                            var smbDriveInfo = new SMBDriveInfo(sharePath, _fileSystem, smbFileSystemInformation, credential);

                            driveInfos.Add(smbDriveInfo);
                        }
                        catch (IOException ioEx)
                        {
                            _logger?.LogTrace(ioEx, $"Failed to get drive info for {shareName}");
                            throw new SMBException($"Failed to get drive info for {shareName}", new AggregateException($"Unable to connect to {shareName}", ioEx));
                        }
                        catch (Exception ex)
                        {
                            _logger?.LogTrace(ex, $"Failed to get drive info for {shareName}");
                            continue;
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger?.LogTrace(ex, $"Failed to GetDrives for {shareHost}.");
                    continue;
                }
            }

            return(driveInfos.ToArray());
        }
Exemplo n.º 28
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);
            }
        }
Exemplo n.º 29
0
        private IDirectoryInfo CreateDirectory(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.CreateDirectory(path));
            }

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

            NTStatus status = NTStatus.STATUS_SUCCESS;

            AccessMask        accessMask    = AccessMask.MAXIMUM_ALLOWED;
            ShareAccess       shareAccess   = ShareAccess.Read;
            CreateDisposition disposition   = CreateDisposition.FILE_OPEN_IF;
            CreateOptions     createOptions = CreateOptions.FILE_DIRECTORY_FILE;

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

            if (credential == null)
            {
                throw new Exception($"Unable to find credential for path: {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, 0, shareAccess,
                                              disposition, createOptions, null);

                if (status == NTStatus.STATUS_OBJECT_PATH_NOT_FOUND)
                {
                    CreateDirectory(path.GetParentPath(), credential);
                    status = fileStore.CreateFile(out handle, out fileStatus, relativePath, accessMask, 0, shareAccess,
                                                  disposition, createOptions, null);
                }
            }while (status == NTStatus.STATUS_PENDING && attempts < allowedRetrys);

            status.HandleStatus();

            fileStore.CloseFile(handle);

            return(_directoryInfoFactory.FromDirectoryName(path, credential));
        }
Exemplo n.º 30
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);
            }
        }