3 * File System Watcher internal calls
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.
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
19 #ifdef HAVE_SYS_EVENT_H
20 #include <sys/event.h>
22 #ifdef HAVE_SYS_TIME_H
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/utils/mono-dl.h>
31 #include <mono/utils/mono-io-portability.h>
32 #include <mono/metadata/w32error.h>
38 * We use the managed watcher on windows, so the code inside this #if is never used
41 ves_icall_System_IO_FSW_SupportsFSW (void)
47 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
48 MonoString **filename,
57 static int (*FAMNextEvent) (gpointer, gpointer);
60 ves_icall_System_IO_FSW_SupportsFSW (void)
66 int lib_used = 4; /* gamin */
70 inotify_instance = ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ();
71 if (inotify_instance != -1) {
72 close (inotify_instance);
73 return 5; /* inotify */
76 fam_module = mono_dl_open ("libgamin-1.so", MONO_DL_LAZY, NULL);
77 if (fam_module == NULL) {
78 lib_used = 2; /* FAM */
79 fam_module = mono_dl_open ("libfam.so", MONO_DL_LAZY, NULL);
82 if (fam_module == NULL)
85 err = mono_dl_symbol (fam_module, "FAMNextEvent", (gpointer *) &FAMNextEvent);
87 if (FAMNextEvent == NULL)
94 /* Almost copied from fam.h. Weird, I know */
99 typedef struct FAMEvent {
103 gchar filename [PATH_MAX];
109 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
110 MonoString **filename,
117 if (FAMNextEvent (conn, &ev) == 1) {
118 *filename = mono_string_new_checked (mono_domain_get (), ev.filename, &error);
120 *reqnum = ev.fr.reqnum;
121 if (mono_error_set_pending_exception (&error))
130 #ifndef HAVE_SYS_INOTIFY_H
131 int ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
136 int ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *directory, gint32 mask)
141 int ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
146 #include <sys/inotify.h>
150 ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
152 return inotify_init ();
156 ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 mask)
165 str = mono_string_to_utf8_checked (name, &error);
166 if (mono_error_set_pending_exception (&error))
168 path = mono_portability_find_file (str, TRUE);
172 retval = inotify_add_watch (fd, path, mask);
176 errno = ERROR_ACCESS_DENIED;
179 errno = ERROR_INVALID_HANDLE;
182 errno = ERROR_INVALID_ACCESS;
185 errno = ERROR_INVALID_DATA;
188 errno = ERROR_NOT_ENOUGH_MEMORY;
191 errno = ERROR_TOO_MANY_OPEN_FILES;
194 errno = ERROR_GEN_FAILURE;
197 mono_marshal_set_last_error ();
206 ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
208 return inotify_rm_watch (fd, watch_descriptor);
215 interrupt_kevent (gpointer data)
219 /* Interrupt the kevent () call by closing the fd */
221 /* Signal to managed code that the fd is closed */
226 * ves_icall_System_IO_KqueueMonitor_kevent_notimeout:
228 * Call kevent (), while handling runtime interruptions.
231 ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
234 gboolean interrupted;
236 mono_thread_info_install_interrupt (interrupt_kevent, kq_ptr, &interrupted);
244 res = kevent (*kq_ptr, changelist, nchanges, eventlist, nevents, NULL);
247 mono_thread_info_uninstall_interrupt (&interrupted);
255 ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
257 g_assert_not_reached ();
261 #endif /* #if HAVE_KQUEUE */