Implemeneted imprecise.
[mono-project.git] / mono / metadata / filewatcher.c
blob69ab3a89fb081757fc6387f01bb7fbd81f15d1ed
1 /**
2 * \file
3 * File System Watcher internal calls
5 * Authors:
6 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include <config.h>
14 #if !ENABLE_NETCORE
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
18 #endif
19 #ifdef HAVE_SYS_EVENT_H
20 #include <sys/event.h>
21 #endif
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
26 #include <mono/metadata/appdomain.h>
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/filewatcher.h>
29 #include <mono/metadata/marshal.h>
30 #include <mono/metadata/icall-decl.h>
31 #include <mono/utils/mono-dl.h>
32 #include <mono/utils/mono-io-portability.h>
33 #include <mono/metadata/w32error.h>
35 #ifdef HOST_WIN32
38 * TODO:
39 * We use the managed watcher on windows, so the code inside this #if is never used
41 gint
42 ves_icall_System_IO_FSW_SupportsFSW (void)
44 return 1;
47 int
48 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
49 MonoStringHandleOut filename,
50 int *code,
51 int *reqnum, MonoError *error)
53 return FALSE;
56 #else
58 static int (*FAMNextEvent) (gpointer, gpointer);
60 #if defined(HAVE_SYS_INOTIFY_H)
61 #include <sys/inotify.h>
62 #endif
64 gint
65 ves_icall_System_IO_FSW_SupportsFSW (void)
67 #if defined(__APPLE__)
68 if (getenv ("MONO_DARWIN_USE_KQUEUE_FSW"))
69 return 3; /* kqueue */
70 else
71 return 6; /* CoreFX */
72 #elif defined(HAVE_SYS_INOTIFY_H)
73 int inotify_instance = inotify_init ();
74 if (inotify_instance == -1)
75 return 0; /* DefaultWatcher */
76 close (inotify_instance);
77 return 6; /* CoreFX */
78 #elif HAVE_KQUEUE
79 return 3; /* kqueue */
80 #else
81 MonoDl *fam_module;
82 int lib_used = 4; /* gamin */
83 char *err;
85 fam_module = mono_dl_open ("libgamin-1.so", MONO_DL_LAZY, NULL);
86 if (fam_module == NULL) {
87 lib_used = 2; /* FAM */
88 fam_module = mono_dl_open ("libfam.so", MONO_DL_LAZY, NULL);
91 if (fam_module == NULL)
92 return 0; /* DefaultWatcher */
94 err = mono_dl_symbol (fam_module, "FAMNextEvent", (gpointer *) &FAMNextEvent);
95 g_free (err);
96 if (FAMNextEvent == NULL)
97 return 0;
99 return lib_used; /* DefaultWatcher */
100 #endif
103 /* Almost copied from fam.h. Weird, I know */
104 typedef struct {
105 gint reqnum;
106 } FAMRequest;
108 typedef struct FAMEvent {
109 gpointer fc;
110 FAMRequest fr;
111 gchar *hostname;
112 gchar filename [PATH_MAX];
113 gpointer userdata;
114 gint code;
115 } FAMEvent;
118 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
119 MonoStringHandleOut filename,
120 int *code,
121 int *reqnum,
122 MonoError *error)
124 FAMEvent ev;
126 if (FAMNextEvent (conn, &ev) == 1) {
127 MONO_HANDLE_ASSIGN_RAW (filename, mono_string_new_checked (mono_domain_get (), ev.filename, error));
128 return_val_if_nok (error, FALSE);
129 *code = ev.code;
130 *reqnum = ev.fr.reqnum;
131 return TRUE;
134 return FALSE;
136 #endif
138 #if HAVE_KQUEUE
140 static void
141 interrupt_kevent (gpointer data)
143 int *kq_ptr = (int*)data;
145 /* Interrupt the kevent () call by closing the fd */
146 close (*kq_ptr);
147 /* Signal to managed code that the fd is closed */
148 *kq_ptr = -1;
152 * ves_icall_System_IO_KqueueMonitor_kevent_notimeout:
154 * Call kevent (), while handling runtime interruptions.
157 ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
159 int res;
160 gboolean interrupted;
162 mono_thread_info_install_interrupt (interrupt_kevent, kq_ptr, &interrupted);
163 if (interrupted) {
164 close (*kq_ptr);
165 *kq_ptr = -1;
166 return -1;
169 MONO_ENTER_GC_SAFE;
170 res = kevent (*kq_ptr, (const struct kevent*)changelist, nchanges, (struct kevent*)eventlist, nevents, NULL);
171 MONO_EXIT_GC_SAFE;
173 mono_thread_info_uninstall_interrupt (&interrupted);
175 return res;
178 #else
181 ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
183 g_assert_not_reached ();
184 return -1;
187 #endif /* #if HAVE_KQUEUE */
189 #endif /* !ENABLE_NETCORE */