/// <summary> /// Ensures the specified directory exists /// </summary> /// <param name="directory">The directory.</param> public void CreateDirectory(string directory) { if (string.IsNullOrEmpty(directory)) { throw new ArgumentNullException("directory"); } directory = Path.GetFullPath(QQnPath.Combine(_directory, directory)); // Gets directory with separator if (!directory.StartsWith(_directory)) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Directory {0} is not below root", directory), "directory"); } if (Directory.Exists(directory)) { return; } CreateDirectory(QQnPath.GetParentDirectory(directory)); Directory.CreateDirectory(directory); DirectoryMapDirectory item = DoGetDirectory(QQnPath.GetRelativePath(directory, _directory)); using (item.Updater()) { item.Created = true; } }
/// <summary> /// Initializes a new instance of the <see cref="DirectoryMap"/> class. /// </summary> /// <param name="dirInfo">The dir info.</param> protected DirectoryMap(DirectoryInfo dirInfo) { if (dirInfo == null) { throw new ArgumentNullException("dirInfo"); } else if (!dirInfo.Exists) { throw new DirectoryNotFoundException("Directory does not exist"); } //_dirInfo = dirInfo; _directory = dirInfo.FullName; string mapFile = QQnPath.Combine(dirInfo.FullName, DirectoryMapData.DirMapFile); DirectoryMapData mapData = null; if (File.Exists(mapFile)) { mapData = DirectoryMapData.Load(dirInfo.FullName); } _data = mapData ?? new DirectoryMapData(dirInfo.FullName); }
public static DirectoryMapData Load(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } path = Path.GetFullPath(path); using (FileStream fs = File.OpenRead(QQnPath.Combine(path, DirMapFile))) { XPathDocument doc = new XPathDocument(fs); XPathNavigator nav = doc.CreateNavigator(); nav.MoveToRoot(); nav.MoveToFirstChild(); DirectoryMapData data; TokenizerArgs ta = new TokenizerArgs(); ta.SkipUnknownNamedItems = true; if (Tokenizer.TryParseXml(nav, ta, out data)) { data._directory = path; return(data); } } return(null); }
/// <summary> /// Verifies the file. /// </summary> /// <param name="baseDirectory">The base directory.</param> /// <param name="verifyData">The verify data.</param> /// <param name="verificationMode">The verification mode.</param> /// <returns></returns> public static bool VerifyFile(string baseDirectory, IVerifiableFile verifyData, VerifyMode verificationMode) { if (string.IsNullOrEmpty(baseDirectory)) { throw new ArgumentNullException("baseDirectory"); } else if (verifyData == null) { throw new ArgumentNullException("verifyData"); } string path = QQnPath.Combine(baseDirectory, verifyData.Filename); FileInfo fif = new FileInfo(path); if (!fif.Exists) { return(false); } if (verificationMode < VerifyMode.Time) { return(true); } bool hasTime = verifyData.LastWriteTimeUtc.HasValue; bool timeFailed = hasTime && fif.LastWriteTimeUtc != verifyData.LastWriteTimeUtc.Value; if (timeFailed && verificationMode == VerifyMode.Time) { return(false); } if (verificationMode < VerifyMode.TimeSize) { return(true); } bool hasSize = (verifyData.FileSize >= 0); bool sizeFailed = hasSize && fif.Length != verifyData.FileSize; if ((timeFailed || sizeFailed) && verificationMode == VerifyMode.TimeSize) { return(false); } if (verificationMode < VerifyMode.FileHash) { return(true); } if (!string.IsNullOrEmpty(verifyData.FileHash) && !QQnCryptoHelpers.VerifyFileHash(fif.FullName, verifyData.FileHash)) { return(false); } return(true); }
/// <summary> /// Checks if a DirMap exists for the specified path /// </summary> /// <param name="path">The path.</param> /// <returns></returns> public static bool Exists(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } path = Path.GetFullPath(path); return(Directory.Exists(path) && File.Exists(QQnPath.Combine(path, ".tDirMap"))); }
/// <summary> /// Creates the file. /// </summary> /// <param name="path">The path.</param> /// <param name="fileMode">The file mode.</param> /// <param name="hash">The hash.</param> /// <param name="size">The size.</param> /// <param name="allowExternal">if set to <c>true</c> [allow external].</param> /// <returns></returns> public Stream OpenFile(string path, FileMode fileMode, string hash, long size, bool allowExternal) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } string fullPath = QQnPath.CombineFullPath(_directory, path); path = QQnPath.MakeRelativePath(_directory, fullPath); switch (fileMode) { case FileMode.CreateNew: case FileMode.Create: if (!allowExternal && File.Exists(fullPath)) { throw new IOException(string.Format(CultureInfo.InvariantCulture, "Unmanaged file {0} exists", path)); } break; case FileMode.Open: case FileMode.Truncate: if (!_data.Files.Contains(path) && (!allowExternal || !File.Exists(path))) { throw new IOException("File does not exist"); } break; default: throw new ArgumentException("The specified mode is not supported"); } if (size < 0) { size = -1; } CreateDirectory(Path.GetDirectoryName(fullPath)); DirectoryMapFile file = DoGetFile(path); if (file.ToBeDeleted && (fileMode == FileMode.Create || fileMode == FileMode.CreateNew)) { file.ToBeDeleted = false; } return(new DirectoryMapStream(File.Open(fullPath, fileMode), file, fileMode, hash, string.IsNullOrEmpty(hash) ? -1 : size, _data.HashType)); }
/// <summary> /// Unschedules the delete. /// </summary> /// <param name="path">The path.</param> public void UnscheduleDelete(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } path = QQnPath.EnsureRelativePath(_directory, path); if (!_data.Files.Contains(path)) { return; // Not in DirectoryMap } DirectoryMapFile file = DoGetFile(path); file.ToBeDeleted = false; }
/// <summary> /// Initializes a new instance of the <see cref="SeekableStream"/> class. /// </summary> /// <param name="innerStream">The inner stream.</param> /// <param name="length">The length.</param> public SeekableStream(Stream innerStream, long length) { if (innerStream == null) { throw new ArgumentNullException("innerStream"); } _parentStream = innerStream; if (innerStream.CanSeek) { _innerStream = innerStream; _length = innerStream.Length; } else { length = _length; if (length >= 0 && length < (1024 * 1024)) // Less than 1 MB, use memory { byte[] buffer = new byte[length]; innerStream.Read(buffer, 0, buffer.Length); innerStream.Close(); _innerStream = new MemoryStream(buffer, false); _innerStream.Position = 0; } else { FileStream tempStream = new DeleteOnCloseStream(true); try { // For now, just read the file at once; we should optimize this to read when needed QQnPath.CopyStream(innerStream, tempStream); tempStream.Position = 0; _innerStream = tempStream; } finally { if (_innerStream != tempStream) { tempStream.Close(); } } } } }
public void Write() { string file = QQnPath.Combine(_directory, DirMapFile); FileInfo fif = new FileInfo(file); if (fif.Exists && (fif.Attributes & (FileAttributes.Hidden | FileAttributes.ReadOnly)) != 0) { // The hidden flag is threated for some read-only like flag by .Net, so we must reset it fif.Attributes = FileAttributes.Normal; } using (FileStream fs = File.Create(file)) using (XmlWriter xw = XmlWriter.Create(fs)) { xw.WriteStartDocument(); xw.WriteStartElement("DirectoryMap", DirMapNs); Tokenizer.TryWriteXml(xw, this); } File.SetAttributes(file, FileAttributes.Normal | FileAttributes.Hidden); }
/// <summary> /// Deletes the specified file if it is within the DirectoryMap /// </summary> /// <param name="path"></param> public void DeleteFile(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } path = QQnPath.EnsureRelativePath(_directory, path); if (!_data.Files.Contains(path)) { return; // Not in DirectoryMap } DirectoryMapFile file = DoGetFile(path); if (file.Exists) { File.Delete(file.FullName); } _data.Files.Remove(path); }
/// <summary> /// Adds the file. /// </summary> /// <param name="path">The path.</param> /// <returns></returns> public DirectoryMapFile AddFile(string path) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } string fullPath = QQnPath.Combine(_directory, path); path = QQnPath.MakeRelativePath(_directory, fullPath); if (_data.Files.Contains(path) || File.Exists(fullPath)) { DirectoryMapFile dmf = DoGetFile(path); dmf.ToBeDeleted = false; return(dmf); } else { throw new FileNotFoundException("File not found", fullPath); } }
/// <summary> /// Gets the file. /// </summary> /// <param name="path">The path.</param> /// <param name="addExistingFile">if set to <c>true</c> [add existing file].</param> /// <returns></returns> public DirectoryMapFile GetFile(string path, bool addExistingFile) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } string fullPath = QQnPath.Combine(_directory, path); path = QQnPath.MakeRelativePath(_directory, fullPath); if (_data.Files.Contains(path)) { return(DoGetFile(path)); } else if (addExistingFile && File.Exists(fullPath)) { return(AddFile(path)); } else { return(null); } }
/// <summary> /// Updates the file. /// </summary> /// <param name="baseDirectory">The base directory.</param> /// <param name="verifyData">The verify data.</param> /// <param name="hashType">Type of the hash.</param> public static void UpdateFile(string baseDirectory, IUpdatableVerifiableFile verifyData, HashType hashType) { if (string.IsNullOrEmpty(baseDirectory)) { throw new ArgumentNullException("baseDirectory"); } else if (verifyData == null) { throw new ArgumentNullException("verifyData"); } FileInfo fif = new FileInfo(QQnPath.Combine(baseDirectory, verifyData.Filename)); if (!fif.Exists) { return; } long size = fif.Length; string hash = QQnCryptoHelpers.CalculateFileHash(fif.FullName, hashType); DateTime dt = fif.LastWriteTimeUtc; verifyData.UpdateVerifyData(hash, size, dt); }