gvfs/daemon/trashlib/trashexpunge.c

133 lines
3.6 KiB
C

/*
* Copyright © 2008 Ryan Lortie
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
* published by the Free Software Foundation.
*/
#include "trashexpunge.h"
static gsize trash_expunge_initialised;
static GHashTable *trash_expunge_queue;
static gboolean trash_expunge_alive;
static GMutex trash_expunge_lock;
static GCond trash_expunge_wait;
static void
trash_expunge_delete_everything_under (GFile *directory)
{
GFileEnumerator *enumerator;
g_file_set_attribute_uint32 (directory,
G_FILE_ATTRIBUTE_UNIX_MODE, 0700,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, NULL);
enumerator = g_file_enumerate_children (directory,
G_FILE_ATTRIBUTE_STANDARD_NAME ","
G_FILE_ATTRIBUTE_STANDARD_TYPE,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, NULL);
if (enumerator)
{
GFileInfo *info;
while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
{
const gchar *basename;
GFile *sub;
basename = g_file_info_get_name (info);
sub = g_file_get_child (directory, basename);
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
trash_expunge_delete_everything_under (sub);
/* do the delete here */
g_file_delete (sub, NULL, NULL);
g_object_unref (info);
g_object_unref (sub);
}
g_object_unref (enumerator);
}
}
static gboolean
just_return_true (gpointer a,
gpointer b,
gpointer c)
{
return TRUE;
}
static gpointer
trash_expunge_thread (gpointer data)
{
gint64 end_time;
g_mutex_lock (&trash_expunge_lock);
do
{
while (g_hash_table_size (trash_expunge_queue))
{
GFile *directory;
directory = g_hash_table_find (trash_expunge_queue,
just_return_true, NULL);
g_hash_table_remove (trash_expunge_queue, directory);
g_mutex_unlock (&trash_expunge_lock);
trash_expunge_delete_everything_under (directory);
g_mutex_lock (&trash_expunge_lock);
g_object_unref (directory);
}
end_time = g_get_monotonic_time () + 1 * G_TIME_SPAN_MINUTE;
}
while (g_cond_wait_until (&trash_expunge_wait,
&trash_expunge_lock,
end_time));
trash_expunge_alive = FALSE;
g_mutex_unlock (&trash_expunge_lock);
return NULL;
}
void
trash_expunge (GFile *directory)
{
if G_UNLIKELY (g_once_init_enter (&trash_expunge_initialised))
{
trash_expunge_queue = g_hash_table_new (g_file_hash,
(GEqualFunc) g_file_equal);
g_once_init_leave (&trash_expunge_initialised, 1);
}
g_mutex_lock (&trash_expunge_lock);
if (!g_hash_table_lookup (trash_expunge_queue, directory))
g_hash_table_insert (trash_expunge_queue,
g_object_ref (directory),
directory);
if (trash_expunge_alive == FALSE)
{
GThread *thread;
thread = g_thread_new ("trash-expunge", trash_expunge_thread, NULL);
g_assert (thread != NULL);
trash_expunge_alive = TRUE;
}
else
g_cond_signal (&trash_expunge_wait);
g_mutex_unlock (&trash_expunge_lock);
}