Krolyxon
Commit c21a3e3

Branches

Refs →

nsxivc21a3e3

Write thumbnail cache files on exit

Author
Bert
Date
2011-04-07 14:33 +0200
Parent
83bdf67
Commit
c21a3e3f28a5c45497d09ab27d71538b983ca535

+155 −1

3 files changed

  1. M thumbs.c +69 −0
  2. M util.c +79 −1
  3. M util.h +7 −0
M thumbs.c View
@@ -18,6 +18,7 @@
1818
1919 #include <stdlib.h>
2020 #include <string.h>
21+#include <sys/time.h>
2122 #include <sys/types.h>
2223 #include <sys/stat.h>
2324 #include <unistd.h>
@@ -292,6 +293,9 @@ int tns_translate(tns_t *tns, int x, int y) {
292293 return -1;
293294 }
294295
296+
297+/* thumbnail caching */
298+
295299 int tns_cache_enabled() {
296300 int len, ret = 0;
297301 char *cpath, *homedir;
@@ -309,5 +313,70 @@ int tns_cache_enabled() {
309313 return ret;
310314 }
311315
316+char* tns_cache_filename(const char *filename) {
317+ size_t len;
318+ int i;
319+ char *cfile, *abspath, *homedir;
320+
321+ if (!filename)
322+ return NULL;
323+ if (!(homedir = getenv("HOME")))
324+ return NULL;
325+
326+ if (*filename != '/') {
327+ if (!(abspath = absolute_path(filename)))
328+ return NULL;
329+ } else {
330+ abspath = (char*) s_malloc(strlen(filename) + 1);
331+ strcpy(abspath, filename);
332+ }
333+
334+ len = strlen(abspath);
335+ for (i = 1; i < len; ++i) {
336+ if (abspath[i] == '/')
337+ abspath[i] = '%';
338+ }
339+
340+ len += strlen(homedir) + 15;
341+ cfile = (char*) s_malloc(len);
342+ snprintf(cfile, len, "%s/.sxiv/%s.png", homedir, abspath + 1);
343+
344+ free(abspath);
345+
346+ return cfile;
347+}
348+
312349 void tns_cache_write(thumb_t *t, Bool force) {
350+ char *cfile;
351+ struct stat cstats, fstats;
352+ struct timeval times[2];
353+ Imlib_Load_Error err;
354+
355+ if (!t || !t->im || !t->filename)
356+ return;
357+
358+ if ((cfile = tns_cache_filename(t->filename))) {
359+ if (stat(t->filename, &fstats))
360+ goto end;
361+
362+ if (force || stat(cfile, &cstats) ||
363+ cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec ||
364+ cstats.st_mtim.tv_nsec != fstats.st_mtim.tv_nsec)
365+ {
366+ imlib_context_set_image(t->im);
367+ imlib_image_set_format("png");
368+ imlib_save_image_with_error_return(cfile, &err);
369+
370+ if (err) {
371+ warn("could not cache thumbnail:", t->filename);
372+ } else {
373+ TIMESPEC_TO_TIMEVAL(&times[0], &fstats.st_atim);
374+ TIMESPEC_TO_TIMEVAL(&times[1], &fstats.st_mtim);
375+ utimes(cfile, times);
376+ }
377+ }
378+ }
379+
380+end:
381+ free(cfile);
313382 }
M util.c View
@@ -18,11 +18,13 @@
1818
1919 #include <stdlib.h>
2020 #include <string.h>
21+#include <unistd.h>
22+#include <errno.h>
2123
2224 #include "options.h"
2325 #include "util.h"
2426
25−#define FNAME_LEN 512
27+#define FNAME_LEN 1024
2628
2729 void cleanup();
2830
@@ -78,6 +80,82 @@ void size_readable(float *size, const char **unit) {
7880 *unit = units[MIN(i, LEN(units) - 1)];
7981 }
8082
83+char* absolute_path(const char *filename) {
84+ size_t len;
85+ char *path = NULL;
86+ const char *basename;
87+ char *dirname = NULL;
88+ char *cwd = NULL;
89+ char *twd = NULL;
90+ char *dir;
91+ char *s;
92+
93+ if (!filename || *filename == '\0' || *filename == '/')
94+ return NULL;
95+
96+ len = FNAME_LEN;
97+ cwd = (char*) s_malloc(len);
98+ while (!(s = getcwd(cwd, len)) && errno == ERANGE) {
99+ len *= 2;
100+ cwd = (char*) s_realloc(cwd, len);
101+ }
102+ if (!s)
103+ goto error;
104+
105+ s = strrchr(filename, '/');
106+ if (s) {
107+ len = s - filename;
108+ dirname = (char*) s_malloc(len + 1);
109+ strncpy(dirname, filename, len);
110+ dirname[len] = '\0';
111+ basename = s + 1;
112+
113+ if (chdir(cwd))
114+ /* we're not able to come back afterwards */
115+ goto error;
116+ if (chdir(dirname))
117+ goto error;
118+
119+ len = FNAME_LEN;
120+ twd = (char*) s_malloc(len);
121+ while (!(s = getcwd(twd, len)) && errno == ERANGE) {
122+ len *= 2;
123+ twd = (char*) s_realloc(twd, len);
124+ }
125+ if (chdir(cwd))
126+ die("could not revert to working directory");
127+ if (!s)
128+ goto error;
129+ dir = twd;
130+ } else {
131+ /* only a single filename given */
132+ basename = filename;
133+ dir = cwd;
134+ }
135+
136+ len = strlen(dir) + strlen(basename) + 2;
137+ path = (char*) s_malloc(len);
138+ snprintf(path, len, "%s/%s", dir, basename);
139+
140+goto end;
141+
142+error:
143+ if (path) {
144+ free(path);
145+ path = NULL;
146+ }
147+
148+end:
149+ if (dirname)
150+ free(dirname);
151+ if (cwd)
152+ free(cwd);
153+ if (twd)
154+ free(twd);
155+
156+ return path;
157+}
158+
81159 char* readline(FILE *stream) {
82160 size_t len;
83161 char *buf, *s, *end;
M util.h View
@@ -30,6 +30,11 @@
3030 #define TV_TO_DOUBLE(x) ((double) ((x).tv_sec) + 0.000001 * \
3131 (double) ((x).tv_usec))
3232
33+#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
34+ (tv)->tv_sec = (ts)->tv_sec; \
35+ (tv)->tv_usec = (ts)->tv_nsec / 1000; \
36+}
37+
3338 void* s_malloc(size_t);
3439 void* s_realloc(void*, size_t);
3540
@@ -38,6 +43,8 @@ void die(const char*, ...);
3843
3944 void size_readable(float*, const char**);
4045
46+char* absolute_path(const char*);
47+
4148 char* readline(FILE*);
4249
4350 #endif /* UTIL_H */