diff options
Diffstat (limited to 'src/service/fs/fs_file_information.c')
-rw-r--r-- | src/service/fs/fs_file_information.c | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/src/service/fs/fs_file_information.c b/src/service/fs/fs_file_information.c new file mode 100644 index 000000000..f23b9da2a --- /dev/null +++ b/src/service/fs/fs_file_information.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2011 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file fs/fs_file_information.c | ||
23 | * @brief Manage information for publishing directory hierarchies | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #if HAVE_EXTRACTOR_H | ||
28 | #include <extractor.h> | ||
29 | #endif | ||
30 | #include "gnunet_fs_service.h" | ||
31 | #include "fs_api.h" | ||
32 | #include "fs_tree.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Obtain the name under which this file information | ||
37 | * structure is stored on disk. Only works for top-level | ||
38 | * file information structures. | ||
39 | * | ||
40 | * @param s structure to get the filename for | ||
41 | * @return NULL on error, otherwise filename that | ||
42 | * can be used to read this fi-struct from disk. | ||
43 | */ | ||
44 | const char * | ||
45 | GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s) | ||
46 | { | ||
47 | if (NULL != s->dir) | ||
48 | return NULL; | ||
49 | return s->serialization; | ||
50 | } | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Obtain the filename from the file information structure. | ||
55 | * | ||
56 | * @param s structure to get the filename for | ||
57 | * @return "filename" field of the structure (can be NULL) | ||
58 | */ | ||
59 | const char * | ||
60 | GNUNET_FS_file_information_get_filename (const struct | ||
61 | GNUNET_FS_FileInformation *s) | ||
62 | { | ||
63 | return s->filename; | ||
64 | } | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Set the filename in the file information structure. | ||
69 | * If filename was already set, frees it before setting the new one. | ||
70 | * Makes a copy of the argument. | ||
71 | * | ||
72 | * @param s structure to get the filename for | ||
73 | * @param filename filename to set | ||
74 | */ | ||
75 | void | ||
76 | GNUNET_FS_file_information_set_filename (struct GNUNET_FS_FileInformation *s, | ||
77 | const char *filename) | ||
78 | { | ||
79 | GNUNET_free (s->filename); | ||
80 | if (filename) | ||
81 | s->filename = GNUNET_strdup (filename); | ||
82 | else | ||
83 | s->filename = NULL; | ||
84 | } | ||
85 | |||
86 | |||
87 | struct GNUNET_FS_FileInformation * | ||
88 | GNUNET_FS_file_information_create_from_file ( | ||
89 | struct GNUNET_FS_Handle *h, | ||
90 | void *client_info, | ||
91 | const char *filename, | ||
92 | const struct GNUNET_FS_Uri *keywords, | ||
93 | const struct GNUNET_FS_MetaData *meta, | ||
94 | int do_index, | ||
95 | const struct GNUNET_FS_BlockOptions *bo) | ||
96 | { | ||
97 | struct FileInfo *fi; | ||
98 | uint64_t fsize; | ||
99 | struct GNUNET_FS_FileInformation *ret; | ||
100 | const char *fn; | ||
101 | const char *ss; | ||
102 | |||
103 | /* FIXME: should include_symbolic_links be GNUNET_NO or GNUNET_YES here? */ | ||
104 | if (GNUNET_OK != | ||
105 | GNUNET_DISK_file_size (filename, &fsize, GNUNET_NO, GNUNET_YES)) | ||
106 | { | ||
107 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); | ||
108 | return NULL; | ||
109 | } | ||
110 | fi = GNUNET_FS_make_file_reader_context_ (filename); | ||
111 | if (NULL == fi) | ||
112 | { | ||
113 | GNUNET_break (0); | ||
114 | return NULL; | ||
115 | } | ||
116 | ret = | ||
117 | GNUNET_FS_file_information_create_from_reader (h, | ||
118 | client_info, | ||
119 | fsize, | ||
120 | &GNUNET_FS_data_reader_file_, | ||
121 | fi, | ||
122 | keywords, | ||
123 | meta, | ||
124 | do_index, | ||
125 | bo); | ||
126 | if (ret == NULL) | ||
127 | return NULL; | ||
128 | ret->h = h; | ||
129 | ret->filename = GNUNET_strdup (filename); | ||
130 | fn = filename; | ||
131 | while (NULL != (ss = strstr (fn, DIR_SEPARATOR_STR))) | ||
132 | fn = ss + 1; | ||
133 | /* FIXME: If we assume that on other platforms CRT is UTF-8-aware, then | ||
134 | * this should be changed to EXTRACTOR_METAFORMAT_UTF8 | ||
135 | */ | ||
136 | GNUNET_FS_meta_data_insert (ret->meta, | ||
137 | "<gnunet>", | ||
138 | EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, | ||
139 | EXTRACTOR_METAFORMAT_C_STRING, | ||
140 | "text/plain", | ||
141 | fn, | ||
142 | strlen (fn) + 1); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | |||
147 | struct GNUNET_FS_FileInformation * | ||
148 | GNUNET_FS_file_information_create_from_data ( | ||
149 | struct GNUNET_FS_Handle *h, | ||
150 | void *client_info, | ||
151 | uint64_t length, | ||
152 | void *data, | ||
153 | const struct GNUNET_FS_Uri *keywords, | ||
154 | const struct GNUNET_FS_MetaData *meta, | ||
155 | int do_index, | ||
156 | const struct GNUNET_FS_BlockOptions *bo) | ||
157 | { | ||
158 | if (GNUNET_YES == do_index) | ||
159 | { | ||
160 | GNUNET_break (0); | ||
161 | return NULL; | ||
162 | } | ||
163 | return GNUNET_FS_file_information_create_from_reader (h, | ||
164 | client_info, | ||
165 | length, | ||
166 | & | ||
167 | GNUNET_FS_data_reader_copy_, | ||
168 | data, | ||
169 | keywords, | ||
170 | meta, | ||
171 | do_index, | ||
172 | bo); | ||
173 | } | ||
174 | |||
175 | |||
176 | struct GNUNET_FS_FileInformation * | ||
177 | GNUNET_FS_file_information_create_from_reader ( | ||
178 | struct GNUNET_FS_Handle *h, | ||
179 | void *client_info, | ||
180 | uint64_t length, | ||
181 | GNUNET_FS_DataReader reader, | ||
182 | void *reader_cls, | ||
183 | const struct GNUNET_FS_Uri *keywords, | ||
184 | const struct GNUNET_FS_MetaData *meta, | ||
185 | int do_index, | ||
186 | const struct GNUNET_FS_BlockOptions *bo) | ||
187 | { | ||
188 | struct GNUNET_FS_FileInformation *ret; | ||
189 | |||
190 | if ((GNUNET_YES == do_index) && (reader != &GNUNET_FS_data_reader_file_)) | ||
191 | { | ||
192 | GNUNET_break (0); | ||
193 | return NULL; | ||
194 | } | ||
195 | ret = GNUNET_new (struct GNUNET_FS_FileInformation); | ||
196 | ret->h = h; | ||
197 | ret->client_info = client_info; | ||
198 | ret->meta = GNUNET_FS_meta_data_duplicate (meta); | ||
199 | if (ret->meta == NULL) | ||
200 | ret->meta = GNUNET_FS_meta_data_create (); | ||
201 | ret->keywords = (keywords == NULL) ? NULL : GNUNET_FS_uri_dup (keywords); | ||
202 | ret->data.file.reader = reader; | ||
203 | ret->data.file.reader_cls = reader_cls; | ||
204 | ret->data.file.do_index = do_index; | ||
205 | ret->data.file.file_size = length; | ||
206 | ret->bo = *bo; | ||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * Test if a given entry represents a directory. | ||
213 | * | ||
214 | * @param ent check if this FI represents a directory | ||
215 | * @return #GNUNET_YES if so, #GNUNET_NO if not | ||
216 | */ | ||
217 | int | ||
218 | GNUNET_FS_file_information_is_directory ( | ||
219 | const struct GNUNET_FS_FileInformation *ent) | ||
220 | { | ||
221 | return ent->is_directory; | ||
222 | } | ||
223 | |||
224 | |||
225 | struct GNUNET_FS_FileInformation * | ||
226 | GNUNET_FS_file_information_create_empty_directory ( | ||
227 | struct GNUNET_FS_Handle *h, | ||
228 | void *client_info, | ||
229 | const struct GNUNET_FS_Uri *keywords, | ||
230 | const struct GNUNET_FS_MetaData *meta, | ||
231 | const struct GNUNET_FS_BlockOptions *bo, | ||
232 | const char *filename) | ||
233 | { | ||
234 | struct GNUNET_FS_FileInformation *ret; | ||
235 | |||
236 | ret = GNUNET_new (struct GNUNET_FS_FileInformation); | ||
237 | ret->h = h; | ||
238 | ret->client_info = client_info; | ||
239 | ret->meta = GNUNET_FS_meta_data_duplicate (meta); | ||
240 | ret->keywords = GNUNET_FS_uri_dup (keywords); | ||
241 | ret->bo = *bo; | ||
242 | ret->is_directory = GNUNET_YES; | ||
243 | if (filename != NULL) | ||
244 | ret->filename = GNUNET_strdup (filename); | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | |||
249 | int | ||
250 | GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir, | ||
251 | struct GNUNET_FS_FileInformation *ent) | ||
252 | { | ||
253 | if ((ent->dir != NULL) || (ent->next != NULL) || | ||
254 | (dir->is_directory != GNUNET_YES)) | ||
255 | { | ||
256 | GNUNET_break (0); | ||
257 | return GNUNET_SYSERR; | ||
258 | } | ||
259 | ent->dir = dir; | ||
260 | ent->next = dir->data.dir.entries; | ||
261 | dir->data.dir.entries = ent; | ||
262 | dir->data.dir.dir_size = 0; | ||
263 | return GNUNET_OK; | ||
264 | } | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Inspect a file or directory in a publish-structure. Clients | ||
269 | * should never modify publish structures that were passed to | ||
270 | * #GNUNET_FS_publish_start already. When called on a directory, | ||
271 | * this function will FIRST call @a proc with information about | ||
272 | * the directory itself and then for each of the files in the | ||
273 | * directory (but not for files in subdirectories). When called | ||
274 | * on a file, @a proc will be called exactly once (with information | ||
275 | * about the specific file). | ||
276 | * | ||
277 | * @param dir the directory | ||
278 | * @param proc function to call on each entry | ||
279 | * @param proc_cls closure for @a proc | ||
280 | */ | ||
281 | void | ||
282 | GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir, | ||
283 | GNUNET_FS_FileInformationProcessor proc, | ||
284 | void *proc_cls) | ||
285 | { | ||
286 | struct GNUNET_FS_FileInformation *pos; | ||
287 | int no; | ||
288 | |||
289 | no = GNUNET_NO; | ||
290 | if (GNUNET_OK != | ||
291 | proc (proc_cls, | ||
292 | dir, | ||
293 | (dir->is_directory == GNUNET_YES) ? dir->data.dir.dir_size | ||
294 | : dir->data.file.file_size, | ||
295 | dir->meta, | ||
296 | &dir->keywords, | ||
297 | &dir->bo, | ||
298 | (dir->is_directory == GNUNET_YES) ? &no : &dir->data.file.do_index, | ||
299 | &dir->client_info)) | ||
300 | return; | ||
301 | if (dir->is_directory != GNUNET_YES) | ||
302 | return; | ||
303 | pos = dir->data.dir.entries; | ||
304 | while (pos != NULL) | ||
305 | { | ||
306 | no = GNUNET_NO; | ||
307 | if (GNUNET_OK != | ||
308 | proc (proc_cls, | ||
309 | pos, | ||
310 | (pos->is_directory == GNUNET_YES) ? pos->data.dir.dir_size | ||
311 | : pos->data.file.file_size, | ||
312 | pos->meta, | ||
313 | &pos->keywords, | ||
314 | &pos->bo, | ||
315 | (pos->is_directory == GNUNET_YES) ? &no | ||
316 | : &pos->data.file.do_index, | ||
317 | &pos->client_info)) | ||
318 | break; | ||
319 | pos = pos->next; | ||
320 | } | ||
321 | } | ||
322 | |||
323 | |||
324 | /** | ||
325 | * Destroy publish-structure. Clients should never destroy publish | ||
326 | * structures that were passed to #GNUNET_FS_publish_start already. | ||
327 | * | ||
328 | * @param fi structure to destroy | ||
329 | * @param cleaner function to call on each entry in the structure | ||
330 | * (useful to clean up client_info); can be NULL; return | ||
331 | * values are ignored | ||
332 | * @param cleaner_cls closure for @a cleaner | ||
333 | */ | ||
334 | void | ||
335 | GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi, | ||
336 | GNUNET_FS_FileInformationProcessor cleaner, | ||
337 | void *cleaner_cls) | ||
338 | { | ||
339 | struct GNUNET_FS_FileInformation *pos; | ||
340 | int no; | ||
341 | |||
342 | no = GNUNET_NO; | ||
343 | if (GNUNET_YES == fi->is_directory) | ||
344 | { | ||
345 | /* clean up directory */ | ||
346 | while (NULL != (pos = fi->data.dir.entries)) | ||
347 | { | ||
348 | fi->data.dir.entries = pos->next; | ||
349 | GNUNET_FS_file_information_destroy (pos, cleaner, cleaner_cls); | ||
350 | } | ||
351 | /* clean up client-info */ | ||
352 | if (NULL != cleaner) | ||
353 | cleaner (cleaner_cls, | ||
354 | fi, | ||
355 | fi->data.dir.dir_size, | ||
356 | fi->meta, | ||
357 | &fi->keywords, | ||
358 | &fi->bo, | ||
359 | &no, | ||
360 | &fi->client_info); | ||
361 | GNUNET_free (fi->data.dir.dir_data); | ||
362 | } | ||
363 | else | ||
364 | { | ||
365 | /* call clean-up function of the reader */ | ||
366 | if (NULL != fi->data.file.reader) | ||
367 | { | ||
368 | (void) fi->data.file.reader (fi->data.file.reader_cls, 0, 0, NULL, NULL); | ||
369 | fi->data.file.reader = NULL; | ||
370 | } | ||
371 | /* clean up client-info */ | ||
372 | if (NULL != cleaner) | ||
373 | cleaner (cleaner_cls, | ||
374 | fi, | ||
375 | fi->data.file.file_size, | ||
376 | fi->meta, | ||
377 | &fi->keywords, | ||
378 | &fi->bo, | ||
379 | &fi->data.file.do_index, | ||
380 | &fi->client_info); | ||
381 | } | ||
382 | GNUNET_free (fi->filename); | ||
383 | GNUNET_free (fi->emsg); | ||
384 | if (NULL != fi->sks_uri) | ||
385 | GNUNET_FS_uri_destroy (fi->sks_uri); | ||
386 | if (NULL != fi->chk_uri) | ||
387 | GNUNET_FS_uri_destroy (fi->chk_uri); | ||
388 | /* clean up serialization */ | ||
389 | if ((NULL != fi->serialization) && (0 != unlink (fi->serialization))) | ||
390 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
391 | "unlink", | ||
392 | fi->serialization); | ||
393 | if (NULL != fi->keywords) | ||
394 | GNUNET_FS_uri_destroy (fi->keywords); | ||
395 | if (NULL != fi->meta) | ||
396 | GNUNET_FS_meta_data_destroy (fi->meta); | ||
397 | GNUNET_free (fi->serialization); | ||
398 | if (NULL != fi->te) | ||
399 | { | ||
400 | GNUNET_FS_tree_encoder_finish (fi->te, NULL); | ||
401 | fi->te = NULL; | ||
402 | } | ||
403 | GNUNET_free (fi); | ||
404 | } | ||
405 | |||
406 | |||
407 | /* end of fs_file_information.c */ | ||