summaryrefslogtreecommitdiff
path: root/gio/glocalfileinfo.c
diff options
context:
space:
mode:
authorTimothy Arceri <t_arceri@yahoo.com.au>2012-11-29 10:50:55 +1100
committerDavid Zeuthen <zeuthen@gmail.com>2012-12-06 16:18:19 -0500
commit510ba9b4efe1813e24c6dfa7405c3547bf9efdd7 (patch)
tree2434a9ff76e76df8066f5a09fe01146978c0c3a9 /gio/glocalfileinfo.c
parent6869454103471d383216dc39db09279d61aa2bba (diff)
downloadglib-510ba9b4efe1813e24c6dfa7405c3547bf9efdd7.tar.gz
Support for .hidden files
https://bugzilla.gnome.org/show_bug.cgi?id=587806
Diffstat (limited to 'gio/glocalfileinfo.c')
-rw-r--r--gio/glocalfileinfo.c116
1 files changed, 115 insertions, 1 deletions
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index 9cfa041bf..6dfd75fba 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -62,6 +62,9 @@
#include <gfileinfo-priv.h>
#include <gvfs.h>
+#ifndef G_OS_WIN32
+#include "glib-private.h"
+#endif
#include "glibintl.h"
#ifdef G_OS_WIN32
@@ -1415,6 +1418,115 @@ win32_get_file_user_info (const gchar *filename,
}
#endif /* G_OS_WIN32 */
+#ifndef G_OS_WIN32
+/* support for '.hidden' files */
+G_LOCK_DEFINE_STATIC (hidden_cache);
+static GHashTable *hidden_cache;
+
+static gboolean
+remove_from_hidden_cache (gpointer user_data)
+{
+ G_LOCK (hidden_cache);
+ g_hash_table_remove (hidden_cache, user_data);
+ G_UNLOCK (hidden_cache);
+
+ return FALSE;
+}
+
+static GHashTable *
+read_hidden_file (const gchar *dirname)
+{
+ gchar *filename;
+ FILE *hidden;
+
+ filename = g_build_path ("/", dirname, ".hidden", NULL);
+ hidden = fopen (filename, "r");
+ g_free (filename);
+
+ if (hidden != NULL)
+ {
+ gchar buffer[PATH_MAX + 2]; /* \n\0 */
+ GHashTable *table;
+
+ table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ while (fgets (buffer, sizeof buffer, hidden))
+ {
+ gchar *newline;
+
+ if ((newline = strchr (buffer, '\n')) != NULL)
+ {
+ *newline++ = '\0';
+
+ g_hash_table_insert (table,
+ g_memdup (buffer, newline - buffer),
+ GINT_TO_POINTER (TRUE));
+ }
+ }
+
+ fclose (hidden);
+
+ return table;
+ }
+ else
+ return NULL;
+}
+
+static void
+maybe_unref_hash_table (gpointer data)
+{
+ if (data != NULL)
+ g_hash_table_unref (data);
+}
+
+static gboolean
+file_is_hidden (const gchar *path,
+ const gchar *basename)
+{
+ gboolean result;
+ gchar *dirname;
+ gpointer table;
+
+ dirname = g_path_get_dirname (path);
+
+ G_LOCK (hidden_cache);
+
+ if G_UNLIKELY (hidden_cache == NULL)
+ hidden_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, maybe_unref_hash_table);
+
+ if (!g_hash_table_lookup_extended (hidden_cache, dirname,
+ NULL, &table))
+ {
+ gchar *mydirname;
+ GSource *remove_from_cache_source;
+
+ g_hash_table_insert (hidden_cache,
+ mydirname = g_strdup (dirname),
+ table = read_hidden_file (dirname));
+
+ remove_from_cache_source = g_timeout_source_new_seconds (5);
+ g_source_set_priority (remove_from_cache_source, G_PRIORITY_DEFAULT);
+ g_source_set_callback (remove_from_cache_source,
+ remove_from_hidden_cache,
+ mydirname,
+ NULL);
+ g_source_attach (remove_from_cache_source,
+ GLIB_PRIVATE_CALL (g_get_worker_context) ());
+ g_source_unref (remove_from_cache_source);
+ }
+
+ result = table != NULL &&
+ GPOINTER_TO_INT (g_hash_table_lookup (table, basename));
+
+ G_UNLOCK (hidden_cache);
+
+ g_free (dirname);
+
+ return result;
+}
+#endif /* !G_OS_WIN32 */
+
void
_g_local_file_info_get_nostat (GFileInfo *info,
const char *basename,
@@ -1671,7 +1783,9 @@ _g_local_file_info_get (const char *basename,
set_info_from_stat (info, &statbuf, attribute_matcher);
#ifndef G_OS_WIN32
- if (basename != NULL && basename[0] == '.')
+ if (basename != NULL &&
+ (basename[0] == '.' ||
+ file_is_hidden (path, basename)))
g_file_info_set_is_hidden (info, TRUE);
if (basename != NULL && basename[strlen (basename) -1] == '~' &&