public override bool Exists(string path) { if (!path.IsSharePath()) { return(base.Exists(path)); } try { if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\""); } NTStatus status = NTStatus.STATUS_SUCCESS; var credential = _credentialProvider.GetSMBCredential(path); using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize)) { var shareName = path.ShareName(); var directoryPath = _fileSystem.Path.GetDirectoryName(path); var fileName = _fileSystem.Path.GetFileName(path); ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); status = fileStore.CreateFile(out object handle, out FileStatus fileStatus, directoryPath, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null); status.HandleStatus(); fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(fileName) ? "*" : fileName, FileInformationClass.FileDirectoryInformation); foreach (var file in queryDirectoryFileInformation) { if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation) { FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file; if (fileDirectoryInformation.FileName == fileName) { fileStore.CloseFile(handle); return(true); } } } fileStore.CloseFile(handle); } return(false); } catch { return(false); } }
public IEnumerable <FileDirectoryInformation> EnumerateFileEntries(string path, string searchPattern, SearchOption searchOption) { if (path.StartsWith("/")) { path = path.Substring(1); } ThrowOnError(FileStore.CreateFile( out var directoryHandle, out var fileStatus, path, AccessMask.GENERIC_READ, SMBLibrary.FileAttributes.Directory, ShareAccess.Read | ShareAccess.Write, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null)); List <QueryDirectoryFileInformation> fileList; var status = FileStore.QueryDirectory(out fileList, directoryHandle, searchPattern, FileInformationClass.FileDirectoryInformation); var result = fileList .OfType <FileDirectoryInformation>() .Where(f => f.FileName != "." && f.FileName != "..") .Select(f => { f.FileName = Path.Combine(path, f.FileName); return(f); }); if (searchOption == SearchOption.AllDirectories) { FileStore.QueryDirectory(out var dirList, directoryHandle, "*", FileInformationClass.FileDirectoryInformation); var dirsToEnter = dirList.OfType <FileDirectoryInformation>() .Where(f => f.FileName != "." && f.FileName != "..") .Select(f => { f.FileName = Path.Combine(path, f.FileName); return(f); }); var lresult = new List <FileDirectoryInformation>(result); foreach (var dir in dirsToEnter.Where(r => r.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory)).ToArray()) { lresult.AddRange(EnumerateFileEntries(dir.FileName, searchPattern, searchOption)); } ThrowOnError(FileStore.CloseFile(directoryHandle)); return(lresult); } ThrowOnError(FileStore.CloseFile(directoryHandle)); return(result); }
public override bool Exists(string path) { if (!path.IsSharePath()) { return(base.Exists(path)); } ISMBFileStore fileStore = null; object handle = null; try { if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new SMBException($"Failed to determine if {path} exists", new ArgumentException($"Unable to resolve \"{path.Hostname()}\"")); } NTStatus status = NTStatus.STATUS_SUCCESS; var credential = _credentialProvider.GetSMBCredential(path); using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize)) { var shareName = path.ShareName(); var directoryPath = _fileSystem.Path.GetDirectoryName(path).Replace(path.SharePath(), "").RemoveLeadingAndTrailingSeperators(); var fileName = _fileSystem.Path.GetFileName(path); _logger?.LogTrace($"Trying to determine if {{DirectoryPath: {directoryPath}}} {{FileName: {fileName}}} Exists for {{ShareName: {shareName}}}"); fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); AccessMask accessMask = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ; ShareAccess shareAccess = ShareAccess.Read; CreateDisposition disposition = CreateDisposition.FILE_OPEN; CreateOptions createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DIRECTORY_FILE; status = fileStore.CreateFile(out handle, out FileStatus fileStatus, directoryPath, accessMask, 0, shareAccess, disposition, createOptions, null); status.HandleStatus(); fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(fileName) ? "*" : fileName, FileInformationClass.FileDirectoryInformation); foreach (var file in queryDirectoryFileInformation) { if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation) { FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file; if (fileDirectoryInformation.FileName == fileName) { FileStoreUtilities.CloseFile(fileStore, ref handle); return(true); } } } FileStoreUtilities.CloseFile(fileStore, ref handle); } return(false); } catch (Exception ex) { _logger?.LogTrace(ex, $"Failed to determine if {path} exists."); return(false); } finally { FileStoreUtilities.CloseFile(fileStore, ref handle); } }
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); } }
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); } }
public override bool Exists(string path) { if (!path.IsSharePath()) { return(base.Exists(path)); } // For some reason Directory.Exists is returning true if a file exists at that path. // File.Exists works properly so as long as we check it here we are fine. if (_fileSystem.File.Exists(path)) { return(false); } ISMBFileStore fileStore = null; object handle = null; try { if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new SMBException($"Failed to determine if {path} exists", new ArgumentException($"Unable to resolve \"{path.Hostname()}\"")); } NTStatus status = NTStatus.STATUS_SUCCESS; var credential = _credentialProvider.GetSMBCredential(path); using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize)) { var shareName = path.ShareName(); var relativePath = path.RelativeSharePath(); _logger?.LogTrace( $"Trying to determine if {{RelativePath: {relativePath}}} Exists for {{ShareName: {shareName}}}"); if (string.IsNullOrEmpty(relativePath)) { return(true); } var parentFullPath = path.GetParentPath(); var parentPath = parentFullPath.RelativeSharePath(); var directoryName = path.GetLastPathSegment().RemoveLeadingAndTrailingSeperators(); fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); status = fileStore.CreateFile(out handle, out FileStatus fileStatus, parentPath, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null); status.HandleStatus(); fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, string.IsNullOrEmpty(directoryName) ? "*" : directoryName, FileInformationClass.FileDirectoryInformation); foreach (var file in queryDirectoryFileInformation) { if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation) { FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file; if (fileDirectoryInformation.FileName == directoryName) { return(true); } } } } return(false); } catch (Exception ex) { _logger?.LogTrace(ex, $"Failed to determine if {path} exists."); return(false); } finally { FileStoreUtilities.CloseFile(fileStore, ref handle); } }
private IEnumerable <string> EnumerateFiles(string path, string searchPattern, SearchOption searchOption, ISMBCredential credential) { if (!path.IsSharePath()) { return(base.EnumerateFiles(path, searchPattern, searchOption)); } if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new SMBException($"Failed to EnumerateFiles for {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\"")); } NTStatus status = NTStatus.STATUS_SUCCESS; if (credential == null) { credential = _credentialProvider.GetSMBCredential(path); } if (credential == null) { throw new SMBException($"Failed to EnumerateFiles for {path}", new InvalidCredentialException($"Unable to find credential in SMBCredentialProvider for path: {path}")); } ISMBFileStore fileStore = null; object handle = null; try { var shareName = path.ShareName(); var relativePath = path.RelativeSharePath(); _logger?.LogTrace($"Trying to EnumerateFiles for {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}"); using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize)) { fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null); status.HandleStatus(); fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, searchPattern, FileInformationClass.FileDirectoryInformation); _logger?.LogTrace($"Found {queryDirectoryFileInformation.Count} FileDirectoryInformation for {path}"); List <string> files = new List <string>(); foreach (var file in queryDirectoryFileInformation) { if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation) { FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file; if (fileDirectoryInformation.FileName == "." || fileDirectoryInformation.FileName == ".." || fileDirectoryInformation.FileName == ".DS_Store") { continue; } if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory)) { if (searchOption == SearchOption.AllDirectories) { files.AddRange(EnumerateFiles(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName), searchPattern, searchOption, credential)); } } else { files.Add(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName.RemoveLeadingAndTrailingSeperators())); } } } FileStoreUtilities.CloseFile(fileStore, ref handle); return(files); } } catch (Exception ex) { throw new SMBException($"Failed to EnumerateFiles {path}", ex); } finally { FileStoreUtilities.CloseFile(fileStore, ref handle); } }
public void Delete(string path, bool recursive, ISMBCredential credential) { if (!path.IsSharePath()) { base.Delete(path, recursive); return; } if (recursive) { if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new SMBException($"Failed to Delete {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\"")); } if (credential == null) { credential = _credentialProvider.GetSMBCredential(path); } if (credential == null) { throw new SMBException($"Failed to Delete {path}", new InvalidCredentialException("Unable to find credential in SMBCredentialProvider for path: {path}")); } ISMBFileStore fileStore = null; object handle = null; try { var shareName = path.ShareName(); var relativePath = path.RelativeSharePath(); _logger?.LogTrace($"Trying to Delete {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}"); using (var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize)) { fileStore = connection.SMBClient.TreeConnect(shareName, out var status); status.HandleStatus(); AccessMask accessMask = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ; ShareAccess shareAccess = ShareAccess.Delete; CreateDisposition disposition = CreateDisposition.FILE_OPEN; CreateOptions createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_DIRECTORY_FILE; var stopwatch = new Stopwatch(); stopwatch.Start(); do { if (status == NTStatus.STATUS_PENDING) { _logger.LogTrace($"STATUS_PENDING while trying to delete directory {path}. {stopwatch.Elapsed.TotalSeconds}/{_smbFileSystemSettings.ClientSessionTimeout} seconds elapsed."); } status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess, disposition, createOptions, null); } while (status == NTStatus.STATUS_PENDING && stopwatch.Elapsed.TotalSeconds <= _smbFileSystemSettings.ClientSessionTimeout); stopwatch.Stop(); status.HandleStatus(); fileStore.QueryDirectory(out List <QueryDirectoryFileInformation> queryDirectoryFileInformation, handle, "*", FileInformationClass.FileDirectoryInformation); foreach (var file in queryDirectoryFileInformation) { if (file.FileInformationClass == FileInformationClass.FileDirectoryInformation) { FileDirectoryInformation fileDirectoryInformation = (FileDirectoryInformation)file; if (fileDirectoryInformation.FileName == "." || fileDirectoryInformation.FileName == ".." || fileDirectoryInformation.FileName == ".DS_Store") { continue; } else if (fileDirectoryInformation.FileAttributes.HasFlag(SMBLibrary.FileAttributes.Directory)) { Delete(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName), recursive, credential); } _fileSystem.File.Delete(_fileSystem.Path.Combine(path, fileDirectoryInformation.FileName)); } } FileStoreUtilities.CloseFile(fileStore, ref handle); Delete(path, credential); } } catch (Exception ex) { throw new SMBException($"Failed to Delete {path}", ex); } finally { FileStoreUtilities.CloseFile(fileStore, ref handle); } } else { Delete(path); } }