2 This file is part of GNUnet.
3 Copyright (C) 2009, 2011 GNUnet e.V.
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.
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.
17 * @file fs/fs_file_information.c
18 * @brief Manage information for publishing directory hierarchies
19 * @author Christian Grothoff
23 #include <extractor.h>
25 #include "gnunet_fs_service.h"
31 * Obtain the name under which this file information
32 * structure is stored on disk. Only works for top-level
33 * file information structures.
35 * @param s structure to get the filename for
36 * @return NULL on error, otherwise filename that
37 * can be used to read this fi-struct from disk.
40 GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s)
44 return s->serialization;
48 * Obtain the filename from the file information structure.
50 * @param s structure to get the filename for
51 * @return "filename" field of the structure (can be NULL)
54 GNUNET_FS_file_information_get_filename (struct GNUNET_FS_FileInformation *s)
61 * Set the filename in the file information structure.
62 * If filename was already set, frees it before setting the new one.
63 * Makes a copy of the argument.
65 * @param s structure to get the filename for
66 * @param filename filename to set
69 GNUNET_FS_file_information_set_filename (struct GNUNET_FS_FileInformation *s,
72 GNUNET_free_non_null (s->filename);
74 s->filename = GNUNET_strdup (filename);
81 * Create an entry for a file in a publish-structure.
83 * @param h handle to the file sharing subsystem
84 * @param client_info initial value for the client-info value for this entry
85 * @param filename name of the file or directory to publish
86 * @param keywords under which keywords should this file be available
87 * directly; can be NULL
88 * @param meta metadata for the file
89 * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion,
90 * #GNUNET_SYSERR for simulation
91 * @param bo block options
92 * @return publish structure entry for the file
94 struct GNUNET_FS_FileInformation *
95 GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h,
98 const struct GNUNET_FS_Uri
101 GNUNET_CONTAINER_MetaData *meta,
103 const struct GNUNET_FS_BlockOptions
108 struct GNUNET_FS_FileInformation *ret;
113 char fn_conv[MAX_PATH];
116 /* FIXME: should include_symbolic_links be GNUNET_NO or GNUNET_YES here? */
117 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fsize, GNUNET_NO, GNUNET_YES))
119 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
122 fi = GNUNET_FS_make_file_reader_context_ (filename);
129 GNUNET_FS_file_information_create_from_reader (h, client_info,
131 &GNUNET_FS_data_reader_file_,
137 ret->filename = GNUNET_strdup (filename);
141 plibc_conv_to_win_path (filename, fn_conv);
144 while (NULL != (ss = strstr (fn, DIR_SEPARATOR_STR)))
146 /* FIXME: If we assume that on other platforms CRT is UTF-8-aware, then
147 * this should be changed to EXTRACTOR_METAFORMAT_UTF8
150 GNUNET_CONTAINER_meta_data_insert (ret->meta, "<gnunet>",
151 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
152 EXTRACTOR_METAFORMAT_C_STRING,
153 "text/plain", fn, strlen (fn) + 1);
155 GNUNET_CONTAINER_meta_data_insert (ret->meta, "<gnunet>",
156 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
157 EXTRACTOR_METAFORMAT_UTF8,
158 "text/plain", fn, strlen (fn) + 1);
165 * Create an entry for a file in a publish-structure.
167 * @param h handle to the file sharing subsystem
168 * @param client_info initial value for the client-info value for this entry
169 * @param length length of the file
170 * @param data data for the file (should not be used afterwards by
171 * the caller; callee will "free")
172 * @param keywords under which keywords should this file be available
173 * directly; can be NULL
174 * @param meta metadata for the file
175 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
176 * GNUNET_SYSERR for simulation
177 * @param bo block options
178 * @return publish structure entry for the file
180 struct GNUNET_FS_FileInformation *
181 GNUNET_FS_file_information_create_from_data (struct GNUNET_FS_Handle *h,
182 void *client_info, uint64_t length,
184 const struct GNUNET_FS_Uri
187 GNUNET_CONTAINER_MetaData *meta,
189 const struct GNUNET_FS_BlockOptions
192 if (GNUNET_YES == do_index)
197 return GNUNET_FS_file_information_create_from_reader (h, client_info, length,
198 &GNUNET_FS_data_reader_copy_,
199 data, keywords, meta,
205 * Create an entry for a file in a publish-structure.
207 * @param h handle to the file sharing subsystem
208 * @param client_info initial value for the client-info value for this entry
209 * @param length length of the file
210 * @param reader function that can be used to obtain the data for the file
211 * @param reader_cls closure for "reader"
212 * @param keywords under which keywords should this file be available
213 * directly; can be NULL
214 * @param meta metadata for the file
215 * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion,
216 * #GNUNET_SYSERR for simulation
217 * @param bo block options
218 * @return publish structure entry for the file
220 struct GNUNET_FS_FileInformation *
221 GNUNET_FS_file_information_create_from_reader (struct GNUNET_FS_Handle *h,
224 GNUNET_FS_DataReader reader,
226 const struct GNUNET_FS_Uri
229 GNUNET_CONTAINER_MetaData *meta,
232 GNUNET_FS_BlockOptions *bo)
234 struct GNUNET_FS_FileInformation *ret;
236 if ((GNUNET_YES == do_index) && (reader != &GNUNET_FS_data_reader_file_))
241 ret = GNUNET_new (struct GNUNET_FS_FileInformation);
243 ret->client_info = client_info;
244 ret->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
245 if (ret->meta == NULL)
246 ret->meta = GNUNET_CONTAINER_meta_data_create ();
247 ret->keywords = (keywords == NULL) ? NULL : GNUNET_FS_uri_dup (keywords);
248 ret->data.file.reader = reader;
249 ret->data.file.reader_cls = reader_cls;
250 ret->data.file.do_index = do_index;
251 ret->data.file.file_size = length;
258 * Test if a given entry represents a directory.
260 * @param ent check if this FI represents a directory
261 * @return #GNUNET_YES if so, #GNUNET_NO if not
264 GNUNET_FS_file_information_is_directory (const struct GNUNET_FS_FileInformation
267 return ent->is_directory;
272 * Create an entry for an empty directory in a publish-structure.
274 * @param h handle to the file sharing subsystem
275 * @param client_info initial value for the client-info value for this entry
276 * @param meta metadata for the directory
277 * @param keywords under which keywords should this directory be available
278 * directly; can be NULL
279 * @param bo block options
280 * @param filename name of the directory; can be NULL
281 * @return publish structure entry for the directory , NULL on error
283 struct GNUNET_FS_FileInformation *
284 GNUNET_FS_file_information_create_empty_directory (struct GNUNET_FS_Handle *h,
286 const struct GNUNET_FS_Uri
289 GNUNET_CONTAINER_MetaData
292 GNUNET_FS_BlockOptions *bo,
293 const char *filename)
295 struct GNUNET_FS_FileInformation *ret;
297 ret = GNUNET_new (struct GNUNET_FS_FileInformation);
299 ret->client_info = client_info;
300 ret->meta = GNUNET_CONTAINER_meta_data_duplicate (meta);
301 ret->keywords = GNUNET_FS_uri_dup (keywords);
303 ret->is_directory = GNUNET_YES;
304 if (filename != NULL)
305 ret->filename = GNUNET_strdup (filename);
311 * Add an entry to a directory in a publish-structure. Clients
312 * should never modify publish structures that were passed to
313 * #GNUNET_FS_publish_start already.
315 * @param dir the directory
316 * @param ent the entry to add; the entry must not have been
317 * added to any other directory at this point and
318 * must not include @a dir in its structure
319 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
322 GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir,
323 struct GNUNET_FS_FileInformation *ent)
325 if ((ent->dir != NULL) || (ent->next != NULL) || (dir->is_directory != GNUNET_YES))
328 return GNUNET_SYSERR;
331 ent->next = dir->data.dir.entries;
332 dir->data.dir.entries = ent;
333 dir->data.dir.dir_size = 0;
339 * Inspect a file or directory in a publish-structure. Clients
340 * should never modify publish structures that were passed to
341 * #GNUNET_FS_publish_start already. When called on a directory,
342 * this function will FIRST call @a proc with information about
343 * the directory itself and then for each of the files in the
344 * directory (but not for files in subdirectories). When called
345 * on a file, @a proc will be called exactly once (with information
346 * about the specific file).
348 * @param dir the directory
349 * @param proc function to call on each entry
350 * @param proc_cls closure for @a proc
353 GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir,
354 GNUNET_FS_FileInformationProcessor proc,
357 struct GNUNET_FS_FileInformation *pos;
363 (dir->is_directory == GNUNET_YES) ? dir->data.dir.dir_size : dir->data.
365 dir->meta, &dir->keywords, &dir->bo,
366 (dir->is_directory == GNUNET_YES) ? &no : &dir->data.file.do_index,
369 if (dir->is_directory != GNUNET_YES)
371 pos = dir->data.dir.entries;
377 (pos->is_directory == GNUNET_YES) ? pos->data.dir.dir_size : pos->data.
378 file.file_size, pos->meta, &pos->keywords, &pos->bo,
379 (pos->is_directory == GNUNET_YES) ? &no : &pos->data.file.do_index,
388 * Destroy publish-structure. Clients should never destroy publish
389 * structures that were passed to #GNUNET_FS_publish_start already.
391 * @param fi structure to destroy
392 * @param cleaner function to call on each entry in the structure
393 * (useful to clean up client_info); can be NULL; return
395 * @param cleaner_cls closure for @a cleaner
398 GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi,
399 GNUNET_FS_FileInformationProcessor cleaner,
402 struct GNUNET_FS_FileInformation *pos;
406 if (GNUNET_YES == fi->is_directory)
408 /* clean up directory */
409 while (NULL != (pos = fi->data.dir.entries))
411 fi->data.dir.entries = pos->next;
412 GNUNET_FS_file_information_destroy (pos, cleaner, cleaner_cls);
414 /* clean up client-info */
416 cleaner (cleaner_cls, fi, fi->data.dir.dir_size, fi->meta, &fi->keywords,
417 &fi->bo, &no, &fi->client_info);
418 GNUNET_free_non_null (fi->data.dir.dir_data);
422 /* call clean-up function of the reader */
423 if (NULL != fi->data.file.reader)
425 (void) fi->data.file.reader (fi->data.file.reader_cls, 0, 0, NULL, NULL);
426 fi->data.file.reader = NULL;
428 /* clean up client-info */
430 cleaner (cleaner_cls, fi, fi->data.file.file_size, fi->meta,
431 &fi->keywords, &fi->bo, &fi->data.file.do_index,
434 GNUNET_free_non_null (fi->filename);
435 GNUNET_free_non_null (fi->emsg);
436 if (NULL != fi->sks_uri)
437 GNUNET_FS_uri_destroy (fi->sks_uri);
438 if (NULL != fi->chk_uri)
439 GNUNET_FS_uri_destroy (fi->chk_uri);
440 /* clean up serialization */
441 if ((NULL != fi->serialization) && (0 != UNLINK (fi->serialization)))
442 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
444 if (NULL != fi->keywords)
445 GNUNET_FS_uri_destroy (fi->keywords);
446 if (NULL != fi->meta)
447 GNUNET_CONTAINER_meta_data_destroy (fi->meta);
448 GNUNET_free_non_null (fi->serialization);
451 GNUNET_FS_tree_encoder_finish (fi->te, NULL);
458 /* end of fs_file_information.c */