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; }
public void AddSMBCredential(ISMBCredential credential) { lock (_credentialsLock) { credentials.Add(credential); } }
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); }
public void RemoveSMBCredential(ISMBCredential credential) { lock (_credentialsLock) { credentials.Remove(credential); } }
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); } }
internal IDirectoryInfo GetParent(string path, ISMBCredential credential) { if (!path.IsSharePath()) { return(base.GetParent(path)); } return(_directoryInfoFactory.FromDirectoryName(path.GetParentPath(), credential)); }
private Stream Open(string path, FileMode mode, ISMBCredential credential) { if (!path.IsSharePath()) { return(base.Open(path, mode)); } return(Open(path, mode, FileAccess.ReadWrite, credential)); }
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)); }
private Stream OpenRead(string path, ISMBCredential credential) { if (!path.IsSharePath()) { return(base.OpenRead(path)); } return(Open(path, FileMode.Open, FileAccess.Read, credential)); }
private Stream OpenWrite(string path, ISMBCredential credential) { if (!path.IsSharePath()) { return(base.OpenWrite(path)); } return(Open(path, FileMode.OpenOrCreate, FileAccess.Write, credential)); }
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); } }
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; }
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)); } } }
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); } }
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)); }
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(); }
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); }
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); } }
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); } }
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); } }
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); } } }
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); }
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()); }
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); } }
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)); }
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); } }