2009-11-23 Andreas Faerber <andreas.faerber@web.de>
[mono.git] / mono / metadata / filewatcher.c
blob5016e52eb6808da1e9ee26310243ed9c94cd5cd9
1 /*
2 * filewatcher.c: File System Watcher internal calls
4 * Authors:
5 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
8 */
10 #ifdef HAVE_CONFIG_H
11 #include <config.h>
12 #endif
14 #include <mono/metadata/appdomain.h>
15 #include <mono/metadata/exception.h>
16 #include <mono/metadata/filewatcher.h>
17 #include <mono/metadata/marshal.h>
18 #include <mono/utils/mono-dl.h>
19 #ifdef HOST_WIN32
22 * TODO:
23 * We use the managed watcher on windows, so the code inside this #if is never used
25 gint
26 ves_icall_System_IO_FSW_SupportsFSW (void)
28 return 1;
31 gboolean
32 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
33 MonoString **filename,
34 gint *code,
35 gint *reqnum)
37 return FALSE;
40 #else
42 static int (*FAMNextEvent) (gpointer, gpointer);
44 gint
45 ves_icall_System_IO_FSW_SupportsFSW (void)
47 #if HAVE_KQUEUE
48 return 3;
49 #else
50 MonoDl *fam_module;
51 int lib_used = 4; /* gamin */
52 int inotify_instance;
53 void *iter;
54 char *err;
56 MONO_ARCH_SAVE_REGS;
58 inotify_instance = ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ();
59 if (inotify_instance != -1) {
60 close (inotify_instance);
61 return 5; /* inotify */
64 iter = NULL;
65 fam_module = mono_dl_open ("libgamin-1.so", MONO_DL_LAZY, NULL);
66 if (fam_module == NULL) {
67 lib_used = 2; /* FAM */
68 iter = NULL;
69 fam_module = mono_dl_open ("libfam.so", MONO_DL_LAZY, NULL);
72 if (fam_module == NULL)
73 return 0;
75 err = mono_dl_symbol (fam_module, "FAMNextEvent", (gpointer *) &FAMNextEvent);
76 g_free (err);
77 if (FAMNextEvent == NULL)
78 return 0;
80 return lib_used;
81 #endif
84 /* Almost copied from fam.h. Weird, I know */
85 typedef struct {
86 gint reqnum;
87 } FAMRequest;
89 typedef struct FAMEvent {
90 gpointer fc;
91 FAMRequest fr;
92 gchar *hostname;
93 gchar filename [PATH_MAX];
94 gpointer userdata;
95 gint code;
96 } FAMEvent;
98 gboolean
99 ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
100 MonoString **filename,
101 gint *code,
102 gint *reqnum)
104 FAMEvent ev;
106 MONO_ARCH_SAVE_REGS;
108 if (FAMNextEvent (conn, &ev) == 1) {
109 *filename = mono_string_new (mono_domain_get (), ev.filename);
110 *code = ev.code;
111 *reqnum = ev.fr.reqnum;
112 return TRUE;
115 return FALSE;
117 #endif
119 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) && !defined(__NR_inotify_init)
120 # if defined(__i386__)
121 # define __NR_inotify_init 291
122 # elif defined(__x86_64__)
123 # define __NR_inotify_init 253
124 # elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
125 # define __NR_inotify_init 275
126 # elif defined (__s390__) || defined (__s390x__)
127 # define __NR_inotify_init 284
128 # elif defined(__sparc__) || defined (__sparc64__)
129 # define __NR_inotify_init 151
130 # elif defined (__ia64__)
131 # define __NR_inotify_init 1277
132 # elif defined (__arm__)
133 # define __NR_inotify_init 316
134 # elif defined(__alpha__)
135 # define __NR_inotify_init 444
136 # endif
137 #ifdef __NR_inotify_init
138 # ifndef __NR_inotify_add_watch
139 # define __NR_inotify_add_watch (__NR_inotify_init + 1)
140 # endif
141 # ifndef __NR_inotify_rm_watch
142 # define __NR_inotify_rm_watch (__NR_inotify_init + 2)
143 # endif
144 #endif
145 #endif
147 #if !defined(__linux__) || !defined(__NR_inotify_init)
148 int ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
150 return -1;
153 int ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *directory, gint32 mask)
155 return -1;
158 int ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, int watch_descriptor)
160 return -1;
162 #else
163 #include <errno.h>
166 ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
168 return syscall (__NR_inotify_init);
172 ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 mask)
174 char *str;
175 int retval;
177 MONO_ARCH_SAVE_REGS;
179 if (name == NULL)
180 return -1;
182 str = mono_string_to_utf8 (name);
183 retval = syscall (__NR_inotify_add_watch, fd, str, mask);
184 if (retval < 0) {
185 switch (errno) {
186 case EACCES:
187 errno = ERROR_ACCESS_DENIED;
188 break;
189 case EBADF:
190 errno = ERROR_INVALID_HANDLE;
191 break;
192 case EFAULT:
193 errno = ERROR_INVALID_ACCESS;
194 break;
195 case EINVAL:
196 errno = ERROR_INVALID_DATA;
197 break;
198 case ENOMEM:
199 errno = ERROR_NOT_ENOUGH_MEMORY;
200 break;
201 case ENOSPC:
202 errno = ERROR_TOO_MANY_OPEN_FILES;
203 break;
204 default:
205 errno = ERROR_GEN_FAILURE;
206 break;
208 mono_marshal_set_last_error ();
210 g_free (str);
211 return retval;
215 ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
217 return syscall (__NR_inotify_rm_watch, fd, watch_descriptor);
219 #endif