From 07e1601cd54d9ca9ed0b8648597e8d332242d938 Mon Sep 17 00:00:00 2001 From: Kim Woelders Date: Sun, 1 Mar 2020 05:55:25 +0100 Subject: [PATCH] Reduce number of stat() calls during load Also skip empty files entirely. --- src/lib/api.c | 21 ++------------------- src/lib/file.c | 2 +- src/lib/file.h | 22 ++++++++++++++++++++++ src/lib/image.c | 28 ++++++++++++++++++++++++++-- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/lib/api.c b/src/lib/api.c index b65a04d..e94bebf 100644 --- a/src/lib/api.c +++ b/src/lib/api.c @@ -1412,26 +1412,9 @@ imlib_load_image_with_error_return(const char *file, CHECK_CONTEXT(ctx); CHECK_PARAM_POINTER_RETURN("imlib_load_image_with_error_return", "file", file, NULL); - if (!__imlib_FileExists(file)) - { - *error_return = IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST; - return NULL; - } - if (__imlib_FileIsDir(file)) - { - *error_return = IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY; - return NULL; - } - if (!__imlib_FileCanRead(file)) - { - *error_return = IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ; - return NULL; - } prev_ctxt_image = ctx->image; - im = (Imlib_Image) __imlib_LoadImage(file, - (ImlibProgressFunction) - ctx->progress_func, - ctx->progress_granularity, 1, 0, &er); + im = __imlib_LoadImage(file, (ImlibProgressFunction) ctx->progress_func, + ctx->progress_granularity, 1, 0, &er); ctx->image = prev_ctxt_image; if (im) *error_return = IMLIB_LOAD_ERROR_NONE; diff --git a/src/lib/file.c b/src/lib/file.c index ef8eaa5..5616859 100644 --- a/src/lib/file.c +++ b/src/lib/file.c @@ -117,7 +117,7 @@ __imlib_FileExtension(const char *file) return *p != '\0' ? p : NULL; } -static int +int __imlib_FileStat(const char *file, struct stat *st) { if ((!file) || (!*file)) diff --git a/src/lib/file.h b/src/lib/file.h index b5e1fc6..414ef7a 100644 --- a/src/lib/file.h +++ b/src/lib/file.h @@ -1,6 +1,8 @@ #ifndef __FILE_H #define __FILE_H 1 +#include + #include "common.h" int __imlib_IsRealFile(const char *s); @@ -9,6 +11,26 @@ char *__imlib_FileRealFile(const char *file); const char *__imlib_FileExtension(const char *file); +int __imlib_FileStat(const char *file, struct stat *st); + +static inline time_t +__imlib_StatModDate(const struct stat *st) +{ + return (st->st_mtime > st->st_ctime) ? st->st_mtime : st->st_ctime; +} + +static inline int +__imlib_StatIsFile(const struct stat *st) +{ + return S_ISREG(st->st_mode); +} + +static inline int +__imlib_StatIsDir(const struct stat *st) +{ + return S_ISDIR(st->st_mode); +} + int __imlib_FileExists(const char *s); int __imlib_FileIsFile(const char *s); int __imlib_FileIsDir(const char *s); diff --git a/src/lib/image.c b/src/lib/image.c index 24cd1cc..2f343f9 100644 --- a/src/lib/image.c +++ b/src/lib/image.c @@ -526,6 +526,26 @@ __imlib_ErrorFromErrno(int err, int save) } } +static int +__imlib_FileCheck(const char *file, struct stat *st, ImlibLoadError * er) +{ + int err; + + err = 0; + + if (__imlib_FileStat(file, st)) + err = IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST; + else if (__imlib_StatIsDir(st)) + err = IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY; + else if (st->st_size == 0) + err = IMLIB_LOAD_ERROR_UNKNOWN; + + if (er) + *er = err; + + return err; +} + /* create a new image struct from data passed that is wize w x h then return */ /* a pointer to that image sturct */ ImlibImage * @@ -648,6 +668,7 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, ImlibLoader *best_loader; int loader_ret; ImlibLdCtx ilc; + struct stat st; if (!file || file[0] == '\0') return NULL; @@ -686,12 +707,15 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, } } + if (__imlib_FileCheck(file, &st, er)) + return NULL; + /* either image in cache is invalid or we dont even have it in cache */ /* so produce a new one and load an image into that */ im = __imlib_ProduceImage(); im->file = strdup(file); - if (__imlib_IsRealFile(file)) + if (__imlib_StatIsFile(&st)) { im->real_file = im->file; im->key = NULL; @@ -711,7 +735,7 @@ __imlib_LoadImage(const char *file, ImlibProgressFunction progress, return NULL; } - im->moddate = __imlib_FileModDate(im->real_file); + im->moddate = __imlib_StatModDate(&st); im->data_memory_func = imlib_context_get_image_data_memory_function();