aboutsummaryrefslogtreecommitdiff
path: root/src/service/fs/fs_file_information.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/fs/fs_file_information.c')
-rw-r--r--src/service/fs/fs_file_information.c407
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 */
44const char *
45GNUNET_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 */
59const char *
60GNUNET_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 */
75void
76GNUNET_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
87struct GNUNET_FS_FileInformation *
88GNUNET_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
147struct GNUNET_FS_FileInformation *
148GNUNET_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
176struct GNUNET_FS_FileInformation *
177GNUNET_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 */
217int
218GNUNET_FS_file_information_is_directory (
219 const struct GNUNET_FS_FileInformation *ent)
220{
221 return ent->is_directory;
222}
223
224
225struct GNUNET_FS_FileInformation *
226GNUNET_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
249int
250GNUNET_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 */
281void
282GNUNET_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 */
334void
335GNUNET_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 */