Branch data Line data Source code
1 : : /* -*- mode: C -*-
2 : : *
3 : : * File: pdf-fsys.c
4 : : * Date: Thu May 22 15:51:13 2008
5 : : *
6 : : * GNU PDF Library - Filesystem Module
7 : : *
8 : : */
9 : :
10 : : /* Copyright (C) 2008, 2011 Free Software Foundation, Inc. */
11 : :
12 : : /* This program is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU General Public License as published by
14 : : * the Free Software Foundation, either version 3 of the License, or
15 : : * (at your option) any later version.
16 : : *
17 : : * This program is distributed in the hope that it will be useful,
18 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : : * GNU General Public License for more details.
21 : : *
22 : : * You should have received a copy of the GNU General Public License
23 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 : : */
25 : :
26 : : #include <config.h>
27 : :
28 : : #include <pthread.h>
29 : :
30 : : #include <pdf-alloc.h>
31 : : #include <pdf-hash-helper.h>
32 : : #include <pdf-fsys.h>
33 : : #include <pdf-fsys-disk.h>
34 : :
35 : : #if PDF_HAVE_FSYS_HTTP
36 : : # include <pdf-fsys-http.h>
37 : : #endif /* PDF_HAVE_FSYS_HTTP */
38 : :
39 : : /* Hash of filesystem implementations */
40 : : pdf_hash_t *fsys_implementations;
41 : : pthread_mutex_t fsys_implementations_mutex = PTHREAD_MUTEX_INITIALIZER;
42 : :
43 : : static pdf_bool_t
44 : 745 : validate_implementation (const pdf_char_t *id,
45 : : const struct pdf_fsys_s *implementation,
46 : : pdf_error_t **error)
47 : : {
48 : : /* Validate the implementation */
49 : : #define VALIDATE_METHOD(method) do { \
50 : : if (!implementation->method) \
51 : : { \
52 : : pdf_set_error (error, \
53 : : PDF_EDOMAIN_BASE_FSYS, \
54 : : PDF_ERROR, \
55 : : "Missing method '%s' in Filesystem '%s' implementation", \
56 : : #method, \
57 : : id); \
58 : : return PDF_FALSE; \
59 : : } \
60 : : } while (0)
61 : :
62 [ - + ]: 745 : VALIDATE_METHOD (get_free_space_fn);
63 : :
64 [ - + ]: 745 : VALIDATE_METHOD (create_folder_fn);
65 [ - + ]: 745 : VALIDATE_METHOD (get_folder_contents_fn);
66 [ - + ]: 745 : VALIDATE_METHOD (remove_folder_fn);
67 : :
68 [ - + ]: 745 : VALIDATE_METHOD (get_parent_fn);
69 [ - + ]: 745 : VALIDATE_METHOD (get_basename_fn);
70 [ - + ]: 745 : VALIDATE_METHOD (compare_path_p_fn);
71 [ - + ]: 745 : VALIDATE_METHOD (build_path_fn);
72 [ - + ]: 745 : VALIDATE_METHOD (get_url_from_path_fn);
73 [ - + ]: 745 : VALIDATE_METHOD (get_path_from_url_fn);
74 : :
75 [ - + ]: 745 : VALIDATE_METHOD (item_p_fn);
76 [ - + ]: 745 : VALIDATE_METHOD (get_item_props_fn);
77 [ - + ]: 745 : VALIDATE_METHOD (item_readable_p_fn);
78 [ - + ]: 745 : VALIDATE_METHOD (item_writable_p_fn);
79 : :
80 [ - + ]: 745 : VALIDATE_METHOD (file_open_fn);
81 [ - + ]: 745 : VALIDATE_METHOD (file_open_tmp_fn);
82 [ - + ]: 745 : VALIDATE_METHOD (file_reopen_fn);
83 [ - + ]: 745 : VALIDATE_METHOD (file_close_fn);
84 : :
85 [ - + ]: 745 : VALIDATE_METHOD (file_get_size_fn);
86 [ - + ]: 745 : VALIDATE_METHOD (file_can_set_size_p_fn);
87 [ - + ]: 745 : VALIDATE_METHOD (file_set_size_fn);
88 : :
89 [ - + ]: 745 : VALIDATE_METHOD (file_get_pos_fn);
90 [ - + ]: 745 : VALIDATE_METHOD (file_set_pos_fn);
91 : :
92 [ - + ]: 745 : VALIDATE_METHOD (file_read_fn);
93 [ - + ]: 745 : VALIDATE_METHOD (file_write_fn);
94 [ - + ]: 745 : VALIDATE_METHOD (file_flush_fn);
95 : :
96 [ - + ]: 745 : VALIDATE_METHOD (file_request_ria_fn);
97 [ - + ]: 745 : VALIDATE_METHOD (file_has_ria_fn);
98 [ - + ]: 745 : VALIDATE_METHOD (file_cancel_ria_fn);
99 : :
100 : : #undef VALIDATE_METHOD
101 : :
102 : 745 : return PDF_TRUE;
103 : : }
104 : :
105 : : pdf_bool_t
106 : 745 : pdf_fsys_add (const pdf_char_t *id,
107 : : const struct pdf_fsys_s *fsys,
108 : : pdf_fsys_deinit_fn_t fsys_deinit,
109 : : pdf_error_t **error)
110 : : {
111 [ - + ]: 745 : PDF_ASSERT_RETURN_VAL (fsys, PDF_FALSE);
112 : :
113 [ - + ]: 745 : if (!validate_implementation (id, fsys, error))
114 : 0 : return PDF_FALSE;
115 : :
116 : 745 : pthread_mutex_lock (&fsys_implementations_mutex);
117 : :
118 : : /* If first implementation, allocate new HT */
119 [ + - ]: 745 : if (!fsys_implementations)
120 : : {
121 : 745 : fsys_implementations = pdf_hash_new (error);
122 [ - + ]: 745 : if (!fsys_implementations)
123 : : {
124 : 0 : pthread_mutex_unlock (&fsys_implementations_mutex);
125 : 0 : return PDF_FALSE;
126 : : }
127 : : }
128 : :
129 : : /* Check if ID already exists */
130 [ - + ]: 745 : if (pdf_hash_key_p (fsys_implementations, id))
131 : : {
132 : 0 : pdf_set_error (error,
133 : : PDF_EDOMAIN_BASE_FSYS,
134 : : PDF_EEXIST,
135 : : "Filesystem with ID '%s' already exists",
136 : : id);
137 : 0 : pthread_mutex_unlock (&fsys_implementations_mutex);
138 : 0 : return PDF_FALSE;
139 : : }
140 : :
141 : : /* Add the new implementation */
142 [ - + ]: 745 : if (!pdf_hash_add (fsys_implementations,
143 : : id,
144 : : fsys,
145 : : (pdf_hash_value_dispose_fn_t)fsys_deinit,
146 : : error))
147 : : {
148 : 0 : pthread_mutex_unlock (&fsys_implementations_mutex);
149 : 0 : return PDF_FALSE;
150 : : }
151 : :
152 : 745 : pthread_mutex_unlock (&fsys_implementations_mutex);
153 : 745 : return PDF_TRUE;
154 : : }
155 : :
156 : : void
157 : 745 : pdf_fsys_remove (const pdf_char_t *id)
158 : : {
159 : 745 : pthread_mutex_lock (&fsys_implementations_mutex);
160 : :
161 [ + - ]: 745 : if (fsys_implementations)
162 : : {
163 [ - + ]: 745 : if (!pdf_hash_remove (fsys_implementations, id))
164 : : {
165 : : /* If the implementation was not removed is because it was not registered,
166 : : * and that is a programmer error */
167 : 0 : PDF_ASSERT_TRACE_NOT_REACHED ();
168 : : }
169 [ + - ]: 745 : else if (pdf_hash_size (fsys_implementations) == 0)
170 : : {
171 : : /* Remove hash if no contents */
172 : 745 : pdf_hash_destroy (fsys_implementations);
173 : 745 : fsys_implementations = NULL;
174 : : }
175 : : }
176 : :
177 : 745 : pthread_mutex_unlock (&fsys_implementations_mutex);
178 : 745 : }
179 : :
180 : : const pdf_fsys_t *
181 : 90 : pdf_fsys_get (const pdf_char_t *id)
182 : : {
183 : : const pdf_fsys_t *impl;
184 : :
185 : 90 : pthread_mutex_lock (&fsys_implementations_mutex);
186 : :
187 [ + - ]: 180 : impl = (fsys_implementations ?
188 : 90 : pdf_hash_get_value (fsys_implementations, id) :
189 : : NULL);;
190 : :
191 : 90 : pthread_mutex_unlock (&fsys_implementations_mutex);
192 : :
193 : 90 : return impl;
194 : : }
195 : :
196 : : void
197 : 0 : pdf_fsys_foreach (pdf_fsys_foreach_fn_t foreach_fn,
198 : : void *user_data)
199 : : {
200 : : pdf_hash_iterator_t it;
201 : :
202 : : /* Note we're locking the whole implementations HT here, so please do not call
203 : : * pdf_fsys_remove() or pdf_fsys_get() from within the foreach_fn cb. */
204 : 0 : pthread_mutex_lock (&fsys_implementations_mutex);
205 : :
206 [ # # ]: 0 : if (fsys_implementations)
207 : : {
208 : : const pdf_char_t *id;
209 : : const void *impl;
210 : :
211 : 0 : pdf_hash_iterator_init (&it, fsys_implementations);
212 : :
213 [ # # ]: 0 : while (pdf_hash_iterator_next (&it, &id, &impl))
214 : 0 : foreach_fn (user_data, id, impl);
215 : :
216 : 0 : pdf_hash_iterator_deinit (&it);
217 : : }
218 : :
219 : 0 : pthread_mutex_unlock (&fsys_implementations_mutex);
220 : 0 : }
221 : :
222 : : pdf_bool_t
223 : 745 : pdf_fsys_init (pdf_error_t **error)
224 : : {
225 : : /* Init default DISK filesystem */
226 [ - + ]: 745 : if (!pdf_fsys_disk_init (error))
227 : 0 : return PDF_FALSE;
228 : :
229 : : #if PDF_HAVE_FSYS_HTTP
230 : : /* Init HTTP read-only filesystem */
231 : : if (!pdf_fsys_http_init (error))
232 : : return PDF_FALSE;
233 : : #endif /* PDF_HAVE_FSYS_HTTP */
234 : :
235 : 745 : return PDF_TRUE;
236 : : }
237 : :
238 : : void
239 : 745 : pdf_fsys_deinit (void)
240 : : {
241 : : #if PDF_HAVE_FSYS_HTTP
242 : : /* Deinit HTTP read-only filesystem */
243 : : pdf_fsys_http_deinit ();
244 : : #endif /* PDF_HAVE_FSYS_HTTP */
245 : :
246 : : /* Deinit DISK filesystem */
247 : 745 : pdf_fsys_disk_deinit ();
248 : 745 : }
249 : :
250 : : pdf_hash_t *
251 : 0 : pdf_fsys_item_props_to_hash (const struct pdf_fsys_item_props_s *item_props,
252 : : pdf_error_t **error)
253 : : {
254 : : pdf_char_t *creation_date_str;
255 : : pdf_char_t *mod_date_str;
256 : : pdf_hash_t *props_hash;
257 : :
258 : : /* Create new hash table */
259 : 0 : props_hash = pdf_hash_new (error);
260 [ # # ]: 0 : if (!props_hash)
261 : 0 : return NULL;
262 : :
263 : : /* Associate values with hash keys */
264 [ # # ][ # # ]: 0 : if ((!pdf_hash_add_bool (props_hash,
[ # # ][ # # ]
265 : : PDF_FSYS_ITEM_IS_HIDDEN,
266 : 0 : item_props->is_hidden,
267 : : error)) ||
268 : : (!pdf_hash_add_bool (props_hash,
269 : : PDF_FSYS_ITEM_IS_READABLE,
270 : 0 : item_props->is_readable,
271 : : error)) ||
272 : : (!pdf_hash_add_bool (props_hash,
273 : : PDF_FSYS_ITEM_IS_WRITABLE,
274 : 0 : item_props->is_writable,
275 : : error)) ||
276 : : (!pdf_hash_add_size (props_hash,
277 : : PDF_FSYS_ITEM_FILE_SIZE,
278 : : (pdf_size_t) item_props->file_size,
279 : : error)))
280 : : {
281 : 0 : pdf_hash_destroy (props_hash);
282 : 0 : return NULL;
283 : : }
284 : :
285 : : /* Get creation time from the props structure */
286 : 0 : creation_date_str = pdf_time_to_string (&item_props->creation_date,
287 : : PDF_TIME_STRING_FORMAT_PDF,
288 : : PDF_TIME_STRING_TRAILING_APOSTROPHE,
289 : : error);
290 [ # # ]: 0 : if (!creation_date_str)
291 : : {
292 : 0 : pdf_hash_destroy (props_hash);
293 : 0 : return NULL;
294 : : }
295 : :
296 [ # # ]: 0 : if (!pdf_hash_add_string (props_hash,
297 : : PDF_FSYS_ITEM_CREATION_DATE,
298 : : creation_date_str,
299 : : error))
300 : : {
301 : 0 : pdf_dealloc (creation_date_str);
302 : 0 : pdf_hash_destroy (props_hash);
303 : 0 : return NULL;
304 : : }
305 : :
306 : : /* Get mtime from the props structure */
307 : 0 : mod_date_str = pdf_time_to_string (&item_props->modification_date,
308 : : PDF_TIME_STRING_FORMAT_PDF,
309 : : PDF_TIME_STRING_TRAILING_APOSTROPHE,
310 : : error);
311 [ # # ]: 0 : if (!mod_date_str)
312 : : {
313 : 0 : pdf_hash_destroy (props_hash);
314 : 0 : return NULL;
315 : : }
316 : :
317 [ # # ]: 0 : if (!pdf_hash_add_string (props_hash,
318 : : PDF_FSYS_ITEM_MODIFICATION_DATE,
319 : : mod_date_str,
320 : : error))
321 : : {
322 : 0 : pdf_dealloc (mod_date_str);
323 : 0 : pdf_hash_destroy (props_hash);
324 : 0 : return NULL;
325 : : }
326 : :
327 : : /* Done */
328 : 0 : return props_hash;
329 : : }
330 : :
331 : : pdf_bool_t
332 : 26 : pdf_fsys_impl_helper_file_init (struct pdf_fsys_file_s *common,
333 : : const struct pdf_fsys_s *fsys,
334 : : const pdf_text_t *path,
335 : : enum pdf_fsys_file_mode_e mode,
336 : : pdf_error_t **error)
337 : : {
338 [ - + ]: 26 : PDF_ASSERT_RETURN_VAL (common != NULL, PDF_FALSE);
339 : :
340 [ + + ]: 26 : if (path)
341 : : {
342 : 25 : common->unicode_path = pdf_text_dup (path, error);
343 [ - + ]: 25 : if (!common->unicode_path)
344 : 0 : return PDF_FALSE;
345 : : }
346 : : else
347 : 1 : common->unicode_path = NULL;
348 : :
349 : 26 : common->fsys = fsys;
350 : 26 : common->mode = mode;
351 : :
352 : 26 : return PDF_TRUE;
353 : : }
354 : :
355 : : void
356 : 26 : pdf_fsys_impl_helper_file_deinit (struct pdf_fsys_file_s *common)
357 : : {
358 [ - + ]: 26 : PDF_ASSERT_RETURN (common != NULL);
359 : :
360 [ + + ]: 26 : if (common->unicode_path)
361 : 26 : pdf_text_destroy (common->unicode_path);
362 : : }
363 : :
364 : : /* End of pdf-fsys.c */
|