Created
June 20, 2011 20:53
-
-
Save dmatveev/1036558 to your computer and use it in GitHub Desktop.
Directory tree activity monitor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <glib.h> | |
#include <gio/gio.h> | |
#include <glib/gstdio.h> | |
#include <sys/resource.h> | |
static GHashTable *g_all_entries = NULL; | |
G_GNUC_INTERNAL G_LOCK_DEFINE (hash_lock); | |
static void | |
on_file_change (GFileMonitor *, GFile *, GFile *, GFileMonitorEvent, gpointer); | |
static void | |
add_file (const gchar *path); | |
static void | |
add_tree (const gchar *path); | |
static void | |
add_if_directory(const gchar *path); | |
static void | |
add_if_directory(const gchar *path) | |
{ | |
GFile *file = g_file_new_for_path (path); | |
if (g_file_query_file_type (file, 0, NULL) == G_FILE_TYPE_DIRECTORY) | |
add_tree (path); | |
g_object_unref (file); | |
} | |
static void | |
cancel_on_delete (GFileMonitor *mon, const gchar *path) | |
{ | |
g_file_monitor_cancel(mon); | |
G_LOCK (hash_lock); | |
g_hash_table_remove (g_all_entries, path); | |
G_UNLOCK (hash_lock); | |
} | |
#define pcase(sym, file, code) \ | |
case G_FILE_MONITOR_EVENT_##sym: \ | |
g_print (#sym": %s\n", file); \ | |
{code;}; \ | |
break | |
static void | |
on_file_change (GFileMonitor *mon, | |
GFile *file, | |
GFile *other_file, | |
GFileMonitorEvent event_type, | |
gpointer user_data) | |
{ | |
gchar *path = g_file_get_path (file); | |
switch (event_type) | |
{ | |
pcase(CHANGED, path, add_if_directory(path)); | |
pcase(CHANGES_DONE_HINT, path, {}); | |
pcase(DELETED, path, cancel_on_delete(mon, path)); | |
pcase(CREATED, path, {}); | |
pcase(ATTRIBUTE_CHANGED, path, {}); | |
pcase(PRE_UNMOUNT, path, {}); | |
pcase(UNMOUNTED, path, {}); | |
pcase(MOVED, path, {}); | |
default: | |
g_print ("What?\n"); | |
} | |
g_free (path); | |
} | |
static void | |
add_file (const gchar *path) | |
{ | |
GFile *file = g_file_new_for_path (path); | |
G_LOCK (hash_lock); | |
if (!g_hash_table_lookup (g_all_entries, path)) { | |
GFileMonitor *mon; | |
g_hash_table_insert (g_all_entries, (gpointer) g_strdup(path), GINT_TO_POINTER(TRUE)); | |
mon = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL); | |
g_signal_connect (mon, "changed", G_CALLBACK(on_file_change), NULL); | |
} | |
G_UNLOCK (hash_lock); | |
} | |
static void | |
add_tree (const gchar *path) | |
{ | |
GDir *root = NULL; | |
const gchar *each = NULL; | |
root = g_dir_open (path, 0, NULL); | |
if (root == NULL) | |
return; | |
while (each = g_dir_read_name (root)) | |
{ | |
gchar *full = g_strconcat (path, "/", each, NULL); | |
GFile *file = g_file_new_for_path (full); | |
if (g_file_query_file_type (file, 0, NULL) == G_FILE_TYPE_DIRECTORY) | |
add_tree (full); | |
else | |
add_file (full); | |
g_object_unref (file); | |
g_free (full); | |
} | |
/* yes, add_file() is also fine to start monitoring on a directory */ | |
add_file (path); | |
g_dir_close (root); | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
GMainLoop *loop; | |
struct rlimit rl; | |
rl.rlim_cur = 3072; | |
rl.rlim_max = 10240; | |
setrlimit (RLIMIT_NOFILE, &rl); | |
if (argc < 2) | |
return 1; | |
g_type_init(); | |
g_all_entries = g_hash_table_new_full (g_str_hash, | |
g_str_equal, | |
(GDestroyNotify) g_free, | |
NULL); | |
add_tree (argv[1]); | |
g_print ("READY!\n"); | |
loop = g_main_loop_new (NULL, FALSE); | |
g_main_loop_run (loop); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment