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));
        }
Beispiel #2
0
        public override void Delete(string path)
        {
            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;

            var credential = _credentialProvider.GetSMBCredential(path);

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

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

                status.HandleStatus();

                // There should be a seperate option to delete, but it doesn't seem to exsist in the library we are using, so this should work for now. Really hacky though.
                fileStore.CloseFile(handle);
            }
        }
        internal IDriveInfo FromDriveName(string shareName, ISMBCredential credential)
        {
            if (credential == null)
            {
                if (shareName.IsValidSharePath())
                {
                    credential = _smbCredentialProvider.GetSMBCredential(shareName);
                    shareName  = shareName.ShareName();
                }
                else
                {
                    credential = _smbCredentialProvider.GetSMBCredentials().Where(c => c.Path.ShareName().Equals(shareName)).FirstOrDefault();
                }

                if (credential == null)
                {
                    _logger?.LogTrace($"Unable to find credential in SMBCredentialProvider for path: {shareName}");
                    return(null);
                }
            }

            var path = credential.Path;

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

            NTStatus status = NTStatus.STATUS_SUCCESS;

            try
            {
                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);
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed FromDriveName for {shareName}", ex);
            }
        }
Beispiel #4
0
        public override void Delete(string path)
        {
            if (!path.IsSharePath())
            {
                base.Delete(path);
                return;
            }

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

            var 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.DELETE;
                    ShareAccess       shareAccess   = ShareAccess.Read | ShareAccess.Delete;
                    CreateDisposition disposition   = CreateDisposition.FILE_OPEN;
                    CreateOptions     createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DELETE_ON_CLOSE;

                    var stopwatch = new Stopwatch();
                    stopwatch.Start();

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

                    // There should be a seperate option to delete, but it doesn't seem to exsist in the library we are using, so this should work for now. Really hacky though.
                    FileStoreUtilities.CloseFile(fileStore, ref handle);
                }
            }
            catch (Exception ex)
            {
                throw new SMBException($"Failed to Delete {path}", ex);
            }
            finally
            {
                FileStoreUtilities.CloseFile(fileStore, ref handle);
            }
        }
Beispiel #5
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));
        }
Beispiel #6
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);
            }
        }
        private IDirectoryInfo CreateDirectory(string path, ISMBCredential credential)
        {
            if (!path.IsSharePath())
            {
                return(base.CreateDirectory(path));
            }

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

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

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

            if (Exists(path))
            {
                return(_directoryInfoFactory.FromDirectoryName(path));
            }

            ISMBFileStore fileStore = null;
            object        handle    = null;

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

                _logger?.LogTrace($"Trying to CreateDirectory {{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.MAXIMUM_ALLOWED;
                ShareAccess       shareAccess   = ShareAccess.Read | ShareAccess.Write;
                CreateDisposition disposition   = CreateDisposition.FILE_OPEN_IF;
                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 create directory {path}. {stopwatch.Elapsed.TotalSeconds}/{_smbFileSystemSettings.ClientSessionTimeout} seconds elapsed.");
                    }

                    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 && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout);

                stopwatch.Stop();

                status.HandleStatus();

                FileStoreUtilities.CloseFile(fileStore, ref handle);

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