diff --git a/ASS.Server/Helpers/EmetNativeMethods.cs b/ASS.Server/Helpers/EmetNativeMethods.cs deleted file mode 100644 index e7bcc55..0000000 --- a/ASS.Server/Helpers/EmetNativeMethods.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; - -namespace ASS.Server.Helpers -{ - - // TODO: Remove when https://github.com/joshudson/Emet/pull/3 is merged - internal class EmetNativeMethods - { - - [StructLayout(LayoutKind.Sequential)] - internal struct dirent64 { - internal ulong d_ino; - internal ulong d_off; - internal ushort d_reclen; - internal byte d_type; - [MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] - internal byte[] d_name; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct statbuf64 { - internal ulong st_dev; - internal ulong st_ino; - internal ulong st_nlink; - internal uint st_mode; - internal uint st_uid; - internal uint st_gid; - internal ulong st_rdev; - internal ulong st_size; - internal ulong st_blksize; - internal ulong st_blocks; /* number of 512 byte blocks */ - internal long st_atime; - internal ulong st_atime_nsec; - internal long st_mtime; - internal ulong st_mtime_nsec; - internal long st_ctime; - internal ulong st_ctime_nsec; - internal ulong st_glibc_reserved0; - internal ulong st_glibc_reserved1; - internal ulong st_glibc_reserved2; - }; - - internal const int statbuf_version = 1; - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern IntPtr opendir([MarshalAs(UnmanagedType.LPArray)] byte[] path); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern IntPtr closedir(IntPtr dir); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int readdir64_r(IntPtr dir, ref dirent64 entry, out IntPtr result); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int __xstat64(int version, [MarshalAs(UnmanagedType.LPArray)] byte[] file, out statbuf64 buf); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int __lxstat64(int version, [MarshalAs(UnmanagedType.LPArray)] byte[] file, out statbuf64 buf); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int __fxstat64(int version, IntPtr file, out statbuf64 buf); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int rename([MarshalAs(UnmanagedType.LPArray)] byte[] from, [MarshalAs(UnmanagedType.LPArray)] byte[] to); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int link([MarshalAs(UnmanagedType.LPArray)] byte[] filename, [MarshalAs(UnmanagedType.LPArray)] byte[] linktarget); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern int symlink([MarshalAs(UnmanagedType.LPArray)] byte[] filename, [MarshalAs(UnmanagedType.LPArray)] byte[] linktarget); - - [DllImport("libc.so.6", SetLastError=true)] - internal static extern long readlink([MarshalAs(UnmanagedType.LPArray)] byte[] filename, [MarshalAs(UnmanagedType.LPArray)] byte[] buffer, long buflen); - - internal const int FileFsVolumeInformation = 1; - internal const int FileBasicInformation = 4; - internal const int FileStandardInformation = 5; - internal const int FileInternalInformation = 6; - internal const int FileAllInformation = 18; - internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); - internal const uint MOVEFILE_REPLACE_EXISTING = 1; - internal const uint FILE_SHARE_READ = 1; - internal const uint FILE_SHARE_WRITE = 2; - internal const uint FILE_SHARE_DELETE = 4; - internal const uint FILE_SHARE_ALL = 7; - internal const uint CREATE_ALWAYS = 2; - internal const uint CREATE_NEW = 1; - internal const uint OPEN_ALWAYS = 4; - internal const uint OPEN_EXISTING = 3; - internal const uint TRUNCATE_EXISTING = 5; - internal const uint FILE_ATTRIBUTE_DIRECTORY = 16; - internal const uint FILE_ATTRIBUTE_REPARSE_POINT = 1024; - internal const uint FILE_READ_ATTRIBUTES = 128; - internal const uint FILE_FLAG_BACKUP_SEMANTICS = 0x2000000; - internal const uint FILE_FLAG_OPEN_NO_RECALL = 0x1000000; - internal const uint FILE_FLAG_OPEN_REPARSE_POINT = 0x200000; - internal const uint SYMBOLIC_LINK_FLAG_DIRECTORY = 1; - internal const uint SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 2; - internal const uint FSCTL_GET_REPARSE_POINT = 589992; - - [StructLayout(LayoutKind.Sequential)] - internal struct IO_STATUS_BLOCK { - internal IntPtr Status; - internal UIntPtr Information; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct REPARSE_DATA_BUFFER_SYMLINK { - internal uint ReparseTag; - internal ushort ReparseDataLength; - internal ushort Reserved; - internal ushort SubstituteNameOffset; - internal ushort SubstituteNameLength; - internal ushort PrintNameOffset; - internal ushort PrintNameLength; - internal uint Flags; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_BASIC_INFORMATION { - internal ulong CreationTime; // 100ns units since Jan 1 1601 - internal ulong LastAccessTime; - internal ulong LastWriteTime; - internal ulong ChangeTime; - internal uint FileAttributes; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_STANDARD_INFORMATION { - internal ulong AllocationSize; - internal ulong EndOfFile; - internal uint NumberOfLinks; - internal bool DeletePending; - internal bool Directory; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_INTERNAL_INFORMATION { - internal ulong file_index; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_FS_VOLUME_INFORMATION { - internal ulong VolumeCreationTime; - internal uint VolumeSerialNumber; - internal uint VolumeLabelLength; - internal bool SupportsObjects; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_EA_INFORMATION { - internal uint EaSize; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_ACCESS_INFORMATION { - internal uint AccessMask; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_POSITION_INFORMATION { - internal ulong CurrentByteOffset; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_MODE_INFORMATION { - internal uint Mode; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_ALIGNMENT_INFORMATION { - internal uint AlignmentRequirement; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILE_ALL_INFORMATION { - internal FILE_BASIC_INFORMATION BasicInformation; - internal FILE_STANDARD_INFORMATION StandardInformation; - internal FILE_INTERNAL_INFORMATION InternalInformation; - internal FILE_EA_INFORMATION EaInformation; - internal FILE_ACCESS_INFORMATION AccessInformation; - internal FILE_POSITION_INFORMATION PositionInformation; - internal FILE_MODE_INFORMATION ModeInformation; - internal FILE_ALIGNMENT_INFORMATION AlignmentInformation; - internal uint FileNameLength; // Variable structure - } - - [StructLayout(LayoutKind.Sequential)] - internal struct FILETIME { - internal uint dwLowDateTime; - internal uint dwHighDateTime; - } - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - internal struct WIN32_FIND_DATA { - internal uint dwFileAttributes; - internal FILETIME ftCreationTime; - internal FILETIME ftLastAccessTime; - internal FILETIME ftLastWriteTime; - internal uint nFileSizeHigh; - internal uint nFileSizeLow; - internal uint dwReserved0; - internal uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)] - internal string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst=14)] - internal string cAlternateFileName; - } - - [DllImport("ntdll.dll")] - internal static extern int NtQueryVolumeInformationFile(IntPtr handle, out IO_STATUS_BLOCK block, out FILE_FS_VOLUME_INFORMATION volume_info, int length, int Class); - [DllImport("ntdll.dll")] - internal static extern int NtQueryInformationFile(IntPtr handle, out IO_STATUS_BLOCK block, out FILE_BASIC_INFORMATION basic_info, int length, int Class); - [DllImport("ntdll.dll")] - internal static extern int NtQueryInformationFile(IntPtr handle, out IO_STATUS_BLOCK block, out FILE_STANDARD_INFORMATION standard_info, int length, int Class); - [DllImport("ntdll.dll")] - internal static extern int NtQueryInformationFile(IntPtr handle, out IO_STATUS_BLOCK block, out FILE_INTERNAL_INFORMATION internal_info, int length, int Class); - [DllImport("ntdll.dll")] - internal static extern int NtQueryInformationFile(IntPtr handle, out IO_STATUS_BLOCK block, out FILE_ALL_INFORMATION all_info, int length, int Class); - - [DllImport("ntdll.dll")] - internal static extern int RtlNtStatusToDosError(int ntstatus); - - [DllImport("kernel32.dll", SetLastError=true)] - internal static extern void SetLastError(int error); - - [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] - internal static extern IntPtr FindFirstFileW(string filename, out WIN32_FIND_DATA FindFileData); - - [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] - internal static extern byte FindNextFileW(IntPtr hFindFile, out WIN32_FIND_DATA FindFileData); - - [DllImport("kernel32.dll", SetLastError=true)] - internal static extern byte FindClose(IntPtr hFindFile); - - [DllImport("kernel32.dll", SetLastError=true)] - internal static extern byte MoveFileEx(string oldfilename, string newfilename, uint flags); - - [DllImport("kernel32.dll", SetLastError=true)] - internal static extern byte CloseHandle(IntPtr hFindFile); - - [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] - internal static extern IntPtr CreateFileW(string filename, uint dwDesiredAccess, uint dwShareMode, - IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); - - [DllImport("kernel32.dll", SetLastError=true)] - internal static extern byte DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr inptr, uint inlen, - [MarshalAs(UnmanagedType.LPArray)] byte[] outdata, uint outlen, out uint returned, IntPtr overlapped); - - [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] - internal static extern byte CreateSymbolicLinkW(string lpSymlinkFileName, string lpTargetFileName, uint dwFlags); - - [DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)] - internal static extern byte CreateHardLinkW(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); - } -} diff --git a/ASS.Server/Helpers/FileSystemHelper.cs b/ASS.Server/Helpers/FileSystemHelper.cs index 599aa96..9f5f9e1 100644 --- a/ASS.Server/Helpers/FileSystemHelper.cs +++ b/ASS.Server/Helpers/FileSystemHelper.cs @@ -29,72 +29,7 @@ namespace ASS.Server.Helpers { if (targetHint == FileType.File || targetHint == FileType.Directory) target = Path.GetRelativePath(Path.Combine(link, ".."), target); - CreateSymbolicLink(target, link, targetHint); - } - - // TODO: Remove when https://github.com/joshudson/Emet/pull/3 is merged - ///Creates a symbolic link to a file - ///The path to write to the symbolic link - ///The path to create the new link at - ///The type of node the link is referring to - ///An IO error occurred - ///linkpath doesn't exist and targethint was neither File nor Directory and this platform uses explicit link types - ///If targetpath doesn't exist and targethint is not provided, this call will fail on Windows. - public static void CreateSymbolicLink(string targetpath, string linkpath, FileType targethint = FileType.LinkTargetHintNotAvailable) - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - var btargetpath = NameToByteArray(targetpath); - var blinkpath = NameToByteArray(linkpath); - if (EmetNativeMethods.symlink(btargetpath, blinkpath) != 0) - { - var errno = Marshal.GetLastWin32Error(); - var ci = new System.ComponentModel.Win32Exception(); - throw new IOException(ci.Message, errno); - } - } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - uint flags = 0; - if (targethint != FileType.File && targethint != FileType.Directory) - { - if (!Path.IsPathRooted(targetpath)) - { - var ldname = Path.GetDirectoryName(linkpath); - if (string.IsNullOrEmpty(ldname)) ldname = DirectoryEntry.CurrentDirectoryName; - targetpath = Path.Combine(ldname, targetpath); - } - var node = new DirectoryEntry(targetpath, FileSystem.FollowSymbolicLinks.Never); - var hint = (node.FileType == FileType.SymbolicLink) ? node.LinkTargetHint : node.FileType; - if (hint == FileType.Directory) - flags = EmetNativeMethods.SYMBOLIC_LINK_FLAG_DIRECTORY; - else if (hint != FileType.File) - throw new PlatformNotSupportedException("Windows can't handle symbolic links to file system nodes that don't exist."); - } - if (targethint == FileType.Directory) - flags = EmetNativeMethods.SYMBOLIC_LINK_FLAG_DIRECTORY; - if (0 == EmetNativeMethods.CreateSymbolicLinkW(linkpath, targetpath, flags)) - { - var errno = (int)Marshal.GetLastWin32Error(); - if (errno == 1314) - { - flags |= EmetNativeMethods.SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; - if (0 != EmetNativeMethods.CreateSymbolicLinkW(linkpath, targetpath, flags)) - return; - var errno2 = (int)Marshal.GetLastWin32Error(); - if (errno2 != 1314 && errno2 != 1 && errno2 != 0xA0) - errno = errno2; // Try to get a better error - } - var ci = new System.ComponentModel.Win32Exception(); - throw new IOException(ci.Message, unchecked((int)0x80070000 | errno)); - } - } - } - - internal static byte[] NameToByteArray(string name) - { - var count = Encoding.UTF8.GetByteCount(name); - var bytes = new byte[count + 1]; - Encoding.UTF8.GetBytes(name, 0, name.Length, bytes, 0); - return bytes; + FileSystem.CreateSymbolicLink(target, link, targetHint); } } }