[Mono-list] Announce: Mono.Fuse (+ Required Mono.Posix Changes)

Jonathan Pryor jonpryor at vt.edu
Tue Aug 29 08:27:02 EDT 2006


Mono.Fuse is a binding for the FUSE library, permitting user-space 
file systems to be written in C#.

Why?
===

I read Robert Love's announcement of beaglefs, a FUSE program that 
exposes Beagle searches as a filesystem.  My first thought: Why 
wasn't that done in C# (considering that the rest of Beagle is C#)?


What about SULF?
===============

Stackable User-Level Filesystem, or SULF 
(http://arg0.net/users/vgough/sulf/), is a pre-existing FUSE binding 
in C#, started by Valient Gough in 2004.

Mono.Fuse has no relation to SULF, for two reasons:

  1.  It goes to great efforts to avoid a Mono.Posix.dll dependency,
      duplicating Mono.Unix.Native.Stat (Fuse.Stat),
      Mono.Unix.Native.Statvfs (Fuse.StatFS), and many methods from
      Mono.Unix.Native.Syscall (Fuse.Wrapper).

  2.  I don't like the SULF API.  (Not that I spent a great deal of
      time looking at it, but what I did see I didn't like.)

  3.  SULF wraps the FUSE kernel-level interface, while Mono.Fuse
      wraps the higher level libfuse C interface

I find (1) the most appalling, if only because I'm the Mono.Posix
maintainer and I'd like to see my work actually used. :-)

Once I started writing Mono.Fuse, I discovered a good reason to avoid
Mono.Posix: it's currently impossible to use from outside of Mono.
I figured this would be a good opportunity to rectify that, making it
easier for additional libraries to build upon the Mono.Posix
infrastructure.


Implementation:
==============

Mono.Fuse requires patches to the mcs & mono modules, changes which
need to be proposed (hence this email) and discussed.

mono:
----

The biggest problem with the mono module is that no headers are
installed, making it difficult to make use of libMonoPosixHelper.so.

Changes:
  - Modify `configure' to generate a mono-config.h file, installed as
    $libdir/mono/include/mono-config.h.  (Basic idea "borrowed" from
    GLib's $libdir/glib-2.0/include/glibconfig.h).
  - Add a mono-posix-helper.pc file
  - Install the files $includedir/mono/posix/helper.h and
    $includedir/mono/posix/map.h.

map.h is the current map.h file generated by make-map.exe, with some
major additions (detailed in the mcs section).

helper.h is the main include file, which includes map.h and declares
all types/functions which cannot be generated by make-map.exe.

mono-config.h is necessary because it needs to contain
platform-specific macros.  In particular, Linux needs:

  int
  Mono_Posix_ToStat (struct statvfs *to, struct Mono_Posix_Helper *to);

while OS X and *BSD need:

  int
  Mono_Posix_ToStat (struct statfs *to, struct Mono_Posix_Helper *to);

Note `struct statvfs' vs. `struct statfs'.  The mono/posix/helper.h
header needs to "paper over" the difference, and thus needs to know
which type the platform prefers.  helper.h thus looks like:

  #ifdef MONO_HAVE_STATVFS
    struct statvfs;
    int Mono_Posix_ToStatvfs (struct statvfs *from, 
        struct Mono_Posix_Statvfs *to);
  #endif
  #ifdef MONO_HAVE_STATFS
    struct statfs;
    int Mono_Posix_ToStatvfs (struct statfs *from, 
        struct Mono_Posix_Statvfs *to);
  #endif

One of MONO_HAVE_STATVFS or MONO_HAVE_STATFS would be defined in
mono-config.h.


mcs:
---

There are two major changes:

  * The addition of one public attributes to the API:

    // targets Class, Delegate, Enum, Field, Struct
    class Mono.Unix.Native.MapAttribute {
      public MapAttribute ();
      public MapAttribute (string nativeType);
      public string NativeType {get;}
      public string NativeSymbolPrefix {get; set;}
    }

  * A major revamp to make-map.exe

The Map and MapHeader attributes are public so that make-map.exe can
use a publically exposed API for code generation purposes which can be
used by other libraries (Mono.Fuse makes use of these changes).

Make-map.exe can also generate structure declarations and delegate
declarations in addition to P/Invoke function declarations,
allowing for a better, automated interface between C and C#.

Previously, [Map] could only be used on enumerations.

Now, [Map] can be used on classes, structures, & delegates, to create
a C declaration of the C# type, suitable for P/Invoke purposes, e.g.

  [Map] struct Stat {public FilePermissions mode;}

would generate the C declaration

  struct Namespace_Stat {unsigned int mode;};

The MapAttribute.NativeType property is used to specify that type
conversion functions should be generated, thus:

  [Map ("struct stat")] struct Stat {public FilePermissions mode;}

would generate

  struct Namespace_Stat {unsigned int mode;};
  int Namespace_ToStat (struct stat *from, struct Namespace_Stat *to);
  int Namespace_FromStat (struct Namespace_Stat *from, struct stat *to);

along with the actual implementations of Namespace_ToStat() and
Namespace_FromStat().

The MapAttribute.NativeSymbolPrefix is used to specify the C
"namespace" to use:

  [Map (NativeSymbolPrefix="Foo")] struct Stat {FilePermissiond mode;}

generates

  struct Foo_Stat {unsigned int mode;};

This prefix is also used for the conversion functions.

(You may be wondering why NativeSymbolPrefix exists at all.  This is
for reasonable symbol versioning -- make-map.exe currently has a
"hack" in place to rename Mono.Unix(.Native) to Mono_Posix, a hack
I'd like to remove, and NativeSymbolPrefix allows the Mono.Unix.Native
types to have a "Mono_Posix" C namespace in a reasonably general 
manner.)

The previously internal Mono.Unix.HeaderAttribute has been removed.
The HeaderAttribute.Includes and HeaderAttribute.Defines properties
have been replaced with make-map.exe command-line arguments.  In
particular, HeaderAttribute.Includes has been replaced with
--autoconf-header, --impl-header, --impl-macro, --public-header, and
--public-macro (the first three modify the generated .c file, while
the latter two modify the generated .h file).

Finally, make-map.exe has been renamed and moved from
mcs/class/Mono.Posix/Mono.Unix.Native/make-map.exe to
mcs/tools/create-native-map/create-native-map.exe.


HOWTO:
=====

Go to http://www.jprl.com/mono-fuse for the patches and source download.

Apply ``mcs.patch'' to a ``mcs'' checkout, rebuild, and install.
Apply ``mono.patch'' to a ``mono'' checkout, rebuild, and install.
Build ``mono-fuse-0.1.0.tar.gz'' in "the standard manner" (ye olde
"./configure; make; make install" business).


Questions:
=========

  - Is it OK for create-native-map.exe to be a .NET 2.0 app?

  - How should we cope with unstable APIs which make use of native 
    code?  The Application Deployment Guidelines [1] don't address
    this issue, nor the related issue of what should be done with
    64-bit binaries.  In particular, for an AMD64 machine, which
    directory layout should be used for an assembly + native lib
    combo?
    1. What Mono seems to do, with the GAC in $prefix/lib no matter
       what the architecture:

        /usr/lib/mono-fuse/Mono.Fuse.dll
        /usr/lib64/libMonoFuseHelper.so
    2. Be consistent, and toss everything in @libdir@:

        /usr/lib64/mono-fuse/Mono.Fuse.dll
        /usr/lib64/libMonoFuseHelper.so

[1]
http://www.mono-project.com/Guidelines:Application_Deployment#Libraries_with_Unstable_APIs

Thanks,
 - Jon




More information about the Mono-list mailing list