2 * filewatcher.c: File System Watcher internal calls
5 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
8 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #ifdef HAVE_SYS_TYPES_H
16 #include <sys/types.h>
18 #ifdef HAVE_SYS_EVENT_H
19 #include <sys/event.h>
21 #ifdef HAVE_SYS_TIME_H
25 #include <mono/metadata/appdomain.h>
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/filewatcher.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/utils/mono-dl.h>
30 #include <mono/utils/mono-io-portability.h>
35 * We use the managed watcher on windows, so the code inside this #if is never used
38 ves_icall_System_IO_FSW_SupportsFSW (void)
44 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn
,
45 MonoString
**filename
,
54 static int (*FAMNextEvent
) (gpointer
, gpointer
);
57 ves_icall_System_IO_FSW_SupportsFSW (void)
63 int lib_used
= 4; /* gamin */
67 inotify_instance
= ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ();
68 if (inotify_instance
!= -1) {
69 close (inotify_instance
);
70 return 5; /* inotify */
73 fam_module
= mono_dl_open ("libgamin-1.so", MONO_DL_LAZY
, NULL
);
74 if (fam_module
== NULL
) {
75 lib_used
= 2; /* FAM */
76 fam_module
= mono_dl_open ("libfam.so", MONO_DL_LAZY
, NULL
);
79 if (fam_module
== NULL
)
82 err
= mono_dl_symbol (fam_module
, "FAMNextEvent", (gpointer
*) &FAMNextEvent
);
84 if (FAMNextEvent
== NULL
)
91 /* Almost copied from fam.h. Weird, I know */
96 typedef struct FAMEvent
{
100 gchar filename
[PATH_MAX
];
106 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn
,
107 MonoString
**filename
,
113 if (FAMNextEvent (conn
, &ev
) == 1) {
114 *filename
= mono_string_new (mono_domain_get (), ev
.filename
);
116 *reqnum
= ev
.fr
.reqnum
;
124 #ifndef HAVE_SYS_INOTIFY_H
125 int ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
130 int ves_icall_System_IO_InotifyWatcher_AddWatch (int fd
, MonoString
*directory
, gint32 mask
)
135 int ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd
, gint32 watch_descriptor
)
140 #include <sys/inotify.h>
144 ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
146 return inotify_init ();
150 ves_icall_System_IO_InotifyWatcher_AddWatch (int fd
, MonoString
*name
, gint32 mask
)
159 str
= mono_string_to_utf8_checked (name
, &error
);
160 if (mono_error_set_pending_exception (&error
))
162 path
= mono_portability_find_file (str
, TRUE
);
166 retval
= inotify_add_watch (fd
, path
, mask
);
170 errno
= ERROR_ACCESS_DENIED
;
173 errno
= ERROR_INVALID_HANDLE
;
176 errno
= ERROR_INVALID_ACCESS
;
179 errno
= ERROR_INVALID_DATA
;
182 errno
= ERROR_NOT_ENOUGH_MEMORY
;
185 errno
= ERROR_TOO_MANY_OPEN_FILES
;
188 errno
= ERROR_GEN_FAILURE
;
191 mono_marshal_set_last_error ();
200 ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd
, gint32 watch_descriptor
)
202 return inotify_rm_watch (fd
, watch_descriptor
);
209 interrupt_kevent (gpointer data
)
213 /* Interrupt the kevent () call by closing the fd */
215 /* Signal to managed code that the fd is closed */
220 * ves_icall_System_IO_KqueueMonitor_kevent_notimeout:
222 * Call kevent (), while handling runtime interruptions.
225 ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr
, gpointer changelist
, int nchanges
, gpointer eventlist
, int nevents
)
228 gboolean interrupted
;
230 mono_thread_info_install_interrupt (interrupt_kevent
, kq_ptr
, &interrupted
);
238 res
= kevent (*kq_ptr
, changelist
, nchanges
, eventlist
, nevents
, NULL
);
241 mono_thread_info_uninstall_interrupt (&interrupted
);
249 ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr
, gpointer changelist
, int nchanges
, gpointer eventlist
, int nevents
)
251 g_assert_not_reached ();
255 #endif /* #if HAVE_KQUEUE */