Jonathan,
As far windows is concerned, there exists a native port of file and the
associated library at http://gnuwin32.sourceforge.net/packages/file.htm
. However, it doesn't seam that too many people or projects use it. I
don't have steady access to a win32 dev box to give it a whirl. So I'm
sure what do with the name space now... although Mono.Unix have the warm
fuzzy feeling of correctness/content.
The class name of Magic can be defiantly confusing/entertaining for the
user who stumbles upon it for the first time. The other thing name that
comes to my mind is FileMagicDatabase.
I'm willing to write the documentation as soon as this is done, and I
figure out how to do it...
I've updated the bindings with the things you recommended, and I
integrated it with the build system. I haven't tackled your point #4
since I wasn't sure how to approach it exactly.
Jonathan Pryor wrote:
> On Fri, 2006-09-22 at 23:25 -0400, Milosz Tanski wrote:
>> I wrote a wrapper for the unix libmagic library since it's very handy
>> sometimes (and I'm using this wrapper in my app right now, so I figured
>> might as well submit it). Sorry that's it's not a diff, but I'd know
>> exactly how to integrate it with the class library build system.
>
> I have a few questions/concerns/observations:
>
> 1. Can libmagic be used on Windows without the use of Cygwin? I think
> it can be, but I'm not entirely sure. If it can be, I'm not sure that
> Mono.Unix is the best place for it (deliberately ignoring the Mono.Unix
> types which can work on Windows, Mono.Unix.Native.Stdlib &
> Mono.Unix.Native.StdioFileStream). If libmagic can't work on Windows
> without Cygwin, then Mono.Unix is probably a reasonable spot for it.
>
> 2. I'm not fond of the name "Magic." Yes, it's a `libmagic' wrapper,
> but for those who don't know what `libmagic' is, it's not a very
> informative name. Considering that it's used by the file(1) command,
> I'm sure some better name could be found. Perhaps FileTypeInfo?
>
> Of course, any name would need to be "stand-alone"-ish, and not be
> easily confused with the existing UnixFileSystemInfo & UnixFileInfo
> types.
> 3. The Magic.Descrition property should be Magic.Description.
>
> 4. You should get libmagic to generate UTF-8 (it it doesn't do so by
> default) and use UnixEncoding to do the UTF-8 -> string conversion (in
> case Mono's Marshal.PtrToStringAuto ever stops doing UTF-8, and there's
> a bug open to investigate that).
>
> 5. If it does get into Mono.Unix, the magic_* methods taking a filename
> should make use of the Mono.Unix.Native.FileNameMarshaler custom
> marshaler for "proper" filename transfers (for when a filename contains
> random binary data instead of being valid UTF-8). See
> Mono.Unix.Native.Syscall.
>
> 6. Documentation -- are you willing to write it? :-)
>
>
> Thank you for the file.
>
> - Jon
>
>
Index: class/Mono.Posix/Mono.Unix.Native/LibMagic.cs
===================================================================
--- class/Mono.Posix/Mono.Unix.Native/LibMagic.cs (revision 0)
+++ class/Mono.Posix/Mono.Unix.Native/LibMagic.cs (revision 0)
@@ -0,0 +1,50 @@
+using System;
+using System.Runtime.InteropServices;
+using Mono.Unix.Native;
+
+namespace Mono.Unix.Native
+{
+
+ [Flags]
+ public enum MAGIC_FLAGS
+ {
+ MAGIC_NONE = 0,
+ MAGIC_DEBUG = 1,
+ MAGIC_SYMLINK = 1 << 1,
+ MAGIC_COMPRESS = 1 << 2,
+ MAGIC_DEVICES = 1 << 3,
+ MAGIC_MIME = 1 << 4,
+ MAGIC_CONTINUE = 1 << 5,
+ MAGIC_CHECK = 1 << 6,
+ MAGIC_PRESERVE_ATIME = 1 << 7,
+ MAGIC_RAW = 1 << 8,
+ MAGIC_ERROR = 1 << 9
+ }
+
+ public static class LibMagic
+ {
+ [DllImport("magic")]
+ public extern static IntPtr magic_open(MAGIC_FLAGS flags);
+
+ [DllImport("magic")]
+ public extern static void magic_close(IntPtr magic_cookie);
+
+ [DllImport("magic")]
+ public extern static int magic_setflags(IntPtr magic_cookie, MAGIC_FLAGS flags);
+
+ [DllImport("magic")]
+ public extern static IntPtr magic_file(IntPtr magic_cookie,
+ [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] string filename);
+
+ [DllImport("magic")]
+ public extern static IntPtr magic_buffer(IntPtr magic_cookie, Byte[] data, int len);
+
+ [DllImport("magic")]
+ public extern static IntPtr magic_error(IntPtr magic_cookie);
+
+ [DllImport("magic")]
+ public extern static int magic_load(IntPtr magic_cookie,
+ [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(FileNameMarshaler))] string filename);
+
+ }
+}
Index: class/Mono.Posix/Mono.Posix.dll.sources
===================================================================
--- class/Mono.Posix/Mono.Posix.dll.sources (revision 65832)
+++ class/Mono.Posix/Mono.Posix.dll.sources (working copy)
@@ -6,6 +6,7 @@
./Mono.Unix/FileAccessPermissions.cs
./Mono.Unix/FileAccessPattern.cs
./Mono.Unix/FileHandleOperations.cs
+./Mono.Unix/FileMagicDb.cs
./Mono.Unix/FileSpecialAttributes.cs
./Mono.Unix/FileTypes.cs
./Mono.Unix/MapAttribute.cs
@@ -32,6 +33,7 @@
./Mono.Unix.Native/CdeclFunction.cs
./Mono.Unix.Native/FileNameMarshaler.cs
./Mono.Unix.Native/HeaderAttribute.cs
+./Mono.Unix.Native/LibMagic.cs
./Mono.Unix.Native/NativeConvert.cs
./Mono.Unix.Native/NativeConvert.generated.cs
./Mono.Unix.Native/Stdlib.cs
Index: class/Mono.Posix/Mono.Unix/FileMagicDb.cs
===================================================================
--- class/Mono.Posix/Mono.Unix/FileMagicDb.cs (revision 0)
+++ class/Mono.Posix/Mono.Unix/FileMagicDb.cs (revision 0)
@@ -0,0 +1,163 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using Mono.Unix.Native;
+
+namespace Mono.Unix {
+
+ public class MagicDbException : Exception
+ {
+ string _text;
+
+ public MagicDbException(string text) : base()
+ {
+ _text = text;
+ }
+
+ override public string ToString()
+ {
+ return _text;
+ }
+ }
+
+ public class FileMagicDb : IDisposable
+ {
+ IntPtr _magic = IntPtr.Zero;
+ bool _followSymlinks = false;
+
+ // open the magic database with default database files
+ public FileMagicDb(bool ReturnMime)
+ {
+ _magic = LibMagic.magic_open((ReturnMime) ? DefaultFlags | MAGIC_FLAGS.MAGIC_MIME : DefaultFlags);
+ if (_magic == IntPtr.Zero)
+ throw new MagicDbException("Unable to open the magic database");
+
+ if (LibMagic.magic_load(_magic, null) != 0)
+ throw new MagicDbException(this.Error);
+
+ }
+
+ // open the magic database with a custom database file list
+ public FileMagicDb(bool ReturnMime, string[] dblist)
+ {
+ _magic = LibMagic.magic_open((ReturnMime) ? DefaultFlags | MAGIC_FLAGS.MAGIC_MIME : DefaultFlags);
+ if (_magic == IntPtr.Zero)
+ throw new MagicDbException("Unable to open the magic database");
+
+ foreach(string file in dblist) {
+ if (LibMagic.magic_load(_magic, file) != 0)
+ throw new MagicDbException(this.Error);
+ }
+
+ }
+
+ ~FileMagicDb()
+ {
+ if (_magic != IntPtr.Zero) {
+ LibMagic.magic_close(_magic);
+ _magic = IntPtr.Zero;
+ }
+ }
+
+ public void Dispose ()
+ {
+ if (_magic != IntPtr.Zero) {
+ LibMagic.magic_close(_magic);
+ _magic = IntPtr.Zero;
+ }
+
+ GC.SuppressFinalize(this);
+ }
+
+ public void AddDefaultDbFiles()
+ {
+ if (LibMagic.magic_load(_magic, null) != 0)
+ throw new MagicDbException(this.Error);
+ }
+
+ public void AddDbFile(string file)
+ {
+ if (LibMagic.magic_load(_magic, file) != 0)
+ throw new MagicDbException(this.Error);
+ }
+
+ public bool FollowSymlinks
+ {
+ get {
+ return _followSymlinks;
+ }
+
+ set {
+ LibMagic.magic_setflags(_magic, (value) ? DefaultFlags | MAGIC_FLAGS.MAGIC_MIME : DefaultFlags);
+ _followSymlinks = value;
+ }
+
+ }
+
+ private string Error
+ {
+ get {
+ return Marshal.PtrToStringAuto(LibMagic.magic_error(_magic));
+ }
+ }
+
+ public string Lookup(string filename)
+ {
+ string text;
+
+ text = Marshal.PtrToStringAuto(LibMagic.magic_file(_magic, filename));
+ if (text == null)
+ throw new MagicDbException(this.Error);
+
+ return text;
+ }
+
+ public string Lookup(FileInfo fi)
+ {
+ return Lookup(fi.FullName);
+ }
+
+ public string Lookup(byte[] data)
+ {
+ string text;
+
+ text = Marshal.PtrToStringAuto(LibMagic.magic_buffer(_magic, data, data.Length));
+ if (text == null)
+ throw new MagicDbException(this.Error);
+
+ return text;
+ }
+
+ static public string Mime(string filename)
+ {
+ string mime;
+ FileMagicDb m = new FileMagicDb(true);
+
+ mime = Marshal.PtrToStringAuto(LibMagic.magic_file(m._magic, filename));
+ if (mime == null) {
+ throw new MagicDbException(m.Error);
+ }
+
+ return mime;
+ }
+
+ static public string Description(string filename)
+ {
+ string desc;
+ FileMagicDb m = new FileMagicDb(false);
+
+ desc = Marshal.PtrToStringAuto(LibMagic.magic_file(m._magic, filename));
+ if (desc == null) {
+ throw new MagicDbException(m.Error);
+ }
+
+ return desc;
+ }
+
+ private static MAGIC_FLAGS DefaultFlags{
+ get {
+ return MAGIC_FLAGS.MAGIC_NONE | MAGIC_FLAGS.MAGIC_PRESERVE_ATIME;
+ }
+ }
+ }
+}
_______________________________________________
Mono-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-list