Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: gam_node.c
===================================================================
--- gam_node.c	(nonexistent)
+++ gam_node.c	(revision 5)
@@ -0,0 +1,380 @@
+/* Gamin
+ * Copyright (C) 2003 James Willcox, Corey Bowers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "server_config.h"
+#include <string.h>
+#include <glib.h>
+#include "gam_event.h"
+#include "gam_node.h"
+#include "gam_error.h"
+
+/**
+ * Create a new node
+ *
+ * @param path the path the node will represent
+ * @param sub an initial GamSubscription for the node, could be NULL
+ * @param is_dir whether the node is a directory or not
+ * @returns the new node
+ */
+GamNode *
+gam_node_new(const char *path, GamSubscription * sub, gboolean is_dir)
+{
+    GamNode *node;
+    node = g_new0(GamNode, 1);
+
+    node->path = g_strdup(path);
+    if (sub)
+        node->subs = g_list_prepend(NULL, sub);
+    else
+        node->subs = NULL;
+
+    node->is_dir = is_dir;
+    node->flags = 0;
+	node->checks = 0;
+
+    node->poll_time = gam_fs_get_poll_timeout (path);
+    node->mon_type = gam_fs_get_mon_type (path);
+	GAM_DEBUG(DEBUG_INFO, "g_n_n: node for %s using %s with poll timeout of %d\n", path, node->mon_type == GFS_MT_KERNEL ? "kernel" : "poll", node->poll_time);
+    return node;
+}
+
+/**
+ * Frees a node
+ *
+ * @param node the node
+ */
+void
+gam_node_free(GamNode * node)
+{
+    g_assert(node != NULL);
+    g_assert(node->subs == NULL);
+
+    g_free(node->path);
+    g_free(node);
+}
+
+/**
+ * Retrieves the parent of a given node
+ *
+ * @param node the node
+ * @returns the parent, or NULL if node has no parent
+ */
+GamNode *
+gam_node_parent(GamNode * node)
+{
+    GamNode *ret = NULL;
+
+    g_assert(node);
+
+    if (node->node && node->node->parent)
+        ret = (GamNode *) node->node->parent->data;
+
+    return ret;
+}
+
+/**
+ * Returns whether a node is a directory or not
+ *
+ * @param node the node
+ * @returns TRUE if the node is a directory, FALSE otherwise
+ */
+gboolean
+gam_node_is_dir(GamNode * node)
+{
+    g_assert(node);
+    return(node->is_dir);
+}
+
+/**
+ * Sets whether a node is a directory
+ *
+ * @param node the node
+ * @param is_dir whether the node is a directory
+ */
+void
+gam_node_set_is_dir(GamNode * node, gboolean is_dir)
+{
+    g_assert(node);
+    node->is_dir = is_dir;
+}
+
+/**
+ * Returns the path associated with a node
+ *
+ * @param node the node
+ * @returns the path.  The caller must keep a reference to node until
+ * it has finished with the string.  If it must keep it longer, it
+ * should makes its own copy.  The returned string must not be freed.
+ */
+const char *
+gam_node_get_path(GamNode * node)
+{
+    g_assert(node);
+    return node->path;
+}
+
+/**
+ * Returns the list of subscriptions to a node
+ *
+ * @param node the node
+ * @returns the list of #GamSubscription to the node
+ */
+GList *
+gam_node_get_subscriptions(GamNode * node)
+{
+    g_assert(node);
+    return node->subs;
+}
+
+/**
+ * Returns whether a node has any directory subscriptions
+ *
+ * @param node the node
+ * @returns TRUE if the node has directory subscriptions, FALSE otherwise
+ */
+gboolean
+gam_node_has_dir_subscriptions(GamNode * node)
+{
+    GList *s;
+
+    g_assert (node);
+    if (!(node->is_dir))
+        return(FALSE);
+    for (s = node->subs;s != NULL;s = s->next) {
+        if (gam_subscription_is_dir((GamSubscription *) s->data))
+	    return(TRUE);
+    }
+    return(FALSE);
+}
+
+/**
+ * Adds a subscription to a node
+ *
+ * @param node the node
+ * @param sub the subscription
+ * @returns TRUE on success, FALSE otherwise
+ */
+gboolean
+gam_node_add_subscription(GamNode * node, GamSubscription * sub)
+{
+    g_assert(node);
+    g_assert(sub);
+    g_assert(!g_list_find(node->subs, sub));
+
+    node->subs = g_list_prepend(node->subs, sub);
+
+    return TRUE;
+}
+
+/**
+ * Removes a subscription from a node
+ *
+ * @param node the node
+ * @param sub the subscription to remove
+ * @returns TRUE if the subscription was removed, FALSE otherwise
+ */
+gboolean
+gam_node_remove_subscription(GamNode * node, GamSubscription * sub)
+{
+    g_assert(node);
+    g_assert(g_list_find (node->subs, sub));
+
+    node->subs = g_list_remove_all(node->subs, sub);
+
+    return TRUE;
+}
+
+/**
+ * Sets the GNode associated with a node.  Should only be used by MdTree
+ *
+ * @param node the node
+ * @param gnode the GNode
+ */
+void
+gam_node_set_node(GamNode * node, GNode * gnode)
+{
+    g_assert(node);
+    node->node = gnode;
+}
+
+/**
+ * Gets the GNode associated with a node.  Should only be used by MdTree
+ *
+ * @param node the node
+ * @returns the GNode
+ */
+GNode *
+gam_node_get_node(GamNode * node)
+{
+    g_assert(node);
+    return node->node;
+}
+
+/**
+ * Set a flag on a node
+ *
+ * @param node the node
+ * @param flag the flag to set
+ */
+void
+gam_node_set_flag(GamNode * node, int flag)
+{
+    g_assert(node);
+    /* Make sure we set exactly one flag.  */
+    g_assert((flag & (flag - 1)) == 0);
+    node->flags |= flag;
+}
+
+/**
+ * Clears a flag from a node
+ *
+ * @param node the node
+ * @param flag the flag
+ */
+void
+gam_node_unset_flag(GamNode * node, int flag)
+{
+    g_assert(node);
+    /* Make sure we clear exactly one flag.  */
+    g_assert((flag & (flag - 1)) == 0);
+    node->flags &= ~flag;
+}
+
+/**
+ * Checks whether a flag is set on a node
+ *
+ * @param node the node
+ * @param flag the flag
+ * @returns TRUE if the flag is set, FALSE otherwise
+ */
+gboolean
+gam_node_has_flag(GamNode * node, int flag)
+{
+    g_assert(node);
+    /* Check exactly one flag.  */
+    g_assert((flag & (flag - 1)) == 0);
+    return node->flags & flag;
+}
+
+/**
+ * Set a pflag on a node
+ *
+ * @param node the node
+ * @param flag the flag to set
+ */
+void
+gam_node_set_pflag(GamNode * node, int flag)
+{
+    g_assert(node);
+    /* Make sure we set exactly one flag.  */
+    g_assert((flag & (flag - 1)) == 0);
+    node->pflags |= flag;
+}
+
+/**
+ * Clears a pflag from a node
+ *
+ * @param node the node
+ * @param flag the flag
+ */
+void
+gam_node_unset_pflag(GamNode * node, int flag)
+{
+    g_assert(node);
+    /* Make sure we clear exactly one flag.  */
+    g_assert((flag & (flag - 1)) == 0);
+    node->pflags &= ~flag;
+}
+
+/**
+ * Checks whether a pflag is set on a node
+ *
+ * @param node the node
+ * @param flag the flag
+ * @returns TRUE if the flag is set, FALSE otherwise
+ */
+gboolean
+gam_node_has_pflag(GamNode * node, int flag)
+{
+    g_assert(node);
+    /* Check exactly one flag.  */
+    g_assert((flag & (flag - 1)) == 0);
+    return node->pflags & flag;
+}
+
+/**
+ * Set the pflags on a node
+ *
+ * @param node the node
+ * @param flags the flags
+ */
+void
+gam_node_set_pflags(GamNode * node, int flags)
+{
+    g_assert(node);
+    node->pflags = flags;
+}
+
+
+/**
+ * Checks whether some pflags are set on a node
+ *
+ * @param node the node
+ * @param flags the flags
+ * @returns TRUE if the flag is set, FALSE otherwise
+ */
+gboolean
+gam_node_has_pflags(GamNode * node, int flags)
+{
+    g_assert(node);
+    return node->pflags & flags;
+}
+
+void
+gam_node_emit_event (GamNode *node, GaminEventType event)
+{
+	GList *l;
+	GamNode *parent;
+	GList *subs;
+	int is_dir_node = gam_node_is_dir(node);
+
+#ifdef VERBOSE_POLL
+	GAM_DEBUG(DEBUG_INFO, "Poll: emit events %d for %s\n", event, gam_node_get_path(node));
+#endif
+	subs = gam_node_get_subscriptions(node);
+
+	if (subs)
+		subs = g_list_copy(subs);
+
+	parent = gam_node_parent(node);
+	if (parent) {
+		GList *parent_subs = gam_node_get_subscriptions(parent);
+
+		for (l = parent_subs; l; l = l->next) {
+			if (!g_list_find(subs, l->data))
+				subs = g_list_prepend(subs, l->data);
+		}
+	}
+
+	gam_server_emit_event(gam_node_get_path(node), is_dir_node, event, subs, 0);
+
+	g_list_free(subs);
+}
+
+/** @} */
Index: gam_node.h
===================================================================
--- gam_node.h	(nonexistent)
+++ gam_node.h	(revision 5)
@@ -0,0 +1,107 @@
+
+#ifndef __GAM_NODE_H__
+#define __GAM_NODE_H__
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "gam_event.h"
+#include "gam_subscription.h"
+#include "gam_fs.h"
+
+G_BEGIN_DECLS
+
+#define FLAG_NEW_NODE 1 << 5
+
+/*
+ * Special monitoring modes (pflags)
+ */
+#define MON_MISSING 1 << 0  /* The resource is missing */
+#define MON_NOKERNEL    1 << 1  /* file(system) not monitored by the kernel */
+#define MON_BUSY    1 << 2  /* Too busy to be monitored by the kernel */
+#define MON_WRONG_TYPE  1 << 3  /* Expecting a directory and got a file */
+#define MON_ALL_PFLAGS (MON_MISSING|MON_NOKERNEL|MON_BUSY|MON_WRONG_TYPE)
+
+typedef struct _GamNode GamNode;
+
+typedef gboolean (*GamSubFilterFunc) (GamSubscription *sub);
+
+struct _GamNode {
+        /* the node informations proper */
+	char *path;		/* The file path */
+	GList *subs;		/* the list of subscriptions */
+	GNode *node;		/* pointer in the tree */
+	gboolean is_dir;	/* is that a directory or expected to be one */
+	int flags;		/* generic flags */
+	int poll_time;		/* How often this node should be polled */
+	gam_fs_mon_type mon_type; /* the type of notification that should be done */
+
+        /* what used to be stored in a separate data structure */
+	int checks;
+	int pflags;		/* A combination of MON_xxx flags */
+	time_t lasttime;	/* Epoch of last time checking was done */
+	int flow_on_ticks;	/* Number of ticks while flow control is on */
+	struct stat sbuf;	/* The stat() informations in last check */
+};
+
+
+GamNode               *gam_node_new                 (const char     *path,
+						   GamSubscription *initial_sub,
+						   gboolean        is_dir);
+
+void                  gam_node_free                (GamNode         *node);
+
+GamNode               *gam_node_parent              (GamNode         *node);
+
+gboolean              gam_node_is_dir              (GamNode         *node);
+
+void                  gam_node_set_is_dir          (GamNode         *node,
+						   gboolean        is_dir);
+	
+const char           *gam_node_get_path            (GamNode         *node);
+
+GList                *gam_node_get_subscriptions   (GamNode         *node);
+
+gboolean              gam_node_add_subscription    (GamNode         *node,
+						   GamSubscription *sub);
+
+gboolean              gam_node_remove_subscription (GamNode         *node,
+						   GamSubscription *sub);
+
+gboolean              gam_node_has_dir_subscriptions(GamNode * node);
+
+void                  gam_node_set_node            (GamNode         *node,
+						   GNode          *gnode);
+GNode                *gam_node_get_node            (GamNode         *node);
+
+void                  gam_node_set_data            (GamNode         *node,
+						   gpointer        data,
+						   GDestroyNotify  destroy);
+
+gpointer              gam_node_get_data            (GamNode         *node);
+
+void                  gam_node_set_flag            (GamNode         *node,
+						   int             flag);
+void                  gam_node_unset_flag          (GamNode         *node,
+						   int             flag);
+gboolean              gam_node_has_flag            (GamNode         *node,
+						   int             flag);
+
+void                  gam_node_set_pflag            (GamNode         *node,
+						     int             flag);
+void                  gam_node_unset_pflag          (GamNode         *node,
+						     int             flag);
+gboolean              gam_node_has_pflag            (GamNode         *node,
+						     int             flag);
+void                  gam_node_set_pflags           (GamNode         *node,
+						     int             flags);
+gboolean              gam_node_has_pflags           (GamNode         *node,
+						     int             flags);
+
+
+void	gam_node_emit_event (GamNode *node, GaminEventType event);
+
+
+G_END_DECLS
+
+#endif /* __GAM_NODE_H__ */
Index: gam_poll_basic.c
===================================================================
--- gam_poll_basic.c	(nonexistent)
+++ gam_poll_basic.c	(revision 5)
@@ -0,0 +1,437 @@
+/* Gamin
+ * Copyright (C) 2003 James Willcox, Corey Bowers
+ * Copyright (C) 2004 Daniel Veillard
+ * Copyright (C) 2005 John McCutchan
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "server_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <glib.h>
+#include "fam.h"
+#include "gam_error.h"
+#include "gam_tree.h"
+#include "gam_poll_basic.h"
+#include "gam_event.h"
+#include "gam_server.h"
+#include "gam_protocol.h"
+#include "gam_event.h"
+#include "gam_excludes.h"
+
+#define VERBOSE_POLL
+
+static gboolean gam_poll_basic_add_subscription(GamSubscription * sub);
+static gboolean gam_poll_basic_remove_subscription(GamSubscription * sub);
+static gboolean gam_poll_basic_remove_all_for(GamListener * listener);
+static GaminEventType gam_poll_basic_poll_file(GamNode * node);
+static gboolean gam_poll_basic_scan_callback(gpointer data);
+
+static gboolean scan_callback_running = FALSE;
+
+gboolean
+gam_poll_basic_init ()
+{
+	gam_poll_generic_init ();
+	gam_server_install_poll_hooks (GAMIN_P_BASIC,
+				       gam_poll_basic_add_subscription,
+				       gam_poll_basic_remove_subscription,
+				       gam_poll_basic_remove_all_for,
+				       gam_poll_basic_poll_file);
+
+	GAM_DEBUG(DEBUG_INFO, "basic poll backend initialized\n");
+	return TRUE;
+}
+
+/**
+ * Adds a subscription to be polled.
+ *
+ * @param sub a #GamSubscription to be polled
+ * @returns TRUE if adding the subscription succeeded, FALSE otherwise
+ */
+static gboolean
+gam_poll_basic_add_subscription(GamSubscription * sub)
+{
+	const char *path = gam_subscription_get_path (sub);
+	GamNode *node = gam_tree_get_at_path (gam_poll_generic_get_tree(), path);
+	int node_is_dir = FALSE;
+
+	gam_listener_add_subscription(gam_subscription_get_listener(sub), sub);
+	gam_poll_generic_update_time ();
+
+	if (!node)
+	{
+		node = gam_tree_add_at_path(gam_poll_generic_get_tree(), path, gam_subscription_is_dir(sub));
+	}
+
+	gam_node_add_subscription(node, sub);
+	node_is_dir = gam_node_is_dir(node);
+
+	if (node_is_dir)
+	{
+		gam_poll_generic_first_scan_dir(sub, node, path);
+	} else {
+		GaminEventType event;
+
+		event = gam_poll_basic_poll_file (node);
+		GAM_DEBUG(DEBUG_INFO, "New file subscription: %s event %d\n", path, event);
+
+		if ((event == 0) || (event == GAMIN_EVENT_EXISTS) ||
+		    (event == GAMIN_EVENT_CHANGED) ||
+		    (event == GAMIN_EVENT_CREATED))
+		{
+			if (gam_subscription_is_dir(sub)) {
+				/* we are watching a file but requested a directory */
+				gam_server_emit_one_event(path, node_is_dir, GAMIN_EVENT_DELETED, sub, 0);
+			} else {
+				gam_server_emit_one_event(path, node_is_dir, GAMIN_EVENT_EXISTS, sub, 0);
+			}
+		} else if (event != 0) {
+			gam_server_emit_one_event(path, node_is_dir, GAMIN_EVENT_DELETED, sub, 0);
+		}
+
+		gam_server_emit_one_event(path, node_is_dir, GAMIN_EVENT_ENDEXISTS, sub, 0);
+	}
+
+	if (gam_node_has_pflag (node, MON_MISSING))
+		gam_poll_generic_add_missing(node);
+
+	gam_poll_generic_add (node);
+
+	if (!scan_callback_running)
+	{
+	  scan_callback_running = TRUE;
+	  g_timeout_add (1000, gam_poll_basic_scan_callback, NULL);
+	}
+	
+	GAM_DEBUG(DEBUG_INFO, "Poll: added subscription for %s\n", path);
+	return TRUE;
+}
+
+static gboolean
+node_remove_directory_subscription(GamNode * node, GamSubscription * sub)
+{
+	GList *children, *l;
+	gboolean remove_dir;
+
+	GAM_DEBUG(DEBUG_INFO, "remove_directory_subscription %s\n", gam_node_get_path(node));
+
+	gam_node_remove_subscription(node, sub);
+
+	remove_dir = (gam_node_get_subscriptions(node) == NULL);
+
+	children = gam_tree_get_children(gam_poll_generic_get_tree(), node);
+	for (l = children; l; l = l->next) {
+		GamNode *child = (GamNode *) l->data;
+
+		if ((!gam_node_get_subscriptions(child)) && (remove_dir) &&
+		    (!gam_tree_has_children(gam_poll_generic_get_tree(), child))) 
+		{
+			gam_poll_generic_unregister_node (child);
+
+			gam_tree_remove(gam_poll_generic_get_tree(), child);
+		} else {
+			remove_dir = FALSE;
+		}
+	}
+
+	g_list_free(children);
+
+	/*
+	* do not remove the directory if the parent has a directory subscription
+	*/
+	remove_dir = ((gam_node_get_subscriptions(node) == NULL) && (!gam_node_has_dir_subscriptions(gam_node_parent(node))));
+
+	if (remove_dir) {
+		GAM_DEBUG(DEBUG_INFO, "  => remove_dir %s\n",
+		gam_node_get_path(node));
+	}
+	return remove_dir;
+}
+
+/**
+ * Removes a subscription which was being polled.
+ *
+ * @param sub a #GamSubscription to remove
+ * @returns TRUE if removing the subscription succeeded, FALSE otherwise
+ */
+static gboolean
+gam_poll_basic_remove_subscription(GamSubscription * sub)
+{
+	const char *path = gam_subscription_get_path (sub);
+	GamNode *node = gam_tree_get_at_path (gam_poll_generic_get_tree(), path);
+
+	if (node == NULL) {
+		/* free directly */
+		gam_subscription_free(sub);
+		return TRUE;
+	}
+
+	gam_subscription_cancel(sub);
+
+#ifdef VERBOSE_POLL
+	GAM_DEBUG(DEBUG_INFO, "Tree has %d nodes\n", gam_tree_get_size(gam_poll_generic_get_tree()));
+#endif
+	if (!gam_node_is_dir(node)) {
+		GAM_DEBUG(DEBUG_INFO, "Removing node %s\n", gam_subscription_get_path(sub));
+		gam_node_remove_subscription(node, sub);
+
+		if (!gam_node_get_subscriptions(node)) 
+		{
+			GamNode *parent;
+			gam_poll_generic_unregister_node (node);
+			g_assert (!gam_tree_has_children(gam_poll_generic_get_tree(), node));
+			parent = gam_node_parent(node);
+			if ((parent != NULL) && (!gam_node_has_dir_subscriptions(parent))) {
+				gam_tree_remove(gam_poll_generic_get_tree(), node);
+				gam_poll_generic_prune_tree(parent);
+			}
+		}
+	} else {
+		GAM_DEBUG(DEBUG_INFO, "Removing node %s\n", gam_subscription_get_path(sub));
+		if (node_remove_directory_subscription(node, sub)) {
+			GamNode *parent;
+
+			gam_poll_generic_unregister_node (node);
+			parent = gam_node_parent(node);
+			if (!gam_tree_has_children(gam_poll_generic_get_tree(), node)) {
+				gam_tree_remove(gam_poll_generic_get_tree(), node);
+			}
+
+			gam_poll_generic_prune_tree(parent);
+		}
+	}
+
+#ifdef VERBOSE_POLL
+	GAM_DEBUG(DEBUG_INFO, "Tree has %d nodes\n", gam_tree_get_size(gam_poll_generic_get_tree()));
+#endif
+
+	GAM_DEBUG(DEBUG_INFO, "Poll: removed subscription for %s\n", path);
+
+	gam_subscription_free(sub);
+	return TRUE;
+}
+
+/**
+ * Stop polling all subscriptions for a given #GamListener.
+ *
+ * @param listener a #GamListener
+ * @returns TRUE if removing the subscriptions succeeded, FALSE otherwise
+ */
+static gboolean
+gam_poll_basic_remove_all_for(GamListener * listener)
+{
+	GList *subs, *l = NULL;
+
+	subs = gam_listener_get_subscriptions(listener);
+	for (l = subs; l; l = l->next) {
+		GamSubscription *sub = l->data;
+		g_assert(sub != NULL);
+		gam_poll_remove_subscription(sub);
+	}
+
+	if (subs) {
+		g_list_free(subs);
+		return TRUE;
+	} else
+		return FALSE;
+}
+
+static gboolean
+gam_poll_generic_node_changed (GamNode *node, struct stat sbuf)
+{
+	g_assert(node);
+#ifdef ST_MTIM_NSEC
+	return ((node->sbuf.st_mtim.tv_sec != sbuf.st_mtim.tv_sec) ||
+		(node->sbuf.st_mtim.tv_nsec != sbuf.st_mtim.tv_nsec) ||
+		(node->sbuf.st_size != sbuf.st_size) ||
+		(node->sbuf.st_ctim.tv_sec != sbuf.st_ctim.tv_sec) ||
+		(node->sbuf.st_ctim.tv_nsec != sbuf.st_ctim.tv_nsec));
+#else
+	return ((node->sbuf.st_mtime != sbuf.st_mtime) ||
+		(node->sbuf.st_size != sbuf.st_size) ||
+		(node->sbuf.st_ctime != sbuf.st_ctime));
+#endif
+}
+
+static GaminEventType
+gam_poll_basic_poll_file(GamNode * node)
+{
+	GaminEventType event;
+	struct stat sbuf;
+	int stat_ret;
+	const char *path = NULL;
+
+	g_assert (node);
+
+	path = gam_node_get_path(node);
+	/* If not enough time has passed since the last time we polled this node, stop here */
+	if (node->lasttime && gam_poll_generic_get_delta_time (node->lasttime) < node->poll_time)
+	{
+		GAM_DEBUG(DEBUG_INFO, "poll-basic: not enough time passed for %s\n", path);
+		return 0;
+	} else {
+		GAM_DEBUG(DEBUG_INFO, "poll-basic: %d && %d < %d\n", node->lasttime, gam_poll_generic_get_delta_time (node->lasttime), node->poll_time);
+	}
+
+#ifdef VERBOSE_POLL
+	GAM_DEBUG(DEBUG_INFO, "Poll: poll_file for %s called\n", path);
+#endif
+	memset(&sbuf, 0, sizeof(struct stat));
+	if (node->lasttime == 0) 
+	{
+#ifdef VERBOSE_POLL
+		GAM_DEBUG(DEBUG_INFO, "Poll: file is new\n");
+#endif
+		stat_ret = stat(node->path, &sbuf);
+
+		if (stat_ret != 0)
+			gam_node_set_pflag (node, MON_MISSING);
+		else
+			gam_node_set_is_dir(node, (S_ISDIR(sbuf.st_mode) != 0));
+
+		memcpy(&(node->sbuf), &(sbuf), sizeof(struct stat));
+
+		node->lasttime = gam_poll_generic_get_time ();
+
+		if (stat_ret == 0)
+			return 0;
+		else
+			return GAMIN_EVENT_DELETED;
+	}
+
+	event = 0;
+	node->lasttime = gam_poll_generic_get_time ();
+
+	stat_ret = stat(node->path, &sbuf);
+	if (stat_ret != 0) {
+		if ((gam_errno() == ENOENT) && (!gam_node_has_pflag(node, MON_MISSING))) {
+			/* deleted */
+			gam_node_set_pflags (node, MON_MISSING);
+
+			gam_poll_generic_remove_busy(node);
+			gam_poll_generic_add_missing(node);
+			event = GAMIN_EVENT_DELETED;
+		}
+	} else if (gam_node_has_pflag (node, MON_MISSING)) {
+		/* created */
+		gam_node_unset_pflag (node, MON_MISSING);
+		event = GAMIN_EVENT_CREATED;
+		gam_poll_generic_remove_missing (node);
+	} else if (gam_poll_generic_node_changed (node, sbuf)) {
+		event = GAMIN_EVENT_CHANGED;
+	} else {
+#ifdef VERBOSE_POLL
+		GAM_DEBUG(DEBUG_INFO, "Poll: poll_file %s unchanged\n", path);
+#ifdef ST_MTIM_NSEC
+		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);
+#else
+		GAM_DEBUG(DEBUG_INFO, "%d : %d\n", node->sbuf.st_mtime, sbuf.st_mtime);
+#endif /* ST_MTIM_NSEC */
+#endif /* VERBOSE_POLL */
+	}
+
+	/*
+	* TODO: handle the case where a file/dir is removed and replaced by
+	*       a dir/file
+	*/
+	if (stat_ret == 0)
+		gam_node_set_is_dir(node, (S_ISDIR(sbuf.st_mode) != 0));
+
+	memcpy(&(node->sbuf), &(sbuf), sizeof(struct stat));
+	node->sbuf.st_mtime = sbuf.st_mtime; // VALGRIND!
+
+	return event;
+}
+
+static gboolean
+gam_poll_basic_scan_callback(gpointer data)
+{
+	int idx;
+	gboolean did_something = FALSE;
+
+	gam_poll_generic_update_time ();
+
+	for (idx = 0;; idx++) 
+	{
+		/*
+		 * do not simply walk the list as it may be modified in the callback
+		 */
+		GamNode *node = (GamNode *) g_list_nth_data(gam_poll_generic_get_all_list(), idx);
+
+		if (node == NULL)
+			break;
+
+		g_assert (node);
+
+		did_something = TRUE;
+		
+		if (node->is_dir) {
+			gam_poll_generic_scan_directory_internal(node);
+		} else {
+			GaminEventType event = gam_poll_basic_poll_file (node);
+			gam_node_emit_event(node, event);
+		}
+	}
+
+	/*
+	* do not simply walk the list as it may be modified in the callback
+	*/
+	for (idx = 0;; idx++)
+	{
+		GamNode *node = g_list_nth_data(gam_poll_generic_get_missing_list(), idx);
+
+		if (node == NULL)
+			break;
+
+		g_assert (node);
+
+		did_something = TRUE;
+		
+#ifdef VERBOSE_POLL
+		GAM_DEBUG(DEBUG_INFO, "Checking missing file %s\n", node->path);
+#endif
+		if (node->is_dir) {
+			gam_poll_generic_scan_directory_internal(node);
+		} else {
+			GaminEventType event = gam_poll_basic_poll_file (node);
+			gam_node_emit_event(node, event);
+		}
+
+		/*
+		* if the resource exists again and is not in a special monitoring
+		* mode then switch back to dnotify for monitoring.
+		*/
+		if (!gam_node_has_pflags (node, MON_MISSING)) 
+		{
+			gam_poll_generic_remove_missing(node);
+			gam_poll_generic_add (node);
+		}
+	}
+
+	if (!did_something) {
+	  scan_callback_running = FALSE;
+	  return FALSE;
+	}
+	
+	return TRUE;
+}
Index: gam_subscription.c
===================================================================
--- gam_subscription.c	(nonexistent)
+++ gam_subscription.c	(revision 5)
@@ -0,0 +1,355 @@
+/* Marmot
+ * Copyright (C) 2003 James Willcox, Corey Bowers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include "server_config.h"
+#include <sys/types.h>
+#include <string.h>
+#include <glib.h>
+#include "gam_event.h"
+#include "gam_listener.h"
+#include "gam_subscription.h"
+#include "gam_protocol.h"
+#include "gam_event.h"
+#include "gam_error.h"
+
+//#define GAM_SUB_VERBOSE
+
+struct _GamSubscription {
+    char *path;
+    int events;
+    int reqno;
+    int pathlen;
+    int options;
+
+    gboolean is_dir;
+    gboolean cancelled;
+
+    GamListener *listener;
+};
+
+
+/**
+ * @defgroup GamSubscription GamSubscription
+ * @ingroup Daemon
+ * @brief GamSubscription API.
+ *
+ * A #GamSubscription represents a single monitoring request (or "subscription").
+ *
+ * @{
+ */
+
+/**
+ * Creates a new GamSubscription
+ *
+ * @param path the path to be monitored
+ * @param events the events that are accepted
+ * @param is_dir whether the subscription is for a directory or not
+ * @returns the new GamSubscription
+ */
+GamSubscription *
+gam_subscription_new(const char *path,
+                     int events,
+                     int reqno,
+                     gboolean is_dir,
+		     int options)
+{
+    GamSubscription *sub;
+
+    sub = g_new0(GamSubscription, 1);
+    sub->path = g_strdup(path);
+    sub->events = events;
+    sub->reqno = reqno;
+    sub->pathlen = strlen(path);
+
+    /* everyone accepts this */
+    gam_subscription_set_event(sub, GAMIN_EVENT_EXISTS | GAMIN_EVENT_ENDEXISTS);
+
+    sub->is_dir = is_dir;
+    sub->options = options;
+
+#ifdef GAM_SUB_VERBOSE
+    GAM_DEBUG(DEBUG_INFO, "Created subscription for %s\n", path);
+#endif
+    return sub;
+}
+
+/**
+ * Frees a GamSubscription
+ *
+ * @param sub the GamSubscription
+ */
+void
+gam_subscription_free(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return;
+#ifdef GAM_SUB_VERBOSE
+    GAM_DEBUG(DEBUG_INFO, "Freeing subscription for %s\n", sub->path);
+#endif
+
+    g_free(sub->path);
+    g_free(sub);
+}
+
+/**
+ * Tells if a GamSubscription is for a directory or not
+ *
+ * @param sub the GamSubscription
+ * @returns TRUE if the subscription is for a directory, FALSE otherwise
+ */
+gboolean
+gam_subscription_is_dir(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return(FALSE);
+    return sub->is_dir;
+}
+
+/**
+ * Provide the path len for a GamSubscription
+ *
+ * @param sub the GamSubscription
+ * @returns the path len for the subscription
+ */
+int
+gam_subscription_pathlen(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return(-1);
+    return sub->pathlen;
+}
+
+/**
+ * Gets the path for a GamSubscription
+ *
+ * @param sub the GamSubscription
+ * @returns The path being monitored.  It should not be freed.
+ */
+const char *
+gam_subscription_get_path(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return(NULL);
+    return sub->path;
+}
+
+/**
+ * Gets the request number for a GamSubscription
+ *
+ * @param sub the GamSubscription
+ * @returns The request number
+ */
+int
+gam_subscription_get_reqno(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return(-1);
+    return sub->reqno;
+}
+
+/**
+ * Gets the GamListener which owns this GamSubscription
+ *
+ * @param sub the GamSubscription
+ * @returns the GamListener, or NULL
+ */
+GamListener *
+gam_subscription_get_listener(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return(NULL);
+    return sub->listener;
+}
+
+/**
+ * Sets the GamListener which is owned by this GamSubscription
+ *
+ * @param sub the GamSubscription
+ * @param listener the GamListener
+ */
+void
+gam_subscription_set_listener(GamSubscription * sub,
+                              GamListener * listener)
+{
+    if (sub == NULL)
+        return;
+
+	GAM_DEBUG(DEBUG_INFO, "%s listening for %s\n", gam_listener_get_pidname (listener), sub->path);
+    sub->listener = listener;
+}
+
+/**
+ * Set the events this GamSubscription is interested in
+ *
+ * @param sub the GamSubscription
+ * @param event an ORed combination of the events desired
+ */
+void
+gam_subscription_set_event(GamSubscription * sub, int event)
+{
+    if (sub == NULL)
+        return;
+    sub->events |= event;
+}
+
+/**
+ * Removes an event from the set of acceptable events
+ *
+ * @param sub the GamSubscription
+ * @param event the event to remove
+ */
+void
+gam_subscription_unset_event(GamSubscription * sub, int event)
+{
+    if (sub == NULL)
+        return;
+    sub->events &= ~event;
+}
+
+/**
+ *  
+ * @param sub the GamSubscription
+ * @param event the event to test for
+ * @returns Whether or not this subscription accepts a given event
+ */
+gboolean
+gam_subscription_has_event(GamSubscription * sub, int event)
+{
+    if (sub == NULL)
+        return(FALSE);
+    return((sub->events & event) != 0);
+}
+
+/**
+ *  
+ * @param sub the GamSubscription
+ * @option option
+ * @returns Whether or not this subscription has that option.
+ */
+gboolean
+gam_subscription_has_option(GamSubscription * sub, int option)
+{
+    if (sub == NULL)
+        return(FALSE);
+    return((sub->options & option) != 0);
+}
+
+/**
+ * Mark this GamSubscription as cancelled
+ *
+ * @param sub the GamSubscription
+ */
+void
+gam_subscription_cancel(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return;
+	GAM_DEBUG(DEBUG_INFO, "%s not listening for %s\n", gam_listener_get_pidname (sub->listener), sub->path);
+    sub->cancelled = TRUE;
+}
+
+/**
+ * Checks if the GamSubscription is cancelled or not
+ *
+ * @param sub the GamSubscription
+ * @returns TRUE if the GamSubscription is cancelled, FALSE otherwise
+ */
+gboolean
+gam_subscription_is_cancelled(GamSubscription * sub)
+{
+    if (sub == NULL)
+        return(TRUE);
+    return sub->cancelled == TRUE;
+}
+
+/**
+ * gam_subscription_wants_event:
+ * @sub: the GamSubscription
+ * @name: file name (just the base name, not the complete path)
+ * @is_dir_node: is the target a directory
+ * @event: the event
+ * @force: force the event as much as possible
+ *
+ * Checks if a given path/event combination is accepted by this GamSubscription
+ *
+ * Returns TRUE if the combination is accepted, FALSE otherwise
+ */
+gboolean
+gam_subscription_wants_event(GamSubscription * sub,
+                             const char *name, int is_dir_node, 
+			     GaminEventType event, int force)
+{
+    int same_path = 0;
+
+    if ((sub == NULL) || (name == NULL) || (event == 0))
+        return(FALSE);
+    if (sub->cancelled)
+        return FALSE;
+
+    if ((sub->options & GAM_OPT_NOEXISTS) &&
+        ((event == GAMIN_EVENT_EXISTS) ||
+	 (event == GAMIN_EVENT_ENDEXISTS)))
+	return FALSE;
+
+    /* only directory listening cares for other files */
+    same_path = !strcmp(name, sub->path);
+    if ((sub->is_dir == 0) && (!same_path))
+        return(FALSE);
+
+    if (!gam_subscription_has_event(sub, event)) {
+        return FALSE;
+    }
+
+    if (force)
+        return TRUE;
+    if ((sub->is_dir) && (is_dir_node) && (same_path)) {
+        if ((event == GAMIN_EVENT_EXISTS) ||
+	    (event == GAMIN_EVENT_CHANGED) ||
+	    (event == GAMIN_EVENT_ENDEXISTS))
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+/**
+ * gam_subscription_debug:
+ * @sub: the subscription
+ *
+ * Provide debug output for that subscription node/state
+ */
+void
+gam_subscription_debug(GamSubscription *sub) {
+#ifdef GAM_DEBUG_ENABLED
+    if (sub == NULL) {
+	GAM_DEBUG(DEBUG_INFO, "    Subscription is NULL\n");
+        return;
+    }
+    GAM_DEBUG(DEBUG_INFO,
+              "    Subscription %d reqno %d events %d dir %d: %s\n",
+              sub->reqno, sub->events, sub->events, sub->is_dir, sub->path);
+#endif
+}
+
+void
+gam_subscription_shutdown ()
+{
+}
+
+/** @} */
Index: gam_subscription.h
===================================================================
--- gam_subscription.h	(nonexistent)
+++ gam_subscription.h	(revision 5)
@@ -0,0 +1,54 @@
+
+#ifndef __GAM_SUBSCRIPTION_H__
+#define __GAM_SUBSCRIPTION_H__
+
+#include <glib.h>
+#include "gam_event.h"
+#include "gam_listener.h"
+
+G_BEGIN_DECLS
+
+GamSubscription     *gam_subscription_new          (const char *path,
+						    int         events,
+						    int         reqno,
+						    gboolean    is_dir,
+						    int         options);
+
+void                 gam_subscription_free         (GamSubscription *sub);
+
+gboolean             gam_subscription_is_dir       (GamSubscription *sub);
+int                  gam_subscription_pathlen      (GamSubscription *sub);
+
+int                  gam_subscription_get_reqno    (GamSubscription *sub);
+
+const char          *gam_subscription_get_path     (GamSubscription *sub);
+
+GamListener         *gam_subscription_get_listener (GamSubscription *sub);
+
+void                 gam_subscription_set_listener (GamSubscription *sub,
+						    GamListener     *listener);
+
+void                 gam_subscription_set_event    (GamSubscription *sub,
+						    int              event);
+void                 gam_subscription_unset_event  (GamSubscription *sub,
+						    int              event);
+gboolean             gam_subscription_has_event    (GamSubscription *sub,
+						    int              event);
+
+gboolean             gam_subscription_has_option   (GamSubscription * sub,
+						    int              option);
+void                 gam_subscription_cancel       (GamSubscription *sub);
+gboolean             gam_subscription_is_cancelled (GamSubscription *sub);
+
+gboolean             gam_subscription_wants_event  (GamSubscription *sub,
+						    const char      *name,
+						    int          is_dir_node,
+						    GaminEventType   event,
+						    int force);
+void                 gam_subscription_debug        (GamSubscription *sub);
+
+void				gam_subscription_shutdown ();
+
+G_END_DECLS
+
+#endif /* __GAM_SUBSCRIPTION_H__ */
Index: inotify-helper.c
===================================================================
--- inotify-helper.c	(nonexistent)
+++ inotify-helper.c	(revision 5)
@@ -0,0 +1,210 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* inotify-helper.c - Gnome VFS Monitor based on inotify.
+
+   Copyright (C) 2005 John McCutchan
+
+   The Gnome Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Authors: 
+		 John McCutchan <john@johnmccutchan.com>
+*/
+
+#include "config.h"
+#include <errno.h>
+#include <time.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/inotify.h>
+#include "inotify-helper.h"
+#include "inotify-missing.h"
+#include "inotify-path.h"
+#include "inotify-diag.h"
+
+static gboolean		ih_debug_enabled = FALSE;
+#define IH_W if (ih_debug_enabled) g_warning 
+
+static void ih_event_callback (ik_event_t *event, ih_sub_t *sub);
+static void ih_found_callback (ih_sub_t *sub);
+
+/* We share this lock with inotify-kernel.c and inotify-missing.c
+ *
+ * inotify-kernel.c takes the lock when it reads events from
+ * the kernel and when it processes those events
+ *
+ * inotify-missing.c takes the lock when it is scanning the missing
+ * list.
+ * 
+ * We take the lock in all public functions 
+ */
+G_LOCK_DEFINE (inotify_lock);
+static GList *sub_list = NULL;
+static gboolean initialized = FALSE;
+static event_callback_t user_ecb = NULL;
+static found_callback_t user_fcb = NULL;
+
+/**
+ * Initializes the inotify backend.  This must be called before
+ * any other functions in this module.
+ *
+ * @returns TRUE if initialization succeeded, FALSE otherwise
+ */
+gboolean
+ih_startup (event_callback_t ecb,
+	    found_callback_t fcb)
+{
+	static gboolean result = FALSE;
+
+	G_LOCK(inotify_lock);
+	
+	if (initialized == TRUE) {
+		G_UNLOCK(inotify_lock);
+		return result;
+	}
+
+	result = ip_startup (ih_event_callback);
+	if (!result) {
+		g_warning( "Could not initialize inotify\n");
+		G_UNLOCK(inotify_lock);
+		return FALSE;
+	}
+	initialized = TRUE;
+	user_ecb = ecb;
+	user_fcb = fcb;
+	im_startup (ih_found_callback);
+	id_startup ();
+
+	IH_W ("started gnome-vfs inotify backend\n");
+
+	G_UNLOCK(inotify_lock);
+	return TRUE;
+}
+
+gboolean
+ih_running (void)
+{
+	return initialized;
+}
+
+/**
+ * Adds a subscription to be monitored.
+ */
+gboolean
+ih_sub_add (ih_sub_t * sub)
+{
+	G_LOCK(inotify_lock);
+	
+	g_assert (g_list_find (sub_list, sub) == NULL);
+
+	// make sure that sub isn't on sub_list first.
+	if (!ip_start_watching (sub))
+	{
+		im_add (sub);
+	}
+
+	sub_list = g_list_prepend (sub_list, sub);
+
+	G_UNLOCK(inotify_lock);
+	return TRUE;
+}
+
+/**
+ * Cancels a subscription which was being monitored.
+ */
+gboolean
+ih_sub_cancel (ih_sub_t * sub)
+{
+	if (!sub->cancelled)
+	{
+		IH_W("cancelling %s\n", sub->pathname);
+		g_assert (g_list_find (sub_list, sub) != NULL);
+		sub->cancelled = TRUE;
+		im_rm (sub);
+		ip_stop_watching (sub);
+		sub_list = g_list_remove (sub_list, sub);
+	}
+
+	return TRUE;
+}
+
+static void
+ih_sub_foreach_worker (void *callerdata, gboolean (*f)(ih_sub_t *sub, void *callerdata), gboolean free)
+{
+	GList *l = NULL;
+	GList *next = NULL;
+
+	G_LOCK(inotify_lock);
+
+	for (l = sub_list; l; l = next)
+	{
+		ih_sub_t *sub = l->data;
+		next = l->next;
+		
+		if (f(sub, callerdata))
+		{
+			ih_sub_cancel (sub); /* Removes sub from sub_list */
+			if (free)
+				ih_sub_free (sub);
+		}
+	}
+
+	G_UNLOCK(inotify_lock);
+}
+
+void
+ih_sub_foreach (void *callerdata, gboolean (*f)(ih_sub_t *sub, void *callerdata))
+{
+	ih_sub_foreach_worker (callerdata, f, FALSE);
+}
+
+void
+ih_sub_foreach_free (void *callerdata, gboolean (*f)(ih_sub_t *sub, void *callerdata))
+{
+	ih_sub_foreach_worker (callerdata, f, TRUE);
+}
+
+static void ih_event_callback (ik_event_t *event, ih_sub_t *sub)
+{
+	gchar *fullpath;
+	if (event->name)
+	{
+		fullpath = g_strdup_printf ("%s/%s", sub->dirname, event->name);
+	} else {
+		fullpath = g_strdup_printf ("%s/", sub->dirname);
+	}
+
+	user_ecb (fullpath, event->mask, sub->usersubdata);
+	g_free(fullpath);
+}
+
+static void ih_found_callback (ih_sub_t *sub)
+{
+	gchar *fullpath;
+
+	if (sub->filename)
+	{
+		fullpath = g_strdup_printf ("%s/%s", sub->dirname, sub->filename);
+		if (!g_file_test (fullpath, G_FILE_TEST_EXISTS)) {
+			g_free (fullpath);
+			return;
+		}
+	} else {
+		fullpath = g_strdup_printf ("%s/", sub->dirname);
+	}
+
+	user_fcb (fullpath, sub->usersubdata);
+	g_free(fullpath);
+}
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 5)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~