2006-09-18 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / filewatcher.c
index 7f8deeaceeed5d6de2498dbafc17df014802f575..6952df40f216a96e863e58fecf1d19537c568ed7 100644 (file)
@@ -4,7 +4,7 @@
  * Authors:
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
- * (C) 2004 Novell, Inc. (http://www.novell.com)
+ * (C) 2004,2005,2006 Novell, Inc. (http://www.novell.com)
  */
 
 #ifdef HAVE_CONFIG_H
@@ -14,7 +14,7 @@
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/filewatcher.h>
-
+#include <mono/metadata/marshal.h>
 #if (defined (PLATFORM_WIN32) && WINVER >= 0x0400)
 
 /*
@@ -92,6 +92,7 @@ ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
 {
        return FALSE;
 }
+
 #else
 
 static int (*FAMNextEvent) (gpointer, gpointer);
@@ -104,12 +105,27 @@ ves_icall_System_IO_FSW_SupportsFSW (void)
 #else
        GModule *fam_module;
        gchar *filename;
+       int lib_used = 4; /* gamin */
+       int inotify_instance;
 
        MONO_ARCH_SAVE_REGS;
 
-       filename = g_module_build_path (NULL, "libfam.so.0");
+       inotify_instance = ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ();
+       if (inotify_instance != -1) {
+               close (inotify_instance);
+               return 5; /* inotify */
+       }
+
+       filename = g_module_build_path (NULL, "libgamin-1.so.0");
        fam_module = g_module_open (filename, G_MODULE_BIND_LAZY);
        g_free (filename);
+       if (fam_module == NULL) {
+               lib_used = 2; /* FAM */
+               filename = g_module_build_path (NULL, "libfam.so.0");
+               fam_module = g_module_open (filename, G_MODULE_BIND_LAZY);
+               g_free (filename);
+       }
+
        if (fam_module == NULL)
                return 0;
 
@@ -117,7 +133,7 @@ ves_icall_System_IO_FSW_SupportsFSW (void)
        if (FAMNextEvent == NULL)
                return 0;
 
-       return 2;
+       return lib_used;
 #endif
 }
 
@@ -177,6 +193,107 @@ ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
 
        return FALSE;
 }
+#endif
+
+#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) && !defined(__NR_inotify_init)
+#  if defined(__i386__)
+#     define __NR_inotify_init         291
+#  elif defined(__x86_64__)
+#     define __NR_inotify_init         253
+#  elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
+#     define __NR_inotify_init         275
+#  elif defined (__s390__) || defined (__s390x__)
+#     define __NR_inotify_init         284
+#  elif defined(__sparc__) || defined (__sparc64__)
+#     define __NR_inotify_init         151
+#  elif defined (__ia64__)
+#     define __NR_inotify_init         1277
+#  elif defined (__arm__)
+#     define __NR_inotify_init         316
+#  elif defined(__alpha__)
+#     define __NR_inotify_init         444
+#  endif
+#ifdef __NR_inotify_init
+#  ifndef __NR_inotify_add_watch
+#    define __NR_inotify_add_watch (__NR_inotify_init + 1)
+#  endif
+#  ifndef __NR_inotify_rm_watch
+#    define __NR_inotify_rm_watch (__NR_inotify_init + 2)
+#  endif
+#endif
+#endif
+
+#if !defined(__linux__) || !defined(__NR_inotify_init)
+int ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
+{
+       return -1;
+}
+
+int ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *directory, gint32 mask)
+{
+       return -1;
+}
 
+int ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, int watch_descriptor)
+{
+       return -1;
+}
+#else
+#include <errno.h>
+
+int
+ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
+{
+       return syscall (__NR_inotify_init);
+}
+
+int
+ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 mask)
+{
+       char *str;
+       int retval;
+
+       MONO_ARCH_SAVE_REGS;
+
+       if (name == NULL)
+               return -1;
+
+       str = mono_string_to_utf8 (name);
+       retval = syscall (__NR_inotify_add_watch, fd, str, mask);
+       if (retval < 0) {
+               switch (errno) {
+               case EACCES:
+                       errno = ERROR_ACCESS_DENIED;
+                       break;
+               case EBADF:
+                       errno = ERROR_INVALID_HANDLE;
+                       break;
+               case EFAULT:
+                       errno = ERROR_INVALID_ACCESS;
+                       break;
+               case EINVAL:
+                       errno = ERROR_INVALID_DATA;
+                       break;
+               case ENOMEM:
+                       errno = ERROR_NOT_ENOUGH_MEMORY;
+                       break;
+               case ENOSPC:
+                       errno = ERROR_TOO_MANY_OPEN_FILES;
+                       break;
+               default:
+                       errno = ERROR_GEN_FAILURE;
+                       break;
+               }
+               mono_marshal_set_last_error ();
+       }
+       g_free (str);
+       return retval;
+}
+
+int
+ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
+{
+       return syscall (__NR_inotify_rm_watch, fd, watch_descriptor);
+}
 #endif