diff options
author | Kenneth Skovhede <kenneth@hexad.dk> | 2013-09-08 02:17:10 +0400 |
---|---|---|
committer | Kenneth Skovhede <kenneth@hexad.dk> | 2013-09-08 02:36:02 +0400 |
commit | 60220438569d1a1722dab77d482c77ae8cb70b9f (patch) | |
tree | c62df202bf50fa2da2a95d4856d19c9701858d74 /thirdparty/UnixSupport | |
parent | b7ad87e75959d965f8dcad7b1c843ff2e68b57c7 (diff) |
Added support for reading file types and extend attributes under linux
Diffstat (limited to 'thirdparty/UnixSupport')
-rw-r--r-- | thirdparty/UnixSupport/File.cs | 345 | ||||
-rwxr-xr-x | thirdparty/UnixSupport/UnixSupport.dll | bin | 5120 -> 7168 bytes |
2 files changed, 235 insertions, 110 deletions
diff --git a/thirdparty/UnixSupport/File.cs b/thirdparty/UnixSupport/File.cs index caa2ae30f..f2f5951ca 100644 --- a/thirdparty/UnixSupport/File.cs +++ b/thirdparty/UnixSupport/File.cs @@ -1,110 +1,235 @@ -using System; -using Mono.Unix.Native; - -namespace UnixSupport -{ - public static class File - { - /// <summary> - /// Opens the file and honors advisory locking. - /// </summary> - /// <returns>A open stream that references the file</returns> - /// <param name="path">The full path to the file</param> - public static System.IO.Stream OpenExclusive(string path, System.IO.FileAccess mode) - { - return OpenExclusive(path, mode, (int)Mono.Unix.Native.FilePermissions.DEFFILEMODE); - } - - /// <summary> - /// Opens the file and honors advisory locking. - /// </summary> - /// <returns>A open stream that references the file</returns> - /// <param name="path">The full path to the file</param> - /// <param name="filemode">The file create mode</param> - public static System.IO.Stream OpenExclusive(string path, System.IO.FileAccess mode, int filemode) - { - Flock lck; - lck.l_len = 0; - lck.l_pid = Syscall.getpid(); - lck.l_start = 0; - lck.l_type = LockType.F_WRLCK; - lck.l_whence = SeekFlags.SEEK_SET; - - OpenFlags flags = OpenFlags.O_CREAT; - if (mode == System.IO.FileAccess.Read) - { - lck.l_type = LockType.F_RDLCK; - flags |= OpenFlags.O_RDONLY; - } else if (mode == System.IO.FileAccess.Write) { - flags |= OpenFlags.O_WRONLY; - } else { - flags |= OpenFlags.O_RDWR; - } - - int fd = Syscall.open(path, flags, (Mono.Unix.Native.FilePermissions)filemode); - if (fd > 0) - { - //This does not work on OSX, it gives ENOTTY - //int res = Syscall.fcntl(fd, Mono.Unix.Native.FcntlCommand.F_SETLK, ref lck); - - //This is the same (at least for our purpose, and works on OSX) - int res = Syscall.lockf(fd, LockfCommand.F_TLOCK, 0); - - //If we have the lock, return the stream - if (res == 0) - return new Mono.Unix.UnixStream(fd); - else - { - Mono.Unix.Native.Syscall.close(fd); - throw new LockedFileException(path, mode); - } - } - - throw new BadFileException(path); - } - - [Serializable] - private class BadFileException : System.IO.IOException - { - public BadFileException(string filename) - : base(string.Format("Unable to open the file \"{0}\", error: {1} ({2})", filename, Syscall.GetLastError(), (int)Syscall.GetLastError())) - { - } - } - - [Serializable] - private class LockedFileException : System.IO.IOException - { - public LockedFileException(string filename, System.IO.FileAccess mode) - : base(string.Format("Unable to open the file \"{0}\" in mode {1}, error: {2} ({3})", filename, mode, Syscall.GetLastError(), (int)Syscall.GetLastError())) - { - } - } - - /// <summary> - /// Gets the symlink target for the given path - /// </summary> - /// <param name="path">The path to get the symlink target for</param> - /// <returns>The symlink target</returns> - public static string GetSymlinkTarget(string path) - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(2048); //2kb, should cover utf16 * 1023 chars - if (Mono.Unix.Native.Syscall.readlink(path, sb, (ulong)sb.Capacity) >= 0) - return sb.ToString(); - - throw new System.IO.FileLoadException(string.Format("Unable to get symlink for \"{0}\", error: {1} ({2})", path, Syscall.GetLastError(), (int)Syscall.GetLastError())); - } - - /// <summary> - /// Creates a new symlink - /// </summary> - /// <param name="path">The path to create the symbolic link entry</param> - /// <param name="target">The path the symbolic link points to</param> - public static void CreateSymlink(string path, string target) - { - if (Mono.Unix.Native.Syscall.symlink(target, path) != 0) - throw new System.IO.IOException(string.Format("Unable to create symlink from \"{0}\" to \"{1}\", error: {2} ({3})", path, target, Syscall.GetLastError(), (int)Syscall.GetLastError())); - } - } -} - +using System;
+using System.Collections.Generic;
+using Mono.Unix.Native;
+
+namespace UnixSupport
+{
+ public static class File
+ {
+
+ private static readonly bool SUPPORTS_LLISTXATTR;
+
+ static File ()
+ {
+ bool works = false;
+ try
+ {
+ string[] v;
+ Mono.Unix.Native.Syscall.llistxattr("/", out v);
+ works = true;
+ }
+ catch (EntryPointNotFoundException e)
+ {
+ }
+ catch
+ {
+ }
+ SUPPORTS_LLISTXATTR = works;
+ }
+
+ /// <summary>
+ /// Opens the file and honors advisory locking.
+ /// </summary>
+ /// <returns>A open stream that references the file</returns>
+ /// <param name="path">The full path to the file</param>
+ public static System.IO.Stream OpenExclusive(string path, System.IO.FileAccess mode)
+ {
+ return OpenExclusive(path, mode, (int)Mono.Unix.Native.FilePermissions.DEFFILEMODE);
+ }
+
+ /// <summary>
+ /// Opens the file and honors advisory locking.
+ /// </summary>
+ /// <returns>A open stream that references the file</returns>
+ /// <param name="path">The full path to the file</param>
+ /// <param name="filemode">The file create mode</param>
+ public static System.IO.Stream OpenExclusive(string path, System.IO.FileAccess mode, int filemode)
+ {
+ Flock lck;
+ lck.l_len = 0;
+ lck.l_pid = Syscall.getpid();
+ lck.l_start = 0;
+ lck.l_type = LockType.F_WRLCK;
+ lck.l_whence = SeekFlags.SEEK_SET;
+
+ OpenFlags flags = OpenFlags.O_CREAT;
+ if (mode == System.IO.FileAccess.Read)
+ {
+ lck.l_type = LockType.F_RDLCK;
+ flags |= OpenFlags.O_RDONLY;
+ } else if (mode == System.IO.FileAccess.Write) {
+ flags |= OpenFlags.O_WRONLY;
+ } else {
+ flags |= OpenFlags.O_RDWR;
+ }
+
+ int fd = Syscall.open(path, flags, (Mono.Unix.Native.FilePermissions)filemode);
+ if (fd > 0)
+ {
+ //This does not work on OSX, it gives ENOTTY
+ //int res = Syscall.fcntl(fd, Mono.Unix.Native.FcntlCommand.F_SETLK, ref lck);
+
+ //This is the same (at least for our purpose, and works on OSX)
+ int res = Syscall.lockf(fd, LockfCommand.F_TLOCK, 0);
+
+ //If we have the lock, return the stream
+ if (res == 0)
+ return new Mono.Unix.UnixStream(fd);
+ else
+ {
+ Mono.Unix.Native.Syscall.close(fd);
+ throw new LockedFileException(path, mode);
+ }
+ }
+
+ throw new BadFileException(path);
+ }
+
+ [Serializable]
+ private class BadFileException : System.IO.IOException
+ {
+ public BadFileException(string filename)
+ : base(string.Format("Unable to open the file \"{0}\", error: {1} ({2})", filename, Syscall.GetLastError(), (int)Syscall.GetLastError()))
+ {
+ }
+ }
+
+ [Serializable]
+ private class LockedFileException : System.IO.IOException
+ {
+ public LockedFileException(string filename, System.IO.FileAccess mode)
+ : base(string.Format("Unable to open the file \"{0}\" in mode {1}, error: {2} ({3})", filename, mode, Syscall.GetLastError(), (int)Syscall.GetLastError()))
+ {
+ }
+ }
+
+ [Serializable]
+ private class FileAccesException : System.IO.IOException
+ {
+ public FileAccesException(string filename, string method)
+ : base(string.Format("Unable to access the file \"{0}\" with method {1}, error: {2} ({3})", filename, method, Syscall.GetLastError(), (int)Syscall.GetLastError()))
+ {
+ }
+ }
+
+ /// <summary>
+ /// Gets the symlink target for the given path
+ /// </summary>
+ /// <param name="path">The path to get the symlink target for</param>
+ /// <returns>The symlink target</returns>
+ public static string GetSymlinkTarget(string path)
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder(2048); //2kb, should cover utf16 * 1023 chars
+ if (Mono.Unix.Native.Syscall.readlink(path, sb, (ulong)sb.Capacity) >= 0)
+ return sb.ToString();
+
+ throw new System.IO.FileLoadException(string.Format("Unable to get symlink for \"{0}\", error: {1} ({2})", path, Syscall.GetLastError(), (int)Syscall.GetLastError()));
+ }
+
+ /// <summary>
+ /// Creates a new symlink
+ /// </summary>
+ /// <param name="path">The path to create the symbolic link entry</param>
+ /// <param name="target">The path the symbolic link points to</param>
+ public static void CreateSymlink(string path, string target)
+ {
+ if (Mono.Unix.Native.Syscall.symlink(target, path) != 0)
+ throw new System.IO.IOException(string.Format("Unable to create symlink from \"{0}\" to \"{1}\", error: {2} ({3})", path, target, Syscall.GetLastError(), (int)Syscall.GetLastError()));
+ }
+
+ /// <summary>
+ /// Enum that describes the different filesystem entry types
+ /// </summary>
+ public enum FileType
+ {
+ File,
+ Directory,
+ Symlink,
+ Fifo,
+ Socket,
+ CharacterDevice,
+ BlockDevice,
+ Unknown
+ }
+
+ /// <summary>
+ /// Gets the type of the file.
+ /// </summary>
+ /// <returns>The file type</returns>
+ /// <param name="path">The full path to look up</param>
+ public static FileType GetFileType(string path)
+ {
+
+ var fse = Mono.Unix.UnixFileInfo.GetFileSystemEntry(path);
+ if (fse.IsRegularFile)
+ return FileType.File;
+ else if (fse.IsDirectory)
+ return FileType.Directory;
+ else if (fse.IsSymbolicLink)
+ return FileType.Symlink;
+ else if (fse.IsFifo)
+ return FileType.Fifo;
+ else if (fse.IsSocket)
+ return FileType.Socket;
+ else if (fse.IsCharacterDevice)
+ return FileType.CharacterDevice;
+ else if (fse.IsBlockDevice)
+ return FileType.CharacterDevice;
+ else
+ return FileType.Unknown;
+ }
+
+
+ /// <summary>
+ /// Gets the extended attributes.
+ /// </summary>
+ /// <returns>The extended attributes.</returns>
+ /// <param name="path">The full path to look up</param>
+ public static Dictionary<string, byte[]> GetExtendedAttributes(string path)
+ {
+ string[] values;
+ var size = SUPPORTS_LLISTXATTR ? Mono.Unix.Native.Syscall.llistxattr(path, out values) : Mono.Unix.Native.Syscall.listxattr(path, out values);
+ if (size < 0)
+ throw new FileAccesException(path, "llistxattr");
+
+ var dict = new Dictionary<string, byte[]>();
+ foreach(var s in values)
+ {
+ byte[] v;
+ var n = SUPPORTS_LLISTXATTR ? Mono.Unix.Native.Syscall.lgetxattr(path, s, out v) : Mono.Unix.Native.Syscall.getxattr(path, s, out v);
+ if (n > 0)
+ dict.Add(s, v);
+ }
+
+ return dict;
+ }
+
+ /// <summary>
+ /// Describes the basic user/group/perm tuplet for a file or folder
+ /// </summary>
+ public struct FileInfo
+ {
+ public readonly long UID;
+ public readonly long GID;
+ public readonly long Permissions;
+
+ internal FileInfo(Mono.Unix.UnixFileSystemInfo fse)
+ {
+ UID = fse.OwnerUser.UserId;
+ GID = fse.OwnerGroupId;
+ Permissions = (long)fse.FileAccessPermissions;
+ }
+ }
+
+ /// <summary>
+ /// Gets the basic user/group/perm tuplet for a file or folder
+ /// </summary>
+ /// <returns>The basic user/group/perm tuplet for a file or folder</returns>
+ /// <param name="path">The full path to look up</param>
+ public static FileInfo GetUserGroupAndPermissions(string path)
+ {
+ return new FileInfo(Mono.Unix.UnixFileInfo.GetFileSystemEntry(path));
+ }
+ }
+}
+
diff --git a/thirdparty/UnixSupport/UnixSupport.dll b/thirdparty/UnixSupport/UnixSupport.dll Binary files differindex 022fb2b8f..04560702a 100755 --- a/thirdparty/UnixSupport/UnixSupport.dll +++ b/thirdparty/UnixSupport/UnixSupport.dll |