123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
- *
- * You can redistribute this program and/or modify it under the terms of
- * the GNU Lesser Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- */
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using Utilities;
- using Microsoft.Win32.SafeHandles;
- namespace SMBServer
- {
- public class DirectoryFileSystem : FileSystem
- {
- private DirectoryInfo m_directory;
- // If a FileStream is already opened, calling File.SetCreationTime(path, ..) will result in ERROR_SHARING_VIOLATION,
- // So we must keep track of the opened file handles and use SetFileTime(handle, ..)
- private Dictionary<string, SafeFileHandle> m_openHandles = new Dictionary<string, SafeFileHandle>();
- public DirectoryFileSystem(string path) : this(new DirectoryInfo(path))
- {
- }
- public DirectoryFileSystem(DirectoryInfo directory)
- {
- m_directory = directory;
- }
- public override FileSystemEntry GetEntry(string path)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- if (File.Exists(fullPath))
- {
- FileInfo file = new FileInfo(fullPath);
- bool isHidden = (file.Attributes & FileAttributes.Hidden) > 0;
- bool isReadonly = (file.Attributes & FileAttributes.ReadOnly) > 0;
- bool isArchived = (file.Attributes & FileAttributes.Archive) > 0;
- return new FileSystemEntry(path, file.Name, false, (ulong)file.Length, file.CreationTime, file.LastWriteTime, file.LastAccessTime, isHidden, isReadonly, isArchived);
- }
- else if (Directory.Exists(fullPath))
- {
- DirectoryInfo directory = new DirectoryInfo(fullPath);
- string fullName = FileSystem.GetDirectoryPath(path);
- bool isHidden = (directory.Attributes & FileAttributes.Hidden) > 0;
- bool isReadonly = (directory.Attributes & FileAttributes.ReadOnly) > 0;
- bool isArchived = (directory.Attributes & FileAttributes.Archive) > 0;
- return new FileSystemEntry(fullName, directory.Name, true, 0, directory.CreationTime, directory.LastWriteTime, directory.LastAccessTime, isHidden, isReadonly, isArchived);
- }
- else
- {
- return null;
- }
- }
- public override FileSystemEntry CreateFile(string path)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- FileStream stream = File.Create(fullPath);
- stream.Close();
- return GetEntry(path);
- }
- public override FileSystemEntry CreateDirectory(string path)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- Directory.CreateDirectory(fullPath);
- return GetEntry(path);
- }
- public override void Move(string source, string destination)
- {
- ValidatePath(source);
- ValidatePath(destination);
- string sourcePath = m_directory.FullName + source;
- string destinationPath = m_directory.FullName + destination;
- if (File.Exists(sourcePath))
- {
- File.Move(sourcePath, destinationPath);
- }
- else // Entry is a directory
- {
- Directory.Move(sourcePath, destinationPath);
- }
- }
- public override void Delete(string path)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- if (File.Exists(fullPath))
- {
- File.Delete(fullPath);
- }
- else if (Directory.Exists(fullPath))
- {
- Directory.Delete(fullPath, false);
- }
- else
- {
- throw new FileNotFoundException();
- }
- }
- public override List<FileSystemEntry> ListEntriesInDirectory(string path)
- {
- ValidatePath(path);
- if (path == String.Empty)
- {
- path = @"\";
- }
- string fullPath = m_directory.FullName + path;
- DirectoryInfo directory = new DirectoryInfo(fullPath);
- List<FileSystemEntry> result = new List<FileSystemEntry>();
- foreach (DirectoryInfo subDirectory in directory.GetDirectories())
- {
- string fullName = GetRelativeDirectoryPath(subDirectory.FullName);
- bool isHidden = (subDirectory.Attributes & FileAttributes.Hidden) > 0;
- bool isReadonly = (subDirectory.Attributes & FileAttributes.ReadOnly) > 0;
- bool isArchived = (subDirectory.Attributes & FileAttributes.Archive) > 0;
- result.Add(new FileSystemEntry(fullName, subDirectory.Name, true, 0, subDirectory.CreationTime, subDirectory.LastWriteTime, subDirectory.LastAccessTime, isHidden, isReadonly, isArchived));
- }
- foreach (FileInfo file in directory.GetFiles())
- {
- string fullName = GetRelativePath(file.FullName);
- bool isHidden = (file.Attributes & FileAttributes.Hidden) > 0;
- bool isReadonly = (file.Attributes & FileAttributes.ReadOnly) > 0;
- bool isArchived = (file.Attributes & FileAttributes.Archive) > 0;
- result.Add(new FileSystemEntry(fullName, file.Name, false, (ulong)file.Length, file.CreationTime, file.LastWriteTime, file.LastAccessTime, isHidden, isReadonly, isArchived));
- }
- return result;
- }
- public override Stream OpenFile(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- const int DefaultBufferSize = 4096;
- FileStream fileStream = new FileStream(fullPath, mode, access, share, DefaultBufferSize, options);
- if (!m_openHandles.ContainsKey(fullPath.ToLower()))
- {
- m_openHandles.Add(fullPath.ToLower(), fileStream.SafeFileHandle);
- }
- StreamWatcher watcher = new StreamWatcher(fileStream);
- watcher.Closed += new EventHandler(Stream_Closed);
- return watcher;
- }
- private void Stream_Closed(object sender, EventArgs e)
- {
- StreamWatcher watcher = (StreamWatcher)sender;
- FileStream fileStream = (FileStream)watcher.Stream;
- m_openHandles.Remove(fileStream.Name.ToLower());
- }
- public override void SetAttributes(string path, bool? isHidden, bool? isReadonly, bool? isArchived)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- if (File.Exists(fullPath) || Directory.Exists(fullPath))
- {
- FileAttributes attributes = File.GetAttributes(fullPath);
- if (isHidden.HasValue)
- {
- if (isHidden.Value)
- {
- attributes |= FileAttributes.Hidden;
- }
- else
- {
- attributes &= ~FileAttributes.Hidden;
- }
- }
- if (isReadonly.HasValue)
- {
- if (isReadonly.Value)
- {
- attributes |= FileAttributes.ReadOnly;
- }
- else
- {
- attributes &= ~FileAttributes.ReadOnly;
- }
- }
- if (isArchived.HasValue)
- {
- if (isArchived.Value)
- {
- attributes |= FileAttributes.Archive;
- }
- else
- {
- attributes &= ~FileAttributes.Archive;
- }
- }
- File.SetAttributes(fullPath, attributes);
- }
- else
- {
- throw new FileNotFoundException();
- }
- }
- public override void SetDates(string path, DateTime? creationDT, DateTime? lastWriteDT, DateTime? lastAccessDT)
- {
- ValidatePath(path);
- string fullPath = m_directory.FullName + path;
- if (File.Exists(fullPath))
- {
- SafeFileHandle openHandle;
- if (m_openHandles.TryGetValue(fullPath.ToLower(), out openHandle))
- {
- if (creationDT.HasValue)
- {
- Win32Native.SetCreationTime(openHandle, creationDT.Value);
- }
- if (lastWriteDT.HasValue)
- {
- Win32Native.SetLastWriteTime(openHandle, lastWriteDT.Value);
- }
- if (lastAccessDT.HasValue)
- {
- Win32Native.SetLastAccessTime(openHandle, lastAccessDT.Value);
- }
- }
- else
- {
- if (creationDT.HasValue)
- {
- File.SetCreationTime(fullPath, creationDT.Value);
- }
- if (lastWriteDT.HasValue)
- {
- File.SetLastWriteTime(fullPath, lastWriteDT.Value);
- }
- if (lastAccessDT.HasValue)
- {
- File.SetLastAccessTime(fullPath, lastAccessDT.Value);
- }
- }
- }
- else if (Directory.Exists(fullPath))
- {
- if (creationDT.HasValue)
- {
- Directory.SetCreationTime(fullPath, creationDT.Value);
- }
- if (lastWriteDT.HasValue)
- {
- Directory.SetLastWriteTime(fullPath, lastWriteDT.Value);
- }
- if (lastAccessDT.HasValue)
- {
- Directory.SetLastAccessTime(fullPath, lastAccessDT.Value);
- }
- }
- else
- {
- throw new FileNotFoundException();
- }
- }
- private void ValidatePath(string path)
- {
- if (path != String.Empty && !path.StartsWith(@"\"))
- {
- throw new ArgumentException("Path must start with a backslash");
- }
- if (path.Contains(@"\..\"))
- {
- throw new ArgumentException("Given path is not allowed");
- }
- }
- public override string Name
- {
- get
- {
- DriveInfo drive = new DriveInfo(m_directory.FullName.Substring(0, 2));
- return drive.DriveFormat;
- }
- }
- public override long Size
- {
- get
- {
- DriveInfo drive = new DriveInfo(m_directory.FullName.Substring(0, 2));
- return drive.TotalSize;
- }
- }
- public override long FreeSpace
- {
- get
- {
- DriveInfo drive = new DriveInfo(m_directory.FullName.Substring(0, 2));
- return drive.AvailableFreeSpace;
- }
- }
- private string GetRelativePath(string fullPath)
- {
- return fullPath.Substring(m_directory.FullName.Length);
- }
- private string GetRelativeDirectoryPath(string fullPath)
- {
- return GetRelativePath(GetDirectoryPath(fullPath));
- }
- }
- }
|