mirror of https://gitee.com/openkylin/gvfs.git
133 lines
3.6 KiB
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);
|
|
}
|