4242#include <gio/gio.h>
4343#include <cairo.h>
4444
45+ // Unavailability of an mtime is usually fatal, but if the thumb was created
46+ // with an absent mtime, this is tolerable (and actually beneficial, because it
47+ // enables montage mode on incomplete data).
48+ //
49+ // This does not get any special treatment at checking time -- if
50+ // 1970-01-01T00:00:00 is indeed a value placed in the MTime of a thumbnail,
51+ // chances are that the creator might even have intended to actually not set
52+ // the MTime.
53+ const time_t MTIME_UNAVAILABLE = 0 ;
54+
4555/* Sorted in decreasing size, such that when looking for thumbnails of at least
4656 * some size, they can be traversed last-to-first, starting at the one that
4757 * first has a chance to match (see use of minimum_level_index). */
@@ -145,9 +155,11 @@ gboolean check_png_attributes(gchar *file_name, gchar *file_uri, time_t file_mti
145155 //
146156 // See below in png_writer for a rough explaination, or read the PNG TR
147157 // https://www.w3.org/TR/PNG/
148- //
149- gboolean file_uri_match = FALSE;
150- gboolean file_mtime_match = FALSE;
158+
159+ // Tracking whether they were found to return early once both are matched.
160+ gboolean found_uri = FALSE;
161+ gboolean found_mtime = FALSE;
162+ gboolean found_mismatch = FALSE;
151163
152164 int fd = g_open (file_name , O_RDONLY , 0 );
153165 if (fd < 0 ) {
@@ -174,7 +186,7 @@ gboolean check_png_attributes(gchar *file_name, gchar *file_uri, time_t file_mti
174186 while (1 ) {
175187 if (read (fd , header .buf , 8 ) != 8 ) {
176188 g_close (fd , NULL );
177- return FALSE ;
189+ return ! found_mismatch ;
178190 }
179191
180192 int header_length = (int )ntohl (header .uint32 );
@@ -205,18 +217,22 @@ gboolean check_png_attributes(gchar *file_name, gchar *file_uri, time_t file_mti
205217
206218 if (file_crc == actual_crc ) {
207219 if (strcmp (data , "Thumb::URI" ) == 0 ) {
208- file_uri_match = strncmp (& data [sizeof ("Thumb::URI" )], file_uri , strlen (file_uri )) == 0 ;
220+ gboolean match = strncmp (& data [sizeof ("Thumb::URI" )], file_uri , strlen (file_uri )) == 0 ;
221+ found_mismatch |= !match ;
222+ found_uri = TRUE;
209223 }
210224 else if (strcmp (data , "Thumb::MTime" ) == 0 ) {
211225 gchar * file_mtime_str = g_strdup_printf ("%" PRIuMAX , (intmax_t )file_mtime );
212- file_mtime_match = strncmp (& data [sizeof ("Thumb::MTime" )], file_mtime_str , strlen (file_mtime_str )) == 0 ;
226+ gboolean match = strncmp (& data [sizeof ("Thumb::MTime" )], file_mtime_str , strlen (file_mtime_str )) == 0 ;
213227 g_free (file_mtime_str );
228+ found_mismatch |= !match ;
229+ found_mtime = TRUE;
214230 }
215231
216- if (file_uri_match && file_mtime_match ) {
232+ if (( found_uri && found_mtime ) || found_mismatch ) {
217233 g_free (data );
218234 g_close (fd , NULL );
219- return TRUE ;
235+ return ! found_mismatch ;
220236 }
221237 }
222238
@@ -298,11 +314,12 @@ gboolean load_thumbnail_from_cache(file_t *file, unsigned width, unsigned height
298314
299315 // Obtain modification timestamp
300316 struct stat file_stat ;
317+ time_t file_mtime ;
301318 if (stat (local_filename , & file_stat ) < 0 ) {
302- g_free (local_filename );
303- return FALSE;
319+ file_mtime = MTIME_UNAVAILABLE ;
320+ } else {
321+ file_mtime = file_stat .st_mtime ;
304322 }
305- time_t file_mtime = file_stat .st_mtime ;
306323
307324 // Obtain the name of the candidate for the local thumbnail file
308325 gchar * file_uri = multi_page_suffix ? g_strdup_printf ("file://%s#%s" , local_filename , multi_page_suffix ) : g_strdup_printf ("file://%s" , local_filename );
0 commit comments