summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJing Wang <99jingw@gmail.com>2020-10-10 16:06:33 -0400
committerJing Wang <99jingw@gmail.com>2020-10-10 16:44:06 -0400
commit647c0af7779757b18708a07b7cfc95e6b1bc79f0 (patch)
tree80ab17bd5c533cb8b4ce27718eface2ae3cf9ae0
parent4607668092130370e2e71ba502d7bcebc9152e1c (diff)
downloadgnome-settings-daemon-647c0af7779757b18708a07b7cfc95e6b1bc79f0.tar.gz
Fix crashing when atime is not present
Recent changes to gio omit the atime instead of setting it to an out of range value. Fixes #556, but note this doesn't fix the fact that gio omitted atime on a system where atime should have been available.
-rw-r--r--plugins/housekeeping/gsd-housekeeping-manager.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/plugins/housekeeping/gsd-housekeeping-manager.c b/plugins/housekeeping/gsd-housekeeping-manager.c
index 40d016aa..8ad985c8 100644
--- a/plugins/housekeeping/gsd-housekeeping-manager.c
+++ b/plugins/housekeeping/gsd-housekeeping-manager.c
@@ -78,7 +78,7 @@ typedef struct {
typedef struct {
- gint64 atime;
+ gint64 time;
char *path;
glong size;
} ThumbData;
@@ -100,11 +100,13 @@ read_dir_for_purge (const char *path, GList *files)
{
GFile *read_path;
GFileEnumerator *enum_dir;
+ int cannot_get_time = 0;
read_path = g_file_new_for_path (path);
enum_dir = g_file_enumerate_children (read_path,
G_FILE_ATTRIBUTE_STANDARD_NAME ","
G_FILE_ATTRIBUTE_TIME_ACCESS ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED ","
G_FILE_ATTRIBUTE_STANDARD_SIZE,
G_FILE_QUERY_INFO_NONE,
NULL,
@@ -120,28 +122,31 @@ read_dir_for_purge (const char *path, GList *files)
ThumbData *td;
GFile *entry;
char *entry_path;
- gint64 atime;
+ gint64 time;
entry = g_file_get_child (read_path, name);
entry_path = g_file_get_path (entry);
g_object_unref (entry);
- // Note that using atime here is no worse than using mtime.
+ // If atime is available, it should be no worse than mtime.
// - Even if the file system is mounted with noatime, the atime and
// mtime will be set to the same value on file creation.
// - Since the thumbnailer never edits thumbnails, and instead swaps
// in newly created temp files, atime will always be >= mtime.
- // - atime should never be absent, which would cause
- // g_file_info_get_attribute_int64 to return 0. The presence of
- // atime is determined by the filters we pass to
- // g_file_enumerate_children, not the file system atime settings.
- g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_ACCESS));
- atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS);
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_ACCESS)) {
+ time = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS);
+ } else if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED)) {
+ time = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+ } else {
+ // Unlikely to get here, but be defensive
+ cannot_get_time += 1;
+ time = G_MAXINT64;
+ }
td = g_new0 (ThumbData, 1);
td->path = entry_path;
- td->atime = atime;
+ td->time = time;
td->size = g_file_info_get_size (info);
files = g_list_prepend (files, td);
@@ -149,6 +154,10 @@ read_dir_for_purge (const char *path, GList *files)
g_object_unref (info);
}
g_object_unref (enum_dir);
+
+ if (cannot_get_time > 0) {
+ g_warning ("Could not read atime or mtime on %d files in %s", cannot_get_time, path);
+ }
}
g_object_unref (read_path);
@@ -158,7 +167,7 @@ read_dir_for_purge (const char *path, GList *files)
static void
purge_old_thumbnails (ThumbData *info, PurgeData *purge_data)
{
- if ((purge_data->now - info->atime) > purge_data->max_age) {
+ if ((purge_data->now - info->time) > purge_data->max_age) {
g_unlink (info->path);
info->size = 0;
} else {
@@ -167,9 +176,9 @@ purge_old_thumbnails (ThumbData *info, PurgeData *purge_data)
}
static int
-sort_file_atime (ThumbData *file1, ThumbData *file2)
+sort_file_time (ThumbData *file1, ThumbData *file2)
{
- return file1->atime - file2->atime;
+ return file1->time - file2->time;
}
static char **
@@ -260,7 +269,7 @@ purge_thumbnail_cache (GsdHousekeepingManager *manager)
if ((purge_data.total_size > purge_data.max_size) && (purge_data.max_size >= 0)) {
GList *scan;
- files = g_list_sort (files, (GCompareFunc) sort_file_atime);
+ files = g_list_sort (files, (GCompareFunc) sort_file_time);
for (scan = files; scan && (purge_data.total_size > purge_data.max_size); scan = scan->next) {
ThumbData *info = scan->data;
g_unlink (info->path);