Ravenports generated: 14 Oct 2022 17:40
[ravenports.git] / bucket_F9 / gamin
1 # Buildsheet autogenerated by ravenadm tool -- Do not edit.
2
3 NAMEBASE=               gamin
4 VERSION=                0.1.10
5 REVISION=               2
6 KEYWORDS=               devel
7 VARIANTS=               standard
8 SDESC[standard]=        Monitor files and directories for changes
9 HOMEPAGE=               https://gitlab.gnome.org/Archive/gamin
10 CONTACT=                Michael_Reim[kraileth@elderlinux.org]
11
12 DOWNLOAD_GROUPS=        main
13 SITES[main]=            https://download.gnome.org/sources/gamin/0.1/
14 DISTFILE[1]=            gamin-0.1.10.tar.gz:main
15 DF_INDEX=               1
16 SPKGS[standard]=        single
17
18 OPTIONS_AVAILABLE=      none
19 OPTIONS_STANDARD=       none
20
21 USES=                   gettext-runtime gmake libtool pkgconfig fbsd10fix
22 GNOME_COMPONENTS=       glib
23
24 LICENSE=                LGPL20+:single
25 LICENSE_TERMS=          single:{{WRKDIR}}/TERMS
26 LICENSE_FILE=           LGPL20+:{{WRKSRC}}/COPYING
27 LICENSE_AWK=            TERMS:"^$$"
28 LICENSE_SOURCE=         TERMS:{{WRKSRC}}/server/gam_poll_basic.c
29 LICENSE_SCHEME=         solo
30
31 FPC_EQUIVALENT=         devel/gamin
32
33 MUST_CONFIGURE=         gnu
34
35 SOVERSION=              0.1.10
36 PLIST_SUB=              FAMVERSION=0.0.0
37                         FAMMAJOR=0
38
39 CPPFLAGS=               -DHAVE_LINUX
40
41 post-install:
42         ${STRIP_CMD} ${STAGEDIR}${PREFIX}/lib/*.so*
43
44 [FILE:284:descriptions/desc.single]
45 Gamin is a file and directory monitoring system defined to be a subset of 
46 the FAM (File Alteration Monitor) system. This is a service provided by a 
47 library which allows to detect when a file or a directory has been 
48 modified.
49
50 It uses kqueue/kevent on FreeBSD and inotify on Linux.
51
52
53 [FILE:98:distinfo]
54 28085f0ae8be10eab582ff186af4fb0be92cc6c62b5cc19cd09b295c7c2899a1       653392 gamin-0.1.10.tar.gz
55
56
57 [FILE:236:manifests/plist.single]
58 include/fam.h
59 lib/
60  libfam.a
61  libfam.so
62  libfam.so.%%FAMMAJOR%%
63  libfam.so.%%FAMVERSION%%
64  libgamin-1.a
65  libgamin-1.so
66  libgamin-1.so.%%SOMAJOR%%
67  libgamin-1.so.%%SOVERSION%%
68  libgamin_shared.a
69 lib/pkgconfig/gamin.pc
70 libexec/gam_server
71
72
73 [FILE:247:patches/patch-lib_gam__event.h]
74 --- lib/gam_event.h.orig        2007-07-04 13:36:49 UTC
75 +++ lib/gam_event.h
76 @@ -3,6 +3,8 @@
77  #ifndef __MD_EVENT_H__
78  #define __MD_EVENT_H__
79  
80 +#define        G_CONST_RETURN  const
81 +
82  typedef enum {
83         GAMIN_EVENT_CHANGED = 1 << 4,
84         GAMIN_EVENT_CREATED = 1 << 5,
85
86
87 [FILE:4380:freebsd/patch-libgamin_gam__api.c]
88 --- libgamin/gam_api.c.orig     2007-08-27 03:21:03.000000000 -0700
89 +++ libgamin/gam_api.c  2013-02-16 15:51:11.927100135 -0800
90 @@ -14,6 +14,7 @@
91  #include <sys/socket.h>
92  #include <sys/un.h>
93  #include <sys/uio.h>
94 +#include <string.h>
95  #include "fam.h"
96  #include "gam_protocol.h"
97  #include "gam_data.h"
98 @@ -117,7 +118,11 @@
99      if (user_name[0] != 0)
100          return (user_name);
101  
102 +#ifdef RUN_AS_EUID
103 +    pw = getpwuid(geteuid());
104 +#else
105      pw = getpwuid(getuid());
106 +#endif
107  
108      if (pw != NULL) {
109         strncpy(user_name, pw->pw_name, 99);
110 @@ -224,7 +229,11 @@
111         free(dir);
112         return(0);
113      }
114 +#ifdef RUN_AS_EUID
115 +    if (st.st_uid != geteuid()) {
116 +#else
117      if (st.st_uid != getuid()) {
118 +#endif
119         gam_error(DEBUG_INFO,
120                   "Socket directory %s has different owner\n",
121                   dir);
122 @@ -301,7 +310,11 @@
123      if (ret < 0)
124         return(0);
125      
126 +#ifdef RUN_AS_EUID
127 +    if (st.st_uid != geteuid()) {
128 +#else
129      if (st.st_uid != getuid()) {
130 +#endif
131         gam_error(DEBUG_INFO,
132                   "Socket %s has different owner\n",
133                   path);
134 @@ -428,10 +441,10 @@
135  {
136      char data[2] = { 0, 0 };
137      int written;
138 -#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
139 -    struct {
140 +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
141 +    union {
142             struct cmsghdr hdr;
143 -           struct cmsgcred cred;
144 +           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
145      } cmsg;
146      struct iovec iov;
147      struct msghdr msg;
148 @@ -443,16 +456,16 @@
149      msg.msg_iov = &iov;
150      msg.msg_iovlen = 1;
151  
152 -    msg.msg_control = &cmsg;
153 -    msg.msg_controllen = sizeof (cmsg);
154 +    msg.msg_control = (caddr_t) &cmsg;
155 +    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
156      memset (&cmsg, 0, sizeof (cmsg));
157 -    cmsg.hdr.cmsg_len = sizeof (cmsg);
158 +    cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
159      cmsg.hdr.cmsg_level = SOL_SOCKET;
160      cmsg.hdr.cmsg_type = SCM_CREDS;
161  #endif
162  
163  retry:
164 -#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
165 +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
166      written = sendmsg(fd, &msg, 0);
167  #else
168      written = write(fd, &data[0], 1);
169 @@ -654,15 +667,20 @@
170      gid_t c_gid;
171  
172  #ifdef HAVE_CMSGCRED
173 -    struct {
174 +    struct cmsgcred *cred;
175 +    union {
176             struct cmsghdr hdr;
177 -           struct cmsgcred cred;
178 +           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
179      } cmsg;
180  #endif
181  
182 +#ifdef RUN_AS_EUID
183 +    s_uid = geteuid();
184 +#else
185      s_uid = getuid();
186 +#endif
187  
188 -#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
189 +#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED) && !defined(__FreeBSD__)
190      /* Set the socket to receive credentials on the next message */
191      {
192          int on = 1;
193 @@ -683,8 +701,8 @@
194  
195  #ifdef HAVE_CMSGCRED
196      memset(&cmsg, 0, sizeof(cmsg));
197 -    msg.msg_control = &cmsg;
198 -    msg.msg_controllen = sizeof(cmsg);
199 +    msg.msg_control = (caddr_t) &cmsg;
200 +    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
201  #endif
202  
203  retry:
204 @@ -701,7 +719,7 @@
205          goto failed;
206      }
207  #ifdef HAVE_CMSGCRED
208 -    if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
209 +    if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) || cmsg.hdr.cmsg_type != SCM_CREDS) {
210          GAM_DEBUG(DEBUG_INFO,
211                    "Message from recvmsg() was not SCM_CREDS\n");
212          goto failed;
213 @@ -727,9 +745,10 @@
214              goto failed;
215          }
216  #elif defined(HAVE_CMSGCRED)
217 -        c_pid = cmsg.cred.cmcred_pid;
218 -        c_uid = cmsg.cred.cmcred_euid;
219 -        c_gid = cmsg.cred.cmcred_groups[0];
220 +        cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
221 +        c_pid = cred->cmcred_pid;
222 +        c_uid = cred->cmcred_euid;
223 +        c_gid = cred->cmcred_groups[0];
224  #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
225          GAM_DEBUG(DEBUG_INFO,
226                    "Socket credentials not supported on this OS\n");
227 @@ -1288,14 +1307,17 @@
228  
229      // FIXME: drop and reacquire lock while blocked?
230      gamin_data_lock(conn);
231 -    if (!gamin_data_event_ready(conn)) {
232 +    while ((ret = gamin_data_event_ready(conn)) == 0) {
233          if (gamin_read_data(conn, fc->fd, 1) < 0) {
234             gamin_try_reconnect(conn, fc->fd);
235             FAMErrno = FAM_CONNECT;
236             return (-1);
237         }
238      }
239 -    ret = gamin_data_read_event(conn, fe);
240 +
241 +    if (ret > 0)
242 +        ret = gamin_data_read_event(conn, fe);
243 +
244      gamin_data_unlock(conn);
245  
246      if (ret < 0) {
247
248
249 [FILE:3112:freebsd/patch-libgamin_gam__fork.c]
250 --- libgamin/gam_fork.c.orig    2007-07-04 06:36:48.000000000 -0700
251 +++ libgamin/gam_fork.c 2013-02-16 20:37:31.298176973 -0800
252 @@ -42,6 +42,78 @@
253      return NULL;
254  }
255  
256 +#ifdef RUN_AS_EUID
257 +/**
258 + * gamin_drop_privileges
259 + *
260 + * Attempt to drop privileges to another user and group before forking
261 + * a copy of the gam server
262 + * 
263 + * Return 0 in case of success or -1 in case of detected error.
264 + */
265 +int
266 +gamin_drop_privileges(int to_uid, int to_gid)
267 +{
268 +    GAM_DEBUG(DEBUG_INFO, "Dropping privileges to %d:%d before forking server\n", to_uid, to_gid);
269 +
270 +    /* Get the current real user and group */
271 +    int from_uid = getuid();
272 +    int from_gid = getgid();
273 +
274 +    /* Make sure we were able to get the user and group values */
275 +    if ( from_uid == -1 || to_uid == -1 || from_gid == -1 || to_gid == -1 ) {
276 +        gam_error(DEBUG_INFO, "failed to get user or group info, unable to drop privileges\n");
277 +        return(-1);
278 +    }
279 +
280 +    /* Refuse to run setuid if it would escalate privileges */
281 +    if ( from_uid != 0 && to_uid == 0 )
282 +    {
283 +        gam_error(DEBUG_INFO, "refusing to escalate user privileges from=%d to=%d\n", from_uid, to_uid);
284 +        return(-1);
285 +    }
286 +
287 +    /* Refuse to run setgid if it would escalate privileges */
288 +    if ( from_gid != 0 && to_gid == 0 )
289 +    {
290 +        gam_error(DEBUG_INFO, "refusing to escalate group privileges from=%d to=%d\n", from_gid, to_gid);
291 +        return(-1);
292 +    }
293 +
294 +    /* Run setuid to drop privileges to the effective user */
295 +    if ( from_uid != to_uid ) {
296 +        GAM_DEBUG(DEBUG_INFO, "Attempting setuid from=%d to=%d\n", from_uid, to_uid);
297 +
298 +        /* run setuid and check for errors */
299 +        if (setuid(to_uid) == -1) {
300 +            gam_error(DEBUG_INFO, "failed to run setuid from=%d to=%d\n", from_uid, to_uid);
301 +            return(-1);
302 +        }
303 +    }
304 +    else {
305 +        GAM_DEBUG(DEBUG_INFO, "Already running as effective user, skipping setuid\n");
306 +    }
307 +
308 +    /* Run setgid to drop privileges to the effective group */
309 +    if ( from_gid != to_gid ) {
310 +        GAM_DEBUG(DEBUG_INFO, "Attempting setgid from=%d to=%d\n", from_gid, to_gid);
311 +
312 +        /* run setuid and check for errors */
313 +        if (setgid(to_gid) == -1) {
314 +            gam_error(DEBUG_INFO, "failed to run setgid from=%d to=%d\n", from_gid, to_gid);
315 +            return(-1);
316 +        }
317 +    }
318 +    else {
319 +        GAM_DEBUG(DEBUG_INFO, "Already running as effective group, skipping setgid\n");
320 +    }
321 +
322 +    GAM_DEBUG(DEBUG_INFO, "Succeeded in dropping privileges from %d:%d to %d:%d\n", from_uid, from_gid, to_uid, to_gid);
323 +
324 +    return(0);
325 +}
326 +#endif
327 +
328  /**
329   * gamin_fork_server:
330   * @fam_client_id: the client ID string to use
331 @@ -71,6 +143,13 @@
332          long open_max;
333         long i;
334  
335 +#ifdef RUN_AS_EUID
336 +        /* Drop privileges to the current effective uid/gid and return on failure */
337 +        if(gamin_drop_privileges( geteuid(), getegid() ) == -1) {
338 +            return(-1);
339 +        }
340 +#endif
341 +
342          /* don't hold open fd opened from the client of the library */
343         open_max = sysconf (_SC_OPEN_MAX);
344         for (i = 0; i < open_max; i++)
345
346
347 [FILE:313:freebsd/patch-libgamin_gam__fork.h]
348 --- libgamin/gam_fork.h.orig    2007-07-04 06:36:48.000000000 -0700
349 +++ libgamin/gam_fork.h 2013-02-16 20:38:00.328594608 -0800
350 @@ -32,6 +32,9 @@
351  #endif
352  
353  int            gamin_fork_server       (const char *fam_client_id);
354 +#ifdef RUN_AS_EUID
355 +int            gamin_drop_privileges   (int to_uid, int to_gid);
356 +#endif
357  
358  #ifdef __cplusplus
359  }
360
361
362 [FILE:4065:freebsd/patch-server_gam__channel.c]
363 --- server/gam_channel.c.orig   Tue Aug  9 12:17:39 2005
364 +++ server/gam_channel.c        Fri Feb 10 01:22:46 2006
365 @@ -7,6 +7,7 @@
366  #include <sys/stat.h>
367  #include <sys/un.h>
368  #include <sys/uio.h>
369 +#include <string.h>
370  #include "gam_error.h"
371  #include "gam_connection.h"
372  #include "gam_channel.h"
373 @@ -30,10 +31,10 @@ gam_client_conn_send_cred(int fd)
374  {
375      char data[2] = { 0, 0 };
376      int written;
377 -#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
378 -    struct {
379 +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
380 +    union {
381             struct cmsghdr hdr;
382 -           struct cmsgcred cred;
383 +           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
384      } cmsg;
385      struct iovec iov;
386      struct msghdr msg;
387 @@ -45,16 +46,16 @@ gam_client_conn_send_cred(int fd)
388      msg.msg_iov = &iov;
389      msg.msg_iovlen = 1;
390  
391 -    msg.msg_control = &cmsg;
392 -    msg.msg_controllen = sizeof (cmsg);
393 +    msg.msg_control = (caddr_t) &cmsg;
394 +    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
395      memset (&cmsg, 0, sizeof (cmsg));
396 -    cmsg.hdr.cmsg_len = sizeof (cmsg);
397 +    cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
398      cmsg.hdr.cmsg_level = SOL_SOCKET;
399      cmsg.hdr.cmsg_type = SCM_CREDS;
400  #endif
401  
402  retry:
403 -#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
404 +#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
405      written = sendmsg(fd, &msg, 0);
406  #else
407      written = write(fd, &data[0], 1);
408 @@ -95,15 +96,16 @@ gam_client_conn_check_cred(GIOChannel * 
409      gid_t c_gid;
410  
411  #ifdef HAVE_CMSGCRED
412 -    struct {
413 +    struct cmsgcred *cred;
414 +    union {
415             struct cmsghdr hdr;
416 -           struct cmsgcred cred;
417 +           char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
418      } cmsg;
419  #endif
420  
421      s_uid = getuid();
422  
423 -#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
424 +#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED) && !defined(__FreeBSD__)
425      /* Set the socket to receive credentials on the next message */
426      {
427          int on = 1;
428 @@ -124,8 +126,8 @@ gam_client_conn_check_cred(GIOChannel * 
429  
430  #ifdef HAVE_CMSGCRED
431      memset(&cmsg, 0, sizeof(cmsg));
432 -    msg.msg_control = &cmsg;
433 -    msg.msg_controllen = sizeof(cmsg);
434 +    msg.msg_control = (caddr_t) &cmsg;
435 +    msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
436  #endif
437  
438    retry:
439 @@ -142,7 +144,7 @@ gam_client_conn_check_cred(GIOChannel * 
440          goto failed;
441      }
442  #ifdef HAVE_CMSGCRED
443 -    if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
444 +    if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) || cmsg.hdr.cmsg_type != SCM_CREDS) {
445          GAM_DEBUG(DEBUG_INFO,
446                    "Message from recvmsg() was not SCM_CREDS\n");
447          goto failed;
448 @@ -168,9 +170,10 @@ gam_client_conn_check_cred(GIOChannel * 
449              goto failed;
450          }
451  #elif defined(HAVE_CMSGCRED)
452 -       c_pid = cmsg.cred.cmcred_pid;
453 -       c_uid = cmsg.cred.cmcred_euid;
454 -       c_gid = cmsg.cred.cmcred_groups[0];
455 +       cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
456 +       c_pid = cred->cmcred_pid;
457 +       c_uid = cred->cmcred_euid;
458 +       c_gid = cred->cmcred_groups[0];
459  #else /* !SO_PEERCRED && !HAVE_CMSGCRED */
460          GAM_DEBUG(DEBUG_INFO,
461                    "Socket credentials not supported on this OS\n");
462 @@ -620,6 +621,7 @@ gam_listen_unix_socket(const char *path)
463  {
464      int fd;
465      struct sockaddr_un addr;
466 +    struct stat st;
467  
468      fd = socket(PF_UNIX, SOCK_STREAM, 0);
469      if (fd < 0) {
470 @@ -640,8 +642,18 @@ gam_listen_unix_socket(const char *path)
471       * some extra protection checks. Also make sure the socket is created
472       * with restricted mode
473       */
474 -    if (!gam_check_secure_path(path)) {
475 +    if (!gam_check_secure_dir()) {
476 +       close(fd);
477         return (-1);
478 +    }
479 +
480 +    if (stat(path, &st) == 0) {
481 +        /* bind() will fail if the socket already exists */
482 +        if (unlink(path) < 0) {
483 +            GAM_DEBUG(DEBUG_INFO, "Failed to remove %s\n", path);
484 +            close(fd);
485 +            return (-1);
486 +        }
487      }
488      strncpy(&addr.sun_path[0], path, (sizeof(addr) - 4) - 1);
489      umask(0077);
490
491
492 [FILE:376:freebsd/patch-server_gam__eq.c]
493 --- server/gam_eq.c.orig        2012-05-13 19:42:20.257794534 +0400
494 +++ server/gam_eq.c     2012-05-13 19:44:41.228799909 +0400
495 @@ -124,7 +124,7 @@ gam_eq_flush (gam_eq_t *eq, GamConnDataP
496  {
497         gboolean done_work = FALSE;
498         if (!eq)
499 -               return;
500 +               return FALSE;
501  
502  #ifdef GAM_EQ_VERBOSE
503         GAM_DEBUG(DEBUG_INFO, "gam_eq: Flushing event queue for %s\n", gam_connection_get_pidname (conn));
504
505
506 [FILE:3702:freebsd/patch-server_gam__fs.c]
507 --- server/gam_fs.c.orig        2007-07-04 09:36:49.000000000 -0400
508 +++ server/gam_fs.c     2007-08-10 15:05:41.000000000 -0400
509 @@ -7,6 +7,11 @@
510  #include <string.h>
511  #include <errno.h>
512  #include <glib.h>
513 +#ifdef __FreeBSD__
514 +#include <sys/param.h>
515 +#include <sys/ucred.h>
516 +#include <sys/mount.h>
517 +#endif
518  #include "gam_error.h"
519  #include "gam_fs.h"
520  
521 @@ -21,9 +26,13 @@ typedef struct _gam_fs_properties {
522  typedef struct _gam_fs {
523         char *path;
524         char *fsname;
525 +       guint64 flags;
526  } gam_fs;
527  
528  static gboolean initialized = FALSE;
529 +#ifdef __FreeBSD__
530 +static gboolean initializing = FALSE;
531 +#endif
532  static GList *filesystems = NULL;
533  static GList *fs_props = NULL;
534  static struct stat mtab_sbuf;
535 @@ -110,6 +119,7 @@ gam_fs_filesystem_sort_cb (gconstpointer
536         return strlen(fsb->path) - strlen (fsa->path);
537  }
538  
539 +#ifdef __linux__
540  static void
541  gam_fs_scan_mtab (void)
542  {
543 @@ -165,10 +175,41 @@ gam_fs_scan_mtab (void)
544         gam_fs_free_filesystems ();
545         filesystems = g_list_sort (new_filesystems, gam_fs_filesystem_sort_cb);
546  }
547 +#endif
548 +
549 +#ifdef __FreeBSD__
550 +static void
551 +gam_fs_getmntinfo (void)
552 +{
553 +       struct statfs *stat;
554 +       GList *new_filesystems = NULL;
555 +       gam_fs *fs = NULL;
556 +        int i, n;
557 +
558 +       n = getmntinfo(&stat, MNT_NOWAIT);
559 +       if (n == -1)
560 +               return;
561 +
562 +       for (i = 0; i < n; i++)
563 +       {
564 +               fs = g_new0 (gam_fs, 1);
565 +               fs->path = g_strdup (stat[i].f_mntonname);
566 +               fs->fsname = g_strdup (stat[i].f_fstypename);
567 +               fs->flags = stat[i].f_flags;
568 +
569 +               new_filesystems = g_list_prepend (new_filesystems, fs);
570 +       }
571 +
572 +        /* Replace the old file systems list with the new one */
573 +        gam_fs_free_filesystems ();
574 +        filesystems = g_list_sort (new_filesystems, gam_fs_filesystem_sort_cb);
575 +}
576 +#endif
577  
578  void
579  gam_fs_init (void)
580  {
581 +#if defined(__linux__)
582         if (initialized == FALSE)
583         {
584                 initialized = TRUE;
585 @@ -181,6 +222,7 @@ gam_fs_init (void)
586                 if (stat("/etc/mtab", &mtab_sbuf) != 0)
587                 {
588                         GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/mtab\n");
589 +                        return;
590                 }
591                 gam_fs_scan_mtab ();
592         } else {
593 @@ -189,6 +231,7 @@ gam_fs_init (void)
594                 if (stat("/etc/mtab", &sbuf) != 0)
595                 {
596                         GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/mtab\n");
597 +                        return;
598                 }
599  
600                 /* /etc/mtab has changed */
601 @@ -199,6 +242,54 @@ gam_fs_init (void)
602  
603                 mtab_sbuf = sbuf;
604         }
605 +#elif defined(__FreeBSD__)
606 +       if (initialized == FALSE && initializing == FALSE)
607 +       {
608 +               GList *iterator = NULL;
609 +               GHashTable *fs_hash = NULL;
610 +               gam_fs *fs = NULL;
611 +
612 +               initialized = TRUE;
613 +               initializing = TRUE;
614 +
615 +               gam_fs_getmntinfo ();
616 +
617 +               iterator = filesystems;
618 +               fs_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
619 +
620 +               while (iterator) {
621 +                       fs = iterator->data;
622 +
623 +                       if (!g_hash_table_lookup (fs_hash, fs->fsname)) {
624 +                               if (fs->flags & MNT_LOCAL)
625 +                                       gam_fs_set (fs->fsname, GFS_MT_DEFAULT, 0);
626 +                               else
627 +                                       gam_fs_set (fs->fsname, GFS_MT_POLL, 5);
628 +
629 +                               g_hash_table_insert (fs_hash, g_strdup (fs->fsname), GINT_TO_POINTER (1));
630 +                       }
631 +
632 +                       iterator = g_list_next (iterator);
633 +               }
634 +
635 +               g_hash_table_destroy (fs_hash);
636 +               initializing = FALSE;
637 +       } else if (initializing == FALSE) {
638 +               struct stat sbuf;
639 +
640 +               if (stat ("/etc/fstab", &sbuf) != 0) {
641 +                       GAM_DEBUG(DEBUG_INFO, "Could not stat /etc/fstab\n");
642 +                       return;
643 +               }
644 +
645 +               if (sbuf.st_mtime != mtab_sbuf.st_mtime) {
646 +                       GAM_DEBUG(DEBUG_INFO, "Updating list of mounted filesystems\n");
647 +                       gam_fs_getmntinfo ();
648 +               }
649 +
650 +               mtab_sbuf = sbuf;
651 +       }
652 +#endif
653  }
654  
655  gam_fs_mon_type
656 @@ -210,7 +301,11 @@ gam_fs_get_mon_type (const char *path)
657         props = gam_fs_find_fs_props (path);
658  
659         if (!props)
660 +#ifdef USE_GAMIN_POLLER
661 +               return GFS_MT_POLL;
662 +#else
663                 return GFS_MT_DEFAULT;
664 +#endif
665  
666         return props->mon_type;
667  }
668
669
670 [FILE:10104:freebsd/patch-server_gam__kqueue.c]
671 --- server/gam_kqueue.c.orig    2007-07-04 09:50:41.000000000 -0400
672 +++ server/gam_kqueue.c 2009-06-03 13:43:38.000000000 -0400
673 @@ -5,7 +5,8 @@
674   *
675   *     * http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=0650&db=bks&fname=/SGI_Developer/books/IIDsktp_IG/sgi_html/ch08.html
676   *       states that FAM does not follow monitored symbolic links: we
677 - *       do the same (note that regarding
678 + *       do NOT do the same to preserve compatibility with SGI FAM (note
679 + *       that regarding
680   *       http://oss.sgi.com/bugzilla/show_bug.cgi?id=405, we do what
681   *       FAM should do: we do not call g_dir_open() if the file is a
682   *       symbolic link).
683 @@ -28,10 +29,9 @@
684   *           - kqueue needs to be augmented with a filename-based
685   *             monitoring facility;
686   *
687 - *           - kqueue needs to be moved out the UFS code.
688 - *
689   * Copyright (C) 2005 Joe Marcus Clarke <marcus@FreeBSD.org>
690 - * Copyright (C) 2005 Jean-Yves Lefort <jylefort@FreeBSD.org>
691 + * Copyright (C) 2005, 2006 Jean-Yves Lefort <jylefort@FreeBSD.org>
692 + * Copyright (C) 2006 Alex Dupre <ale@FreeBSD.org>
693   *
694   * This library is free software; you can redistribute it and/or
695   * modify it under the terms of the GNU Lesser General Public
696 @@ -53,6 +53,9 @@
697  #include <fcntl.h>
698  #include <unistd.h>
699  #include <sys/param.h>
700 +#ifndef USE_GAMIN_POLLER
701 +#include <sys/mount.h>
702 +#endif
703  #include <sys/types.h>
704  #include <sys/sysctl.h>
705  #include <sys/stat.h>
706 @@ -62,6 +65,7 @@
707  #include "gam_error.h"
708  #include "gam_kqueue.h"
709  #include "gam_event.h"
710 +#include "gam_excludes.h"
711  #include "gam_server.h"
712  #include "gam_poll_basic.h"
713  
714 @@ -130,7 +134,7 @@ typedef struct
715    HashTableRemoveFunc          remove;
716    HashTablePostRemoveFunc      post_remove;
717  } HashTableMethods;
718 -  
719 +
720  /*
721   * A hash table which can be modified while iterating over it.
722   */
723 @@ -281,8 +285,8 @@ static void
724  gam_kqueue_mini_lstat (const char *pathname, MiniStat *mini_sb)
725  {
726    struct stat sb;
727 -  
728 -  if (lstat(pathname, &sb) < 0)
729 +
730 +  if (stat(pathname, &sb) < 0)
731      memset(mini_sb, 0, sizeof(*mini_sb));
732    else
733      {
734 @@ -319,14 +323,14 @@ gam_kqueue_isdir (const char *pathname, 
735    else
736      {
737        struct stat sb;
738 -      return lstat(pathname, &sb) >= 0 && (sb.st_mode & S_IFDIR) != 0;
739 +      return stat(pathname, &sb) >= 0 && (sb.st_mode & S_IFDIR) != 0;
740      }
741  }
742  
743  static gboolean
744  gam_kqueue_get_uint_sysctl (const char *name, unsigned int *value)
745  {
746 -  unsigned int value_len = sizeof(*value);
747 +  size_t value_len = sizeof(*value);
748  
749    if (sysctlbyname(name, value, &value_len, (void *)NULL, 0) < 0)
750      {
751 @@ -406,7 +410,7 @@ gam_kqueue_hash_table_foreach (HashTable
752    table->iterating = TRUE;
753    g_hash_table_foreach(table->main, func, user_data);
754    table->iterating = FALSE;
755 -  
756 +
757    if (table->pending_additions)
758      {
759        GSList *l;
760 @@ -509,33 +513,52 @@ static gboolean
761  gam_kqueue_monitor_enable_kqueue (Monitor *mon)
762  {
763    struct kevent ev[1];
764 +#ifndef USE_GAMIN_POLLER
765 +  struct statfs sb;
766 +#endif
767  
768    if (open_files == max_open_files)
769      {
770        GAM_DEBUG(DEBUG_INFO, "cannot open %s (max_open_files limit reached), falling back to poll\n", mon->pathname);
771        return FALSE;
772      }
773 -  
774 -  mon->fd = open(mon->pathname, O_RDONLY | O_NOFOLLOW);
775 +
776 +  if (gam_exclude_check(mon->pathname))
777 +    {
778 +      GAM_DEBUG(DEBUG_INFO, "not using kqueue for %s since it is excluded, falling back to poll\n", mon->pathname);
779 +      return FALSE;
780 +    }
781 +
782 +  mon->fd = open(mon->pathname, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
783    if (mon->fd < 0)
784      {
785        GAM_DEBUG(DEBUG_INFO, "cannot open %s (%s), falling back to poll\n", mon->pathname, g_strerror(errno));
786        return FALSE;
787      }
788  
789 +#ifndef USE_GAMIN_POLLER
790 +  if (fstatfs(mon->fd, &sb) == 0 && (sb.f_flags & MNT_LOCAL) == 0)
791 +    {
792 +      GAM_DEBUG(DEBUG_INFO, "%s resides on a remote file system, falling back to poll\n", mon->pathname);
793 +      goto poll;
794 +    }
795 +#endif
796 +
797    EV_SET(ev, mon->fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, VN_NOTE_ALL, 0, mon);
798    if (kevent(kq, ev, G_N_ELEMENTS(ev), NULL, 0, NULL) < 0)
799      {
800        GAM_DEBUG(DEBUG_INFO, "cannot enable kqueue notification for %s (%s), falling back to poll\n", mon->pathname, g_strerror(errno));
801 -
802 -      close(mon->fd);
803 -      mon->fd = -1;
804 -
805 -      return FALSE;
806 +      goto poll;
807      }
808  
809    open_files++;
810    return TRUE;
811 +
812 + poll:
813 +  close(mon->fd);
814 +  mon->fd = -1;
815 +
816 +  return FALSE;
817  }
818  
819  static void
820 @@ -612,7 +635,7 @@ gam_kqueue_sub_monitor_free (SubMonitor 
821    gam_kqueue_poller_remove_sub_monitor(&missing_smon_poller, smon);
822    gam_kqueue_poller_remove_sub_monitor(&unsupported_smon_poller, smon);
823    /* unsupported_dirs_poller is handled by _clear_fmons() below */
824 -  
825 +
826    gam_kqueue_sub_monitor_clear_fmons(smon);
827    gam_kqueue_monitor_free(MONITOR(smon));
828  }
829 @@ -700,7 +723,7 @@ gam_kqueue_sub_monitor_enable_notificati
830      {
831        struct stat sb;
832  
833 -      exists = lstat(mon->pathname, &sb) >= 0;
834 +      exists = stat(mon->pathname, &sb) >= 0;
835        flags |= (exists && (sb.st_mode & S_IFDIR) != 0) ? MONITOR_ISDIR : MONITOR_ISNOTDIR;
836      }
837  
838 @@ -715,21 +738,21 @@ gam_kqueue_sub_monitor_enable_notificati
839         {
840           GDir *dir;
841           GError *err = NULL;
842 -         
843 +
844           dir = g_dir_open(mon->pathname, 0, &err);
845           if (dir)
846             {
847               const char *filename;
848 -             
849 +
850               while ((filename = g_dir_read_name(dir)))
851                 {
852                   FileMonitor *fmon;
853                   FileMonitorFlags fmon_flags;
854 -                 
855 +
856                   fmon = gam_kqueue_file_monitor_new(smon, filename, &fmon_flags);
857                   gam_kqueue_file_monitor_emit_event(fmon, gevent, fmon_flags);
858                 }
859 -             
860 +
861               g_dir_close(dir);
862             }
863           else
864 @@ -749,7 +772,7 @@ gam_kqueue_sub_monitor_enable_notificati
865  
866        return;
867      }
868 -    
869 +
870    /* then we enable kqueue notification, falling back to poll if necessary */
871  
872    if (! gam_kqueue_monitor_enable_kqueue(mon))
873 @@ -774,7 +797,7 @@ gam_kqueue_sub_monitor_handle_directory_
874  
875    filenames = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
876  
877 -  if (isdir)                   /* do not follow symbolic links */
878 +  if (isdir)
879      {
880        GDir *dir;
881        GError *err = NULL;
882 @@ -783,7 +806,7 @@ gam_kqueue_sub_monitor_handle_directory_
883        if (dir)
884         {
885           const char *filename;
886 -         
887 +
888           while ((filename = g_dir_read_name(dir)))
889             {
890               g_hash_table_insert(filenames, g_strdup(filename), GINT_TO_POINTER(TRUE));
891 @@ -793,12 +816,12 @@ gam_kqueue_sub_monitor_handle_directory_
892                 {
893                   FileMonitor *fmon;
894                   FileMonitorFlags fmon_flags;
895 -                 
896 +
897                   fmon = gam_kqueue_file_monitor_new(smon, filename, &fmon_flags);
898                   gam_kqueue_file_monitor_emit_event(fmon, GAMIN_EVENT_CREATED, fmon_flags);
899                 }
900             }
901 -         
902 +
903           g_dir_close(dir);
904         }
905        else
906 @@ -840,6 +863,8 @@ gam_kqueue_sub_monitor_emit_event (SubMo
907      case GAMIN_EVENT_MOVED:
908        gam_kqueue_sub_monitor_set_missing(smon);
909        break;
910 +    default:
911 +      break;
912      }
913  
914    gam_server_emit_event(mon->pathname, isdir, event, smon->subs, 1);
915 @@ -931,11 +956,11 @@ gam_kqueue_file_monitor_emit_event (File
916    gboolean isdir;
917    gboolean stat_done;
918    gboolean stat_succeeded;
919 -  
920 +
921    if ((flags & MONITOR_ISDIR) == 0 && (flags & MONITOR_ISNOTDIR) == 0)
922      {
923        stat_done = TRUE;
924 -      stat_succeeded = lstat(mon->pathname, &sb) >= 0;
925 +      stat_succeeded = stat(mon->pathname, &sb) >= 0;
926        isdir = stat_succeeded && (sb.st_mode & S_IFDIR) != 0;
927      }
928    else
929 @@ -943,7 +968,7 @@ gam_kqueue_file_monitor_emit_event (File
930        stat_done = FALSE;
931        isdir = (flags & MONITOR_ISDIR) != 0;
932      }
933 -  
934 +
935    gam_server_emit_event(mon->pathname, isdir, event, fmon->smon->subs, 1);
936  
937    switch (event)
938 @@ -962,7 +987,7 @@ gam_kqueue_file_monitor_emit_event (File
939             {
940               FileMonitor *new_fmon;
941               FileMonitorFlags new_fmon_flags;
942 -             
943 +
944               /*
945                * The file exists again. It means that kqueue has
946                * aggregated a removal+creation into a single event. We
947 @@ -978,9 +1003,11 @@ gam_kqueue_file_monitor_emit_event (File
948               break;            /* do not remove the fmon we've just created */
949             }
950         }
951 -       
952 +
953        gam_kqueue_hash_table_remove(fmon->smon->fmons, fmon);
954        break;
955 +    default:
956 +      break;
957      }
958  }
959  
960 @@ -1033,7 +1060,7 @@ gam_kqueue_kevent_cb (GIOChannel *source
961  
962    for (i = 0; i < nevents; i++)
963      MONITOR(ev[i].udata)->handle_kevent(MONITOR(ev[i].udata), &ev[i]);
964 -  
965 +
966    return TRUE;                 /* keep source */
967  }
968  
969 @@ -1042,7 +1069,7 @@ gam_kqueue_missing_smon_poll (SubMonitor
970  {
971    struct stat sb;
972  
973 -  if (lstat(MONITOR(smon)->pathname, &sb) >= 0)
974 +  if (stat(MONITOR(smon)->pathname, &sb) >= 0)
975      {
976        gam_kqueue_poller_remove_sub_monitor(&missing_smon_poller, smon);
977        gam_kqueue_sub_monitor_enable_notification(smon, SUB_MONITOR_WAS_MISSING | ((sb.st_mode & S_IFDIR) != 0 ? MONITOR_ISDIR : MONITOR_ISNOTDIR));
978 @@ -1062,16 +1089,16 @@ gam_kqueue_unsupported_smon_poll (SubMon
979        if (gam_kqueue_monitor_enable_kqueue(mon))
980         gam_kqueue_poller_remove_sub_monitor(&missing_smon_poller, smon);
981      }
982 -  
983 +
984    gam_kqueue_mini_lstat(mon->pathname, &sb);
985 -  
986 +
987    if (! sb.exists && mon->sb.exists)
988      event = GAMIN_EVENT_DELETED;
989    else if (gam_kqueue_differs(&sb, &mon->sb))
990      event = GAMIN_EVENT_CHANGED;
991    else
992      return;
993 -       
994 +
995    memcpy(&mon->sb, &sb, sizeof(sb));
996    gam_kqueue_sub_monitor_emit_event(smon, event, (sb.mode & S_IFDIR) != 0 ? MONITOR_ISDIR : MONITOR_ISNOTDIR);
997  }
998 @@ -1167,7 +1194,10 @@ gam_kqueue_init (void)
999    channel = g_io_channel_unix_new(kq);
1000    g_io_add_watch(channel, G_IO_IN, gam_kqueue_kevent_cb, NULL);
1001  
1002 -  
1003 +#ifdef USE_GAMIN_POLLER
1004 +  gam_poll_basic_init ();
1005 +#endif
1006 +
1007    gam_server_install_kernel_hooks(GAMIN_K_KQUEUE,
1008                                   gam_kqueue_add_subscription,
1009                                   gam_kqueue_remove_subscription,
1010 @@ -1200,7 +1230,7 @@ gam_kqueue_add_subscription (GamSubscrip
1011        smon->subs = g_list_append(smon->subs, sub);
1012        return TRUE;
1013      }
1014 -  
1015 +
1016    smon = gam_kqueue_sub_monitor_new(sub);
1017    smon->subs = g_list_append(smon->subs, sub);
1018  
1019 @@ -1260,6 +1290,6 @@ gam_kqueue_remove_all_for (GamListener *
1020        success = FALSE;
1021  
1022    g_list_free(subs);
1023 -  
1024 +
1025    return success;
1026  }
1027
1028
1029 [FILE:581:freebsd/patch-server_gam__poll__basic.c]
1030 --- server/gam_poll_basic.c.orig        2007-08-10 15:12:29.000000000 -0400
1031 +++ server/gam_poll_basic.c     2007-08-10 15:16:07.000000000 -0400
1032 @@ -345,7 +345,7 @@ gam_poll_basic_poll_file(GamNode * node)
1033  #ifdef ST_MTIM_NSEC
1034                 GAM_DEBUG(DEBUG_INFO, "%d %d : %d %d\n", node->sbuf.st_mtim.tv_sec, node->sbuf.st_mtim.tv_nsec, sbuf.st_mtim.tv_sec, sbuf.st_mtim.tv_nsec);
1035  #else
1036 -               GAM_DEBUG(DEBUG_INFO, "%d : %d\n", node->sbuf.st_mtime, sbuf.st_mtim.tv_nsec);
1037 +               GAM_DEBUG(DEBUG_INFO, "%d : %d\n", node->sbuf.st_mtime, sbuf.st_mtime);
1038  #endif /* ST_MTIM_NSEC */
1039  #endif /* VERBOSE_POLL */
1040         }
1041
1042
1043
1044 [FILE:1209:freebsd/patch-server_gam__server.c]
1045 --- server/gam_server.c.orig    2007-07-04 09:36:49.000000000 -0400
1046 +++ server/gam_server.c 2009-05-01 20:25:41.000000000 -0400
1047 @@ -32,7 +32,7 @@
1048  #include "gam_server.h"
1049  #include "gam_channel.h"
1050  #include "gam_subscription.h"
1051 -#include "gam_poll_generic.h"
1052 +#include "gam_poll_basic.h"
1053  #ifdef ENABLE_INOTIFY
1054  #include "gam_inotify.h"
1055  #endif
1056 @@ -200,7 +200,8 @@ gam_add_subscription(GamSubscription * s
1057                         return gam_poll_add_subscription (sub);
1058                 else
1059  #endif
1060 -                       return gam_kernel_add_subscription (sub);
1061 +                       /*return gam_kernel_add_subscription (sub);*/
1062 +                       return gam_poll_add_subscription (sub);
1063         } else {
1064                 gam_fs_mon_type type;
1065                 type = gam_fs_get_mon_type (path);
1066 @@ -243,7 +244,8 @@ gam_remove_subscription(GamSubscription 
1067                         return gam_poll_remove_subscription (sub);
1068                 else
1069  #endif
1070 -                       return gam_kernel_remove_subscription(sub);
1071 +                       /*return gam_kernel_remove_subscription(sub);*/
1072 +                       return gam_poll_remove_subscription (sub);
1073         } else {
1074                 gam_fs_mon_type type;
1075                 type = gam_fs_get_mon_type (path);
1076 @@ -438,7 +440,7 @@ gam_server_get_kernel_handler (void)
1077  GamPollHandler
1078  gam_server_get_poll_handler (void)
1079  {
1080 -       return __gam_kernel_handler;
1081 +       return __gam_poll_handler;
1082  }
1083  
1084  gboolean
1085
1086
1087 [FILE:997:freebsd/patch-tests_testing.c]
1088 --- tests/testing.c.orig        Thu Oct 27 10:51:03 2005
1089 +++ tests/testing.c     Tue Feb 14 17:46:01 2006
1090 @@ -376,11 +376,11 @@ processCommand(char *line, int no)
1091          }
1092          printf("chmod %s to %s\n", arg, arg2);
1093      } else if (!strcmp(command, "chown")) {
1094 +       struct stat sb;
1095          if (args != 3) {
1096              fprintf(stderr, "chown line %d: lacks path and owner\n", no);
1097              return (-1);
1098          }
1099 -               struct stat sb;
1100                 if (!lstat (arg, &sb)) {
1101                         ret = (S_ISLNK (sb.st_mode)) ?
1102                                 lchown(arg, strtol(arg2, NULL, 10), -1) :
1103 @@ -486,9 +486,9 @@ processCommand(char *line, int no)
1104              return (-1);
1105          }
1106          /*
1107 -         * wait at most 3 secs before declaring failure
1108 +         * wait at most 7 secs before declaring failure
1109           */
1110 -        while ((delay < 30) && (testState.nb_events < nb_events + count)) {
1111 +        while ((delay < 70) && (testState.nb_events < nb_events + count)) {
1112              debugLoop(100);
1113  
1114  /*         printf("+"); fflush(stdout); */
1115