diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2022-08-09 08:31:03 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2022-08-09 13:22:11 +0200 |
commit | 4e11970a7eb852010fe609ef155d580ae415e54c (patch) | |
tree | 797334392d9414f21a92c1f520935d65047ee5be | |
parent | ae0b5506abf8608905f92aa61d2f2424ed2cf119 (diff) | |
download | fiv-4e11970a7eb852010fe609ef155d580ae415e54c.tar.gz fiv-4e11970a7eb852010fe609ef155d580ae415e54c.tar.xz fiv-4e11970a7eb852010fe609ef155d580ae415e54c.zip |
Do produce thumbnails of thumbnails, but in memory
-rw-r--r-- | fiv-browser.c | 11 | ||||
-rw-r--r-- | fiv-thumbnail.c | 29 | ||||
-rw-r--r-- | fiv-thumbnail.h | 3 |
3 files changed, 27 insertions, 16 deletions
diff --git a/fiv-browser.c b/fiv-browser.c index 1879ddf..55d3fc1 100644 --- a/fiv-browser.c +++ b/fiv-browser.c @@ -729,17 +729,6 @@ thumbnailers_start(FivBrowser *self) if (!self->model) return; - // TODO(p): Leave out all paths containing .cache/thumbnails altogether. - gchar *thumbnails_dir = fiv_thumbnail_get_root(); - GFile *thumbnails = g_file_new_for_path(thumbnails_dir); - g_free(thumbnails_dir); - - GFile *current = fiv_io_model_get_location(self->model); - gboolean is_a_thumbnail = current && g_file_has_prefix(current, thumbnails); - g_object_unref(thumbnails); - if (is_a_thumbnail) - return; - GList *missing = NULL, *lq = NULL; for (guint i = self->entries->len; i--; ) { Entry *entry = &g_array_index(self->entries, Entry, i); diff --git a/fiv-thumbnail.c b/fiv-thumbnail.c index 15a78f1..803296c 100644 --- a/fiv-thumbnail.c +++ b/fiv-thumbnail.c @@ -25,6 +25,7 @@ #include <errno.h> #include <math.h> #include <stdbool.h> +#include <string.h> #include "fiv-io.h" #include "fiv-thumbnail.h" @@ -93,7 +94,7 @@ mark_thumbnail_lq(cairo_surface_t *surface) surface, &fiv_thumbnail_key_lq, (void *) (intptr_t) 1, NULL); } -gchar * +static gchar * fiv_thumbnail_get_root(void) { gchar *cache_dir = get_xdg_home_dir("XDG_CACHE_HOME", ".cache"); @@ -102,6 +103,23 @@ fiv_thumbnail_get_root(void) return thumbnails_dir; } +static gboolean +might_be_a_thumbnail(const char *path_or_uri) +{ + // It is generally difficult to discern case in/sensitivity of subpaths, + // so err on the side of false positives. + gchar *normalized = g_ascii_strdown(path_or_uri, -1); + + // The Windows path separator must be percent-encoded in URIs, + // and the file scheme always uses forward slashes. + if (G_DIR_SEPARATOR != '/') + g_strdelimit(normalized, G_DIR_SEPARATOR_S, '/'); + + gboolean matches = strstr(normalized, "/.cache/thumbnails/") != NULL; + g_free(normalized); + return matches; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static cairo_surface_t * @@ -440,8 +458,10 @@ fiv_thumbnail_produce(GFile *target, FivThumbnailSize max_size, GError **error) g_return_val_if_fail(max_size >= FIV_THUMBNAIL_SIZE_MIN && max_size <= FIV_THUMBNAIL_SIZE_MAX, FALSE); + // Don't save thumbnails for FUSE mounts, such as sftp://. + // Moreover, it doesn't make sense to save thumbnails of thumbnails. const gchar *path = g_file_peek_path(target); - if (!path || !g_file_is_native(target) /* Don't save sftp://. */) + if (!path || !g_file_is_native(target) || might_be_a_thumbnail(path)) return produce_fallback(target, max_size, error); // Make the TOCTTOU issue favour unnecessary reloading. @@ -620,6 +640,11 @@ fiv_thumbnail_lookup(const char *uri, gint64 mtime_msec, FivThumbnailSize size) g_return_val_if_fail(size >= FIV_THUMBNAIL_SIZE_MIN && size <= FIV_THUMBNAIL_SIZE_MAX, NULL); + // Don't waste time looking up something that shouldn't exist-- + // thumbnail directories tend to get huge, and syscalls are expensive. + if (might_be_a_thumbnail(uri)) + return NULL; + gchar *sum = g_compute_checksum_for_string(G_CHECKSUM_MD5, uri, -1); gchar *thumbnails_dir = fiv_thumbnail_get_root(); diff --git a/fiv-thumbnail.h b/fiv-thumbnail.h index d12765a..7f3360a 100644 --- a/fiv-thumbnail.h +++ b/fiv-thumbnail.h @@ -52,9 +52,6 @@ extern FivThumbnailSizeInfo fiv_thumbnail_sizes[FIV_THUMBNAIL_SIZE_COUNT]; /// If non-NULL, indicates a thumbnail of insufficient quality. extern cairo_user_data_key_t fiv_thumbnail_key_lq; -/// Returns this user's root thumbnail directory. -gchar *fiv_thumbnail_get_root(void); - /// Attempts to extract any low-quality thumbnail from fast targets. /// If `max_size` is a valid value, the image will be downscaled as appropriate. cairo_surface_t *fiv_thumbnail_extract( |