public static void FromFileToFolder(string srcFilePath, string dstPath) { // decompress to temp file, // run through the stream, writing the data out to the first file, then copy to all duplicates var tmp = srcFilePath + ".tmp"; // decompress file if (File.Exists(tmp)) File.Delete(tmp); using (var compressing = new GZipStream(File.OpenRead(srcFilePath), CompressionMode.Decompress)) using (var cat = File.OpenWrite(tmp)) { compressing.CopyTo(cat, 65536); cat.Flush(); } // scan the file long pathsLength; using (var fs = File.OpenRead(tmp)) while (ReadLength(fs, out pathsLength)) { // get all target paths long fileLength; var subPaths = ReadUtf8(fs, pathsLength).Split('|'); if (!ReadLength(fs, out fileLength)) throw new Exception("Malformed file: no length for data"); // read source into first file var firstPath = dstPath+subPaths[0]; PutFolder(firstPath); CopyLength(fs, firstPath, fileLength); if (subPaths.Length == 1) continue; // copy first file into all other locations var srcInfo = new PathInfo(firstPath); for (int i = 1; i < subPaths.Length; i++) { var thisPath = dstPath + subPaths[i]; PutFolder(thisPath); if (!NativeIO.CopyFile(srcInfo, new PathInfo(thisPath))) throw new Exception("Failed to write "+ thisPath); } } // cleanup temp file File.Delete(tmp); }
static void WriteFileToAllPaths(IList<string> subPaths, Stream fs, long fileLength, IEnumerable<byte> expectedHash) { // read source into first file var firstPath = subPaths[0]; PutFolder(firstPath); // <data:byte array> CopyLength(fs, firstPath, fileLength, expectedHash); if (subPaths.Count == 1) { return; } // copy first file into all other locations var srcInfo = new PathInfo(firstPath); for (int i = 1; i < subPaths.Count; i++) { var thisPath = subPaths[i]; PutFolder(thisPath); if (!NativeIO.CopyFile(srcInfo, new PathInfo(thisPath))) { throw new Exception("Failed to write " + thisPath); } } }
static void PutFolder(string path) { var pinfo = new PathInfo(path); if (pinfo.Parent != null) NativeIO.CreateDirectory(new PathInfo(path).Parent, recursive:true); }
/// <summary> /// Creates a new directory. If <paramref name="recursive" /> is false, the parent directory must exists. /// </summary> /// <param name="pathInfo"> /// Complete path to create /// </param> /// <param name="recursive">If <paramref name="recursive" /> is false, the parent directory must exist.</param> public static void CreateDirectory(PathInfo pathInfo, bool recursive = false) { if (recursive) { var parent = pathInfo.Parent; if (parent.IsRoot) { // Root if (!parent.Exists) { throw new Exception("Root path does not exists. You cannot create a root this way. " + parent.FullName); } } else if (!parent.Exists) { CreateDirectory(parent, true); } } if (pathInfo.Exists) { return; } bool created = Win32SafeNativeMethods.CreateDirectory(pathInfo.FullNameUnc, IntPtr.Zero); int win32Error = Marshal.GetLastWin32Error(); if (!created) { NativeExceptionMapping(pathInfo.FullName, win32Error); } }
/// <summary> /// Opens a <see cref="FileStream"/> for access at the given path. Ensure stream is correctly disposed. /// </summary> public static FileStream OpenFileStream(PathInfo pathInfo, FileAccess fileAccess, FileMode fileOption = FileMode.Open, FileShare shareMode = FileShare.Read, Int32 buffer = 0) { var fileHandle = Win32SafeNativeMethods.CreateFile(pathInfo.FullNameUnc, fileAccess, shareMode, IntPtr.Zero, fileOption, 0, IntPtr.Zero); var win32Error = Marshal.GetLastWin32Error(); if (fileHandle.IsInvalid) { NativeExceptionMapping(pathInfo.FullName, win32Error); // Throws an exception } return buffer > 0 ? new FileStream(fileHandle, fileAccess, buffer) : new FileStream(fileHandle, fileAccess); }
/// <summary> /// Creates the file information on the basis of the path and <see cref="Win32FindData"/> /// </summary> /// <param name="pathInfo">Full path to the file</param> /// <param name="win32FindData"><see cref="Win32FindData"/></param> internal FileDetail(PathInfo pathInfo, Win32FindData win32FindData) { PathInfo = pathInfo; CalculateSize(win32FindData); }
/// <summary> /// Copies a file and overwrite existing files if desired. /// </summary> /// <param name="sourceFilePath">Full source path</param> /// <param name="targetFilePath">Full target path</param> /// <param name="overwrite">true to overwrite existing files</param> /// <returns>True if copy succeeded, false if not. Check last Win32 Error to get further information.</returns> public static bool CopyFile(PathInfo sourceFilePath, PathInfo targetFilePath, bool overwrite = false) { bool failOnExists = !overwrite; bool result = Win32SafeNativeMethods.CopyFile(sourceFilePath.FullNameUnc, targetFilePath.FullNameUnc, failOnExists); int win32Error = Marshal.GetLastWin32Error(); NativeExceptionMapping(sourceFilePath.FullName, win32Error); return result; }
/// <summary> /// Loads a file from specified path /// </summary> /// <param name="pathInfo">Full path</param> /// <returns> /// <see cref="FileDetail" /> /// </returns> public static FileDetail ReadFileDetails(PathInfo pathInfo) { Win32FindData findData; if (!TryGetFindDataFromPath(pathInfo, out findData)) { throw new Exception("PathNotFound " + pathInfo.FullName); } if (DetermineFileSystemEntry(findData) != FileOrDirectory.File) { throw new Exception("UnmatchedFileSystemEntryType " + FileOrDirectory.File + ", " + FileOrDirectory.Directory + ", " + pathInfo.FullName); } return new FileDetail(pathInfo, findData); }
/// <summary> /// Returns the <see cref="Win32FindData" /> from specified <paramref name="pathInfo" /> /// </summary> /// <param name="pathInfo">Path to the file system entry</param> /// <returns> /// <see cref="Win32FindData" /> /// </returns> public static Win32FindData GetFindDataFromPath(PathInfo pathInfo) { var win32FindData = new Win32FindData(); int win32Error; using (var fileHandle = FindFirstSafeFileHandle(pathInfo.FullNameUnc, win32FindData, out win32Error)) { // Take care of invalid handles if (fileHandle.IsInvalid) { NativeExceptionMapping(pathInfo.FullName, win32Error); } // Ignore . and .. directories if (!IsSystemDirectoryEntry(win32FindData)) { return win32FindData; } } throw new Exception("PathNotFound " + pathInfo.FullName); }
/// <summary> /// Reurns true if passed path exists /// </summary> /// <param name="pathInfo">Path to check</param> public static Boolean Exists(PathInfo pathInfo) { uint attributes = Win32SafeNativeMethods.GetFileAttributes(pathInfo.FullNameUnc); return !Equals(attributes, 0xffffffff); }
/// <summary> /// Gets the <see cref="Win32FindData" /> from the passed path. /// </summary> /// <param name="pathInfo">Path</param> /// <param name="pathFindData"><seealso cref="Win32FindData" />. Will be null if path does not exist.</param> /// <returns>true if path is valid and <see cref="Win32FindData" /> is set</returns> /// <remarks> /// <see> /// <cref>QuickIOCommon.NativeExceptionMapping</cref> /// </see> /// if invalid handle found. /// </remarks> public static bool TryGetFindDataFromPath(PathInfo pathInfo, out Win32FindData pathFindData) { var win32FindData = new Win32FindData(); int win32Error; using (var fileHandle = FindFirstSafeFileHandle(pathInfo.FullNameUnc, win32FindData, out win32Error)) { // Take care of invalid handles if (fileHandle.IsInvalid) { NativeExceptionMapping(pathInfo.FullName, win32Error); } // Ignore . and .. directories if (!IsSystemDirectoryEntry(win32FindData)) { pathFindData = win32FindData; return true; } } pathFindData = null; return false; }
/// <summary> /// Returns true if the file or directory is a reparse point (hopefully a symlink and not a hardlink) /// </summary> public static Boolean IsSymLink(PathInfo pathInfo) { return (Win32SafeNativeMethods.GetFileAttributes(pathInfo.FullNameUnc) & (uint)FileAttrFlags.FILE_ATTRIBUTE_REPARSE_POINT) == (uint)FileAttrFlags.FILE_ATTRIBUTE_REPARSE_POINT; }
/// <summary> /// Reurns true if passed path exists /// </summary> /// <param name="pathInfo">Path to check</param> public static Boolean Exists(PathInfo pathInfo) { var attributes = (FileAttrFlags)Win32SafeNativeMethods.GetFileAttributes(pathInfo.FullNameUnc); return !Equals(attributes, FileAttrFlags.INVALID_FILE_ATTRIBUTES); }