Mercurial > geeqie.yaz
annotate src/cache-loader.c @ 276:4f526d436873
Implement secure rc file saving.
First data is written to a temporary file, then if nothing
was wrong, this file is renamed to the final name.
This way the risk of corrupted rc file is greatly reduced.
The code is borrowed from ELinks (http://elinks.cz).
author | zas_ |
---|---|
date | Tue, 08 Apr 2008 21:55:58 +0000 |
parents | f6e307c7bad6 |
children | 9995c5fb202a |
rev | line source |
---|---|
37 | 1 /* |
196 | 2 * Geeqie |
37 | 3 * (C) 2005 John Ellis |
4 * | |
5 * Author: John Ellis | |
6 * | |
7 * This software is released under the GNU General Public License (GNU GPL). | |
8 * Please read the included file COPYING for more information. | |
9 * This software comes with no warranty of any kind, use at your own risk! | |
10 */ | |
11 | |
12 #include "gqview.h" | |
13 #include "cache-loader.h" | |
138 | 14 #include "cache.h" |
37 | 15 |
138 | 16 #include "filelist.h" |
37 | 17 #include "exif.h" |
18 #include "md5-util.h" | |
19 #include "ui_fileops.h" | |
20 | |
21 | |
22 static gboolean cache_loader_process(CacheLoader *cl); | |
23 | |
24 | |
25 static void cache_loader_done_cb(ImageLoader *il, gpointer data) | |
26 { | |
27 CacheLoader *cl = data; | |
28 | |
29 cache_loader_process(cl); | |
30 } | |
31 | |
32 static void cache_loader_error_cb(ImageLoader *il, gpointer data) | |
33 { | |
34 CacheLoader *cl = data; | |
35 | |
36 cl->error = TRUE; | |
37 cache_loader_done_cb(il, data); | |
38 } | |
39 | |
40 static gboolean cache_loader_process(CacheLoader *cl) | |
41 { | |
42 if (cl->todo_mask & CACHE_LOADER_SIMILARITY && | |
43 !cl->cd->similarity) | |
44 { | |
45 GdkPixbuf *pixbuf; | |
46 | |
47 if (!cl->il && !cl->error) | |
48 { | |
138 | 49 cl->il = image_loader_new(cl->fd); |
37 | 50 image_loader_set_error_func(cl->il, cache_loader_error_cb, cl); |
51 if (image_loader_start(cl->il, cache_loader_done_cb, cl)) | |
52 { | |
53 return FALSE; | |
54 } | |
55 | |
56 cl->error = TRUE; | |
57 } | |
58 | |
59 pixbuf = image_loader_get_pixbuf(cl->il); | |
60 if (pixbuf) | |
61 { | |
62 if (!cl->error) | |
63 { | |
64 ImageSimilarityData *sim; | |
65 | |
66 sim = image_sim_new_from_pixbuf(pixbuf); | |
67 cache_sim_data_set_similarity(cl->cd, sim); | |
68 image_sim_free(sim); | |
69 | |
70 cl->done_mask |= CACHE_LOADER_SIMILARITY; | |
71 } | |
72 | |
73 /* we have the dimensions via pixbuf */ | |
74 if (!cl->cd->dimensions) | |
75 { | |
76 cache_sim_data_set_dimensions(cl->cd, gdk_pixbuf_get_width(pixbuf), | |
77 gdk_pixbuf_get_height(pixbuf)); | |
78 if (cl->todo_mask & CACHE_LOADER_DIMENSIONS) | |
79 { | |
80 cl->todo_mask &= ~CACHE_LOADER_DIMENSIONS; | |
81 cl->done_mask |= CACHE_LOADER_DIMENSIONS; | |
82 } | |
83 } | |
84 } | |
85 | |
86 image_loader_free(cl->il); | |
87 cl->il = NULL; | |
88 | |
89 cl->todo_mask &= ~CACHE_LOADER_SIMILARITY; | |
90 } | |
91 else if (cl->todo_mask & CACHE_LOADER_DIMENSIONS && | |
92 !cl->cd->dimensions) | |
93 { | |
94 if (!cl->error && | |
138 | 95 image_load_dimensions(cl->fd, &cl->cd->width, &cl->cd->height)) |
37 | 96 { |
97 cl->cd->dimensions = TRUE; | |
98 cl->done_mask |= CACHE_LOADER_DIMENSIONS; | |
99 } | |
100 else | |
101 { | |
102 cl->error = TRUE; | |
103 } | |
104 | |
105 cl->todo_mask &= ~CACHE_LOADER_DIMENSIONS; | |
106 } | |
107 else if (cl->todo_mask & CACHE_LOADER_MD5SUM && | |
108 !cl->cd->have_md5sum) | |
109 { | |
138 | 110 if (md5_get_digest_from_file_utf8(cl->fd->path, cl->cd->md5sum)) |
37 | 111 { |
112 cl->cd->have_md5sum = TRUE; | |
113 cl->done_mask |= CACHE_LOADER_MD5SUM; | |
114 } | |
115 else | |
116 { | |
117 cl->error = TRUE; | |
118 } | |
119 | |
120 cl->todo_mask &= ~CACHE_LOADER_MD5SUM; | |
121 } | |
122 else if (cl->todo_mask & CACHE_LOADER_DATE && | |
123 !cl->cd->have_date) | |
124 { | |
125 time_t date = -1; | |
126 ExifData *exif; | |
127 | |
188
0584cb78aa14
write comment and keywords to xmp, sidecars are used if exist
nadvornik
parents:
177
diff
changeset
|
128 exif = exif_read_fd(cl->fd, FALSE); |
37 | 129 if (exif) |
130 { | |
131 gchar *text; | |
132 | |
133 text = exif_get_data_as_text(exif, "fDateTime"); | |
134 if (text) | |
135 { | |
136 struct tm t = { 0 }; | |
137 | |
138 if (sscanf(text, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday, | |
139 &t.tm_hour, &t.tm_min, &t.tm_sec) == 6) | |
140 { | |
141 t.tm_year -= 1900; | |
142 t.tm_mon -= 1; | |
62
5c9f78e1c5f5
Thu Jun 16 01:21:43 2005 John Ellis <johne@verizon.net>
gqview
parents:
37
diff
changeset
|
143 t.tm_isdst = -1; |
37 | 144 date = mktime(&t); |
145 } | |
146 g_free(text); | |
147 } | |
148 exif_free(exif); | |
149 } | |
150 | |
151 cl->cd->date = date; | |
152 cl->cd->have_date = TRUE; | |
153 | |
154 cl->done_mask |= CACHE_LOADER_DATE; | |
155 cl->todo_mask &= ~CACHE_LOADER_DATE; | |
156 } | |
157 else | |
158 { | |
159 /* done, save then call done function */ | |
160 if (enable_thumb_caching && | |
161 cl->done_mask != CACHE_LOADER_NONE) | |
162 { | |
163 gchar *base; | |
164 mode_t mode = 0755; | |
165 | |
138 | 166 base = cache_get_location(CACHE_TYPE_SIM, cl->fd->path, FALSE, &mode); |
37 | 167 if (cache_ensure_dir_exists(base, mode)) |
168 { | |
169 g_free(cl->cd->path); | |
138 | 170 cl->cd->path = cache_get_location(CACHE_TYPE_SIM, cl->fd->path, TRUE, NULL); |
37 | 171 if (cache_sim_data_save(cl->cd)) |
172 { | |
138 | 173 filetime_set(cl->cd->path, filetime(cl->fd->path)); |
37 | 174 } |
175 } | |
176 g_free(base); | |
177 } | |
178 | |
179 cl->idle_id = -1; | |
180 | |
181 if (cl->done_func) | |
182 { | |
183 cl->done_func(cl, cl->error, cl->done_data); | |
184 } | |
185 | |
186 return FALSE; | |
187 } | |
188 | |
189 return TRUE; | |
190 } | |
191 | |
192 static gboolean cache_loader_idle_cb(gpointer data) | |
193 { | |
194 CacheLoader *cl = data; | |
195 | |
196 return cache_loader_process(cl); | |
197 } | |
198 | |
138 | 199 CacheLoader *cache_loader_new(FileData *fd, CacheDataType load_mask, |
37 | 200 CacheLoaderDoneFunc done_func, gpointer done_data) |
201 { | |
202 CacheLoader *cl; | |
203 gchar *found; | |
204 | |
138 | 205 if (!fd || !isfile(fd->path)) return NULL; |
37 | 206 |
207 cl = g_new0(CacheLoader, 1); | |
138 | 208 cl->fd = file_data_ref(fd); |
37 | 209 |
210 cl->done_func = done_func; | |
211 cl->done_data = done_data; | |
212 | |
138 | 213 found = cache_find_location(CACHE_TYPE_SIM, cl->fd->path); |
214 if (found && filetime(found) == filetime(cl->fd->path)) | |
37 | 215 { |
216 cl->cd = cache_sim_data_load(found); | |
217 } | |
218 g_free(found); | |
219 | |
220 if (!cl->cd) cl->cd = cache_sim_data_new(); | |
221 | |
222 cl->todo_mask = load_mask; | |
223 cl->done_mask = CACHE_LOADER_NONE; | |
224 | |
225 cl->il = NULL; | |
226 cl->idle_id = g_idle_add(cache_loader_idle_cb, cl); | |
227 | |
228 cl->error = FALSE; | |
229 | |
230 return cl; | |
231 } | |
232 | |
233 void cache_loader_free(CacheLoader *cl) | |
234 { | |
235 if (!cl) return; | |
236 | |
237 if (cl->idle_id != -1) | |
238 { | |
239 g_source_remove(cl->idle_id); | |
240 cl->idle_id = -1; | |
241 } | |
242 | |
243 image_loader_free(cl->il); | |
244 cache_sim_data_free(cl->cd); | |
245 | |
138 | 246 file_data_unref(cl->fd); |
37 | 247 g_free(cl); |
248 } | |
249 |