aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO4
-rw-r--r--src/fs/Makefile.am7
-rw-r--r--src/fs/fs.c65
-rw-r--r--src/fs/fs.h12
-rw-r--r--src/fs/fs_directory.c7
-rw-r--r--src/fs/fs_download.c923
-rw-r--r--src/fs/fs_file_information.c269
-rw-r--r--src/fs/fs_namespace.c729
-rw-r--r--src/fs/fs_publish.c459
-rw-r--r--src/fs/fs_search.c572
-rw-r--r--src/fs/fs_test.c259
-rw-r--r--src/fs/fs_unindex.c394
-rw-r--r--src/fs/fs_uri.c133
-rw-r--r--src/fs/test_fs_collection.c100
-rw-r--r--src/fs/test_fs_collection_data.conf9
-rw-r--r--src/fs/test_fs_directory.c7
-rw-r--r--src/fs/test_fs_download.c324
-rw-r--r--src/fs/test_fs_download_recursive.c380
-rw-r--r--src/fs/test_fs_getopt.c7
-rw-r--r--src/fs/test_fs_search_persistence.c213
-rw-r--r--src/fs/test_fs_search_ranking.c250
-rw-r--r--src/fs/test_fs_start_stop.c89
-rw-r--r--src/fs/test_fs_uri.c46
-rw-r--r--src/fs/test_namespace.c136
-rw-r--r--src/include/gnunet_fs_service.h107
25 files changed, 5347 insertions, 154 deletions
diff --git a/TODO b/TODO
index ebccd0a39..8b400d5de 100644
--- a/TODO
+++ b/TODO
@@ -39,8 +39,8 @@ PHASE #2: (Goal: recover basic file-sharing functionality)
39 - review FS API [Nils, Amatus, CG] 39 - review FS API [Nils, Amatus, CG]
40 - design network structs (CS) 40 - design network structs (CS)
41 - implement FS library 41 - implement FS library
42 + URI API 42 + URI API -- DONE (but do more testing)
43 + getopt API 43 + getopt API -- DONE (but do more testing)
44 + persistence mechanism 44 + persistence mechanism
45 + sharing API 45 + sharing API
46 ~ file-information 46 ~ file-information
diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am
index 99b631668..9fca261cb 100644
--- a/src/fs/Makefile.am
+++ b/src/fs/Makefile.am
@@ -13,9 +13,13 @@ endif
13lib_LTLIBRARIES = libgnunetfs.la 13lib_LTLIBRARIES = libgnunetfs.la
14 14
15libgnunetfs_la_SOURCES = \ 15libgnunetfs_la_SOURCES = \
16 fs.c \
16 fs_collection.c \ 17 fs_collection.c \
17 fs_directory.c \ 18 fs_directory.c \
19 fs_file_information.c \
18 fs_getopt.c \ 20 fs_getopt.c \
21 fs_publish.c \
22 fs_namespace.c \
19 fs_uri.c 23 fs_uri.c
20 24
21libgnunetfs_la_LIBADD = \ 25libgnunetfs_la_LIBADD = \
@@ -31,8 +35,8 @@ libgnunetfs_la_LDFLAGS = \
31# gnunet-directory 35# gnunet-directory
32# gnunet-download 36# gnunet-download
33# gnunet-pseudonym 37# gnunet-pseudonym
38# gnunet-publish
34# gnunet-search 39# gnunet-search
35# gnunet-share
36# gnunet-unindex 40# gnunet-unindex
37 41
38#gnunet_directory_SOURCES = 42#gnunet_directory_SOURCES =
@@ -76,4 +80,5 @@ test_fs_uri_LDADD = \
76 $(top_builddir)/src/util/libgnunetutil.la 80 $(top_builddir)/src/util/libgnunetutil.la
77 81
78EXTRA_DIST = \ 82EXTRA_DIST = \
83 test_fs_collection_data.conf \
79 test_fs_uri_data.conf 84 test_fs_uri_data.conf
diff --git a/src/fs/fs.c b/src/fs/fs.c
new file mode 100644
index 000000000..0522b7941
--- /dev/null
+++ b/src/fs/fs.c
@@ -0,0 +1,65 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/fs.c
23 * @brief main FS functions
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_fs_service.h"
29#include "fs.h"
30
31
32
33/**
34 * Setup a connection to the file-sharing service.
35 *
36 * @param sched scheduler to use
37 * @param cfg configuration to use
38 * @param client_name unique identifier for this client
39 * @param upcb function to call to notify about FS actions
40 * @param upcb_cls closure for upcb
41 */
42struct GNUNET_FS_Handle *
43GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched,
44 const struct GNUNET_CONFIGURATION_Handle *cfg,
45 const char *client_name,
46 GNUNET_FS_ProgressCallback upcb,
47 void *upcb_cls)
48{
49 return NULL;
50}
51
52
53/**
54 * Close our connection with the file-sharing service.
55 * The callback given to GNUNET_FS_start will no longer be
56 * called after this function returns.
57 *
58 * @param h handle that was returned from GNUNET_FS_start
59 */
60void
61GNUNET_FS_stop (struct GNUNET_FS_Handle *h)
62{
63}
64
65/* end of fs.c */
diff --git a/src/fs/fs.h b/src/fs/fs.h
index 13129be58..024e0ecc8 100644
--- a/src/fs/fs.h
+++ b/src/fs/fs.h
@@ -129,4 +129,16 @@ struct GNUNET_FS_Uri
129 129
130}; 130};
131 131
132
133/**
134 * Information for a file or directory that is
135 * about to be published.
136 */
137struct GNUNET_FS_FileInformation
138{
139
140
141};
142
143
132#endif 144#endif
diff --git a/src/fs/fs_directory.c b/src/fs/fs_directory.c
index 1ee707cd1..3eb3af50d 100644
--- a/src/fs/fs_directory.c
+++ b/src/fs/fs_directory.c
@@ -231,6 +231,13 @@ GNUNET_FS_directory_list_contents (size_t size,
231 } 231 }
232} 232}
233 233
234
235void
236GNUNET_FS_directory_create ()
237{
238}
239
240
234#if 0 241#if 0
235 242
236 243
diff --git a/src/fs/fs_download.c b/src/fs/fs_download.c
new file mode 100644
index 000000000..cb3b39995
--- /dev/null
+++ b/src/fs/fs_download.c
@@ -0,0 +1,923 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file applications/fs/ecrs/download.c
22 * @brief DOWNLOAD helper methods (which do the real work).
23 * @author Christian Grothoff
24 */
25
26#include "platform.h"
27#include "gnunet_protocols.h"
28#include "gnunet_ecrs_lib.h"
29#include "gnunet_fs_lib.h"
30#include "gnunet_identity_lib.h"
31#include "ecrs_core.h"
32#include "ecrs.h"
33#include "fs.h"
34#include "tree.h"
35
36#define DEBUG_DOWNLOAD GNUNET_NO
37
38/**
39 * Node-specific data (not shared, keep small!). 152 bytes.
40 * Nodes are kept in a doubly-linked list.
41 */
42struct Node
43{
44 /**
45 * Pointer to shared data between all nodes (request manager,
46 * progress data, etc.).
47 */
48 struct GNUNET_ECRS_DownloadContext *ctx;
49
50 /**
51 * Previous entry in DLL.
52 */
53 struct Node *prev;
54
55 /**
56 * Next entry in DLL.
57 */
58 struct Node *next;
59
60 /**
61 * What is the GNUNET_EC_ContentHashKey for this block?
62 */
63 GNUNET_EC_ContentHashKey chk;
64
65 /**
66 * At what offset (on the respective level!) is this
67 * block?
68 */
69 unsigned long long offset;
70
71 /**
72 * 0 for dblocks, >0 for iblocks.
73 */
74 unsigned int level;
75
76};
77
78/**
79 * @brief structure that keeps track of currently pending requests for
80 * a download
81 *
82 * Handle to the state of a request manager. Here we keep track of
83 * which queries went out with which priorities and which nodes in
84 * the merkle-tree are waiting for the replies.
85 */
86struct GNUNET_ECRS_DownloadContext
87{
88
89 /**
90 * Total number of bytes in the file.
91 */
92 unsigned long long total;
93
94 /**
95 * Number of bytes already obtained
96 */
97 unsigned long long completed;
98
99 /**
100 * Starting-offset in file (for partial download)
101 */
102 unsigned long long offset;
103
104 /**
105 * Length of the download (starting at offset).
106 */
107 unsigned long long length;
108
109 /**
110 * Time download was started.
111 */
112 GNUNET_CronTime startTime;
113
114 /**
115 * Doubly linked list of all pending requests (head)
116 */
117 struct Node *head;
118
119 /**
120 * Doubly linked list of all pending requests (tail)
121 */
122 struct Node *tail;
123
124 /**
125 * FSLIB context for issuing requests.
126 */
127 struct GNUNET_FS_SearchContext *sctx;
128
129 /**
130 * Context for error reporting.
131 */
132 struct GNUNET_GE_Context *ectx;
133
134 /**
135 * Configuration information.
136 */
137 struct GNUNET_GC_Configuration *cfg;
138
139 /**
140 * The file handle.
141 */
142 int handle;
143
144 /**
145 * Do we exclusively own this sctx?
146 */
147 int my_sctx;
148
149 /**
150 * The base-filename
151 */
152 char *filename;
153
154 /**
155 * Main thread running the operation.
156 */
157 struct GNUNET_ThreadHandle *main;
158
159 /**
160 * Function to call when we make progress.
161 */
162 GNUNET_ECRS_DownloadProgressCallback dpcb;
163
164 /**
165 * Extra argument to dpcb.
166 */
167 void *dpcbClosure;
168
169 /**
170 * Identity of the peer having the content, or all-zeros
171 * if we don't know of such a peer.
172 */
173 GNUNET_PeerIdentity target;
174
175 /**
176 * Abort? Flag that can be set at any time
177 * to abort the RM as soon as possible. Set
178 * to GNUNET_YES during orderly shutdown,
179 * set to GNUNET_SYSERR on error.
180 */
181 int abortFlag;
182
183 /**
184 * Do we have a specific peer from which we download
185 * from?
186 */
187 int have_target;
188
189 /**
190 * Desired anonymity level for the download.
191 */
192 unsigned int anonymityLevel;
193
194 /**
195 * The depth of the file-tree.
196 */
197 unsigned int treedepth;
198
199};
200
201static int
202content_receive_callback (const GNUNET_HashCode * query,
203 const GNUNET_DatastoreValue * reply, void *cls,
204 unsigned long long uid);
205
206
207/**
208 * Close the files and free the associated resources.
209 *
210 * @param self reference to the download context
211 */
212static void
213free_request_manager (struct GNUNET_ECRS_DownloadContext *rm)
214{
215 struct Node *pos;
216
217 if (rm->abortFlag == GNUNET_NO)
218 rm->abortFlag = GNUNET_YES;
219 if (rm->my_sctx == GNUNET_YES)
220 GNUNET_FS_destroy_search_context (rm->sctx);
221 else
222 GNUNET_FS_suspend_search_context (rm->sctx);
223 while (rm->head != NULL)
224 {
225 pos = rm->head;
226 GNUNET_DLL_remove (rm->head, rm->tail, pos);
227 if (rm->my_sctx != GNUNET_YES)
228 GNUNET_FS_stop_search (rm->sctx, &content_receive_callback, pos);
229 GNUNET_free (pos);
230 }
231 if (rm->my_sctx != GNUNET_YES)
232 GNUNET_FS_resume_search_context (rm->sctx);
233 GNUNET_GE_ASSERT (NULL, rm->tail == NULL);
234 if (rm->handle >= 0)
235 CLOSE (rm->handle);
236 if (rm->main != NULL)
237 GNUNET_thread_release_self (rm->main);
238 GNUNET_free_non_null (rm->filename);
239 rm->sctx = NULL;
240 GNUNET_free (rm);
241}
242
243/**
244 * Read method.
245 *
246 * @param self reference to the download context
247 * @param level level in the tree to read/write at
248 * @param pos position where to read or write
249 * @param buf where to read from or write to
250 * @param len how many bytes to read or write
251 * @return number of bytes read, GNUNET_SYSERR on error
252 */
253static int
254read_from_files (struct GNUNET_ECRS_DownloadContext *self,
255 unsigned int level,
256 unsigned long long pos, void *buf, unsigned int len)
257{
258 if ((level > 0) || (self->handle == -1))
259 return GNUNET_SYSERR;
260 LSEEK (self->handle, pos, SEEK_SET);
261 return READ (self->handle, buf, len);
262}
263
264/**
265 * Write method.
266 *
267 * @param self reference to the download context
268 * @param level level in the tree to write to
269 * @param pos position where to write
270 * @param buf where to write to
271 * @param len how many bytes to write
272 * @return number of bytes written, GNUNET_SYSERR on error
273 */
274static int
275write_to_files (struct GNUNET_ECRS_DownloadContext *self,
276 unsigned int level,
277 unsigned long long pos, void *buf, unsigned int len)
278{
279 int ret;
280
281 if (level > 0)
282 return len; /* lie -- no more temps */
283 if (self->handle == -1)
284 return len;
285 LSEEK (self->handle, pos, SEEK_SET);
286 ret = WRITE (self->handle, buf, len);
287 if (ret != len)
288 GNUNET_GE_LOG_STRERROR_FILE (self->ectx,
289 GNUNET_GE_ERROR | GNUNET_GE_BULK |
290 GNUNET_GE_USER, "write", self->filename);
291 return ret;
292}
293
294/**
295 * Queue a request for execution.
296 *
297 * @param rm the request manager struct from createRequestManager
298 * @param node the node to call once a reply is received
299 */
300static void
301add_request (struct Node *node)
302{
303 struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
304
305 GNUNET_DLL_insert (rm->head, rm->tail, node);
306 GNUNET_FS_start_search (rm->sctx,
307 rm->have_target == GNUNET_NO ? NULL : &rm->target,
308 GNUNET_ECRS_BLOCKTYPE_DATA, 1,
309 &node->chk.query,
310 rm->anonymityLevel,
311 &content_receive_callback, node);
312}
313
314static void
315signal_abort (struct GNUNET_ECRS_DownloadContext *rm, const char *msg)
316{
317 rm->abortFlag = GNUNET_SYSERR;
318 if ((rm->head != NULL) && (rm->dpcb != NULL))
319 rm->dpcb (rm->length + 1, 0, 0, 0, msg, 0, rm->dpcbClosure);
320 GNUNET_thread_stop_sleep (rm->main);
321}
322
323/**
324 * Dequeue a request.
325 *
326 * @param self the request manager struct from createRequestManager
327 * @param node the block for which the request is canceled
328 */
329static void
330delete_node (struct Node *node)
331{
332 struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
333
334 GNUNET_DLL_remove (rm->head, rm->tail, node);
335 GNUNET_free (node);
336 if (rm->head == NULL)
337 GNUNET_thread_stop_sleep (rm->main);
338}
339
340/**
341 * Compute how many bytes of data are stored in
342 * this node.
343 */
344static unsigned int
345get_node_size (const struct Node *node)
346{
347 unsigned int i;
348 unsigned int ret;
349 unsigned long long rsize;
350 unsigned long long spos;
351 unsigned long long epos;
352
353 GNUNET_GE_ASSERT (node->ctx->ectx, node->offset < node->ctx->total);
354 if (node->level == 0)
355 {
356 ret = GNUNET_ECRS_DBLOCK_SIZE;
357 if (node->offset + (unsigned long long) ret > node->ctx->total)
358 ret = (unsigned int) (node->ctx->total - node->offset);
359#if DEBUG_DOWNLOAD
360 GNUNET_GE_LOG (node->ctx->rm->ectx,
361 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
362 "Node at offset %llu and level %d has size %u\n",
363 node->offset, node->level, ret);
364#endif
365 return ret;
366 }
367 rsize = GNUNET_ECRS_DBLOCK_SIZE;
368 for (i = 0; i < node->level - 1; i++)
369 rsize *= GNUNET_ECRS_CHK_PER_INODE;
370 spos = rsize * (node->offset / sizeof (GNUNET_EC_ContentHashKey));
371 epos = spos + rsize * GNUNET_ECRS_CHK_PER_INODE;
372 if (epos > node->ctx->total)
373 epos = node->ctx->total;
374 ret = (epos - spos) / rsize;
375 if (ret * rsize < epos - spos)
376 ret++; /* need to round up! */
377#if DEBUG_DOWNLOAD
378 GNUNET_GE_LOG (node->ctx->rm->ectx,
379 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
380 "Node at offset %llu and level %d has size %u\n",
381 node->offset, node->level,
382 ret * sizeof (GNUNET_EC_ContentHashKey));
383#endif
384 return ret * sizeof (GNUNET_EC_ContentHashKey);
385}
386
387/**
388 * Notify client about progress.
389 */
390static void
391notify_client_about_progress (const struct Node *node,
392 const char *data, unsigned int size)
393{
394 struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
395 GNUNET_CronTime eta;
396
397 if ((rm->abortFlag != GNUNET_NO) || (node->level != 0))
398 return;
399 rm->completed += size;
400 eta = GNUNET_get_time ();
401 if (rm->completed > 0)
402 eta = (GNUNET_CronTime) (rm->startTime +
403 (((double) (eta - rm->startTime) /
404 (double) rm->completed)) *
405 (double) rm->length);
406 if (rm->dpcb != NULL)
407 rm->dpcb (rm->length,
408 rm->completed, eta, node->offset, data, size, rm->dpcbClosure);
409}
410
411
412/**
413 * DOWNLOAD children of this GNUNET_EC_IBlock.
414 *
415 * @param node the node for which the children should be downloaded
416 * @param data data for the node
417 * @param size size of data
418 */
419static void iblock_download_children (const struct Node *node,
420 const char *data, unsigned int size);
421
422/**
423 * Check if self block is already present on the drive. If the block
424 * is a dblock and present, the ProgressModel is notified. If the
425 * block is present and it is an iblock, downloading the children is
426 * triggered.
427 *
428 * Also checks if the block is within the range of blocks
429 * that we are supposed to download. If not, the method
430 * returns as if the block is present but does NOT signal
431 * progress.
432 *
433 * @param node that is checked for presence
434 * @return GNUNET_YES if present, GNUNET_NO if not.
435 */
436static int
437check_node_present (const struct Node *node)
438{
439 int res;
440 int ret;
441 char *data;
442 unsigned int size;
443 GNUNET_HashCode hc;
444
445 size = get_node_size (node);
446 /* first check if node is within range.
447 For now, keeping it simple, we only do
448 this for level-0 nodes */
449 if ((node->level == 0) &&
450 ((node->offset + size < node->ctx->offset) ||
451 (node->offset >= node->ctx->offset + node->ctx->length)))
452 return GNUNET_YES;
453 data = GNUNET_malloc (size);
454 ret = GNUNET_NO;
455 res = read_from_files (node->ctx, node->level, node->offset, data, size);
456 if (res == size)
457 {
458 GNUNET_hash (data, size, &hc);
459 if (0 == memcmp (&hc, &node->chk.key, sizeof (GNUNET_HashCode)))
460 {
461 notify_client_about_progress (node, data, size);
462 if (node->level > 0)
463 iblock_download_children (node, data, size);
464 ret = GNUNET_YES;
465 }
466 }
467 GNUNET_free (data);
468 return ret;
469}
470
471/**
472 * DOWNLOAD children of this GNUNET_EC_IBlock.
473 *
474 * @param node the node that should be downloaded
475 */
476static void
477iblock_download_children (const struct Node *node,
478 const char *data, unsigned int size)
479{
480 struct GNUNET_GE_Context *ectx = node->ctx->ectx;
481 int i;
482 struct Node *child;
483 unsigned int childcount;
484 const GNUNET_EC_ContentHashKey *chks;
485 unsigned int levelSize;
486 unsigned long long baseOffset;
487
488 GNUNET_GE_ASSERT (ectx, node->level > 0);
489 childcount = size / sizeof (GNUNET_EC_ContentHashKey);
490 if (size != childcount * sizeof (GNUNET_EC_ContentHashKey))
491 {
492 GNUNET_GE_BREAK (ectx, 0);
493 return;
494 }
495 if (node->level == 1)
496 {
497 levelSize = GNUNET_ECRS_DBLOCK_SIZE;
498 baseOffset =
499 node->offset / sizeof (GNUNET_EC_ContentHashKey) *
500 GNUNET_ECRS_DBLOCK_SIZE;
501 }
502 else
503 {
504 levelSize =
505 sizeof (GNUNET_EC_ContentHashKey) * GNUNET_ECRS_CHK_PER_INODE;
506 baseOffset = node->offset * GNUNET_ECRS_CHK_PER_INODE;
507 }
508 chks = (const GNUNET_EC_ContentHashKey *) data;
509 for (i = 0; i < childcount; i++)
510 {
511 child = GNUNET_malloc (sizeof (struct Node));
512 child->ctx = node->ctx;
513 child->chk = chks[i];
514 child->offset = baseOffset + i * levelSize;
515 GNUNET_GE_ASSERT (ectx, child->offset < node->ctx->total);
516 child->level = node->level - 1;
517 GNUNET_GE_ASSERT (ectx, (child->level != 0) ||
518 ((child->offset % GNUNET_ECRS_DBLOCK_SIZE) == 0));
519 if (GNUNET_NO == check_node_present (child))
520 add_request (child);
521 else
522 GNUNET_free (child); /* done already! */
523 }
524}
525
526
527/**
528 * Decrypts a given data block
529 *
530 * @param data represents the data block
531 * @param hashcode represents the key concatenated with the initial
532 * value used in the alg
533 * @param result where to store the result (encrypted block)
534 * @returns GNUNET_OK on success, GNUNET_SYSERR on error
535 */
536static int
537decrypt_content (const char *data,
538 unsigned int size, const GNUNET_HashCode * hashcode,
539 char *result)
540{
541 GNUNET_AES_InitializationVector iv;
542 GNUNET_AES_SessionKey skey;
543
544 /* get key and init value from the GNUNET_HashCode */
545 GNUNET_hash_to_AES_key (hashcode, &skey, &iv);
546 return GNUNET_AES_decrypt (&skey, data, size, &iv, result);
547}
548
549/**
550 * We received a GNUNET_EC_ContentHashKey reply for a block. Decrypt. Note
551 * that the caller (fslib) has already aquired the
552 * RM lock (we sometimes aquire it again in callees,
553 * mostly because our callees could be also be theoretically
554 * called from elsewhere).
555 *
556 * @param cls the node for which the reply is given, freed in
557 * the function!
558 * @param query the query for which reply is the answer
559 * @param reply the reply
560 * @return GNUNET_OK if the reply was valid, GNUNET_SYSERR on error
561 */
562static int
563content_receive_callback (const GNUNET_HashCode * query,
564 const GNUNET_DatastoreValue * reply, void *cls,
565 unsigned long long uid)
566{
567 struct Node *node = cls;
568 struct GNUNET_ECRS_DownloadContext *rm = node->ctx;
569 struct GNUNET_GE_Context *ectx = rm->ectx;
570 GNUNET_HashCode hc;
571 unsigned int size;
572 char *data;
573
574 if (rm->abortFlag != GNUNET_NO)
575 return GNUNET_SYSERR;
576 GNUNET_GE_ASSERT (ectx,
577 0 == memcmp (query, &node->chk.query,
578 sizeof (GNUNET_HashCode)));
579 size = ntohl (reply->size) - sizeof (GNUNET_DatastoreValue);
580 if ((size <= sizeof (GNUNET_EC_DBlock)) ||
581 (size - sizeof (GNUNET_EC_DBlock) != get_node_size (node)))
582 {
583 GNUNET_GE_BREAK (ectx, 0);
584 return GNUNET_SYSERR; /* invalid size! */
585 }
586 size -= sizeof (GNUNET_EC_DBlock);
587 data = GNUNET_malloc (size);
588 if (GNUNET_SYSERR ==
589 decrypt_content ((const char *)
590 &((const GNUNET_EC_DBlock *) &reply[1])[1], size,
591 &node->chk.key, data))
592 GNUNET_GE_ASSERT (ectx, 0);
593 GNUNET_hash (data, size, &hc);
594 if (0 != memcmp (&hc, &node->chk.key, sizeof (GNUNET_HashCode)))
595 {
596 GNUNET_free (data);
597 GNUNET_GE_BREAK (ectx, 0);
598 signal_abort (rm,
599 _("Decrypted content does not match key. "
600 "This is either a bug or a maliciously inserted "
601 "file. Download aborted.\n"));
602 return GNUNET_SYSERR;
603 }
604 if (size != write_to_files (rm, node->level, node->offset, data, size))
605 {
606 GNUNET_GE_LOG_STRERROR (ectx,
607 GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
608 GNUNET_GE_USER | GNUNET_GE_BULK, "WRITE");
609 signal_abort (rm, _("IO error."));
610 return GNUNET_SYSERR;
611 }
612 notify_client_about_progress (node, data, size);
613 if (node->level > 0)
614 iblock_download_children (node, data, size);
615 GNUNET_free (data);
616 /* request satisfied, stop requesting! */
617 delete_node (node);
618 return GNUNET_OK;
619}
620
621
622/**
623 * Helper function to sanitize filename
624 * and create necessary directories.
625 */
626static char *
627get_real_download_filename (struct GNUNET_GE_Context *ectx,
628 const char *filename)
629{
630 struct stat buf;
631 char *realFN;
632 char *path;
633 char *pos;
634
635 if ((filename[strlen (filename) - 1] == '/') ||
636 (filename[strlen (filename) - 1] == '\\'))
637 {
638 realFN =
639 GNUNET_malloc (strlen (filename) + strlen (GNUNET_DIRECTORY_EXT));
640 strcpy (realFN, filename);
641 realFN[strlen (filename) - 1] = '\0';
642 strcat (realFN, GNUNET_DIRECTORY_EXT);
643 }
644 else
645 {
646 realFN = GNUNET_strdup (filename);
647 }
648 path = GNUNET_malloc (strlen (realFN) * strlen (GNUNET_DIRECTORY_EXT) + 1);
649 strcpy (path, realFN);
650 pos = path;
651 while (*pos != '\0')
652 {
653 if (*pos == DIR_SEPARATOR)
654 {
655 *pos = '\0';
656 if ((0 == STAT (path, &buf)) && (!S_ISDIR (buf.st_mode)))
657 {
658 *pos = DIR_SEPARATOR;
659 memmove (pos + strlen (GNUNET_DIRECTORY_EXT),
660 pos, strlen (pos));
661 memcpy (pos,
662 GNUNET_DIRECTORY_EXT, strlen (GNUNET_DIRECTORY_EXT));
663 pos += strlen (GNUNET_DIRECTORY_EXT);
664 }
665 else
666 {
667 *pos = DIR_SEPARATOR;
668 }
669 }
670 pos++;
671 }
672 GNUNET_free (realFN);
673 return path;
674}
675
676/* ***************** main method **************** */
677
678
679/**
680 * Download parts of a file. Note that this will store
681 * the blocks at the respective offset in the given file.
682 * Also, the download is still using the blocking of the
683 * underlying ECRS encoding. As a result, the download
684 * may *write* outside of the given boundaries (if offset
685 * and length do not match the 32k ECRS block boundaries).
686 * <p>
687 *
688 * This function should be used to focus a download towards a
689 * particular portion of the file (optimization), not to strictly
690 * limit the download to exactly those bytes.
691 *
692 * @param uri the URI of the file (determines what to download)
693 * @param filename where to store the file
694 * @param no_temporaries set to GNUNET_YES to disallow generation of temporary files
695 * @param start starting offset
696 * @param length length of the download (starting at offset)
697 */
698struct GNUNET_ECRS_DownloadContext *
699GNUNET_ECRS_file_download_partial_start (struct GNUNET_GE_Context *ectx,
700 struct GNUNET_GC_Configuration *cfg,
701 struct GNUNET_FS_SearchContext *sc,
702 const struct GNUNET_ECRS_URI *uri,
703 const char *filename,
704 unsigned long long offset,
705 unsigned long long length,
706 unsigned int anonymityLevel,
707 int no_temporaries,
708 GNUNET_ECRS_DownloadProgressCallback
709 dpcb, void *dpcbClosure)
710{
711 struct GNUNET_ECRS_DownloadContext *rm;
712 struct stat buf;
713 struct Node *top;
714 int ret;
715
716 if ((!GNUNET_ECRS_uri_test_chk (uri)) && (!GNUNET_ECRS_uri_test_loc (uri)))
717 {
718 GNUNET_GE_BREAK (ectx, 0);
719 return NULL;
720 }
721 rm = GNUNET_malloc (sizeof (struct GNUNET_ECRS_DownloadContext));
722 memset (rm, 0, sizeof (struct GNUNET_ECRS_DownloadContext));
723 if (sc == NULL)
724 {
725 rm->sctx = GNUNET_FS_create_search_context (ectx, cfg);
726 if (rm->sctx == NULL)
727 {
728 GNUNET_free (rm);
729 return NULL;
730 }
731 rm->my_sctx = GNUNET_YES;
732 }
733 else
734 {
735 rm->sctx = sc;
736 rm->my_sctx = GNUNET_NO;
737 }
738 rm->ectx = ectx;
739 rm->cfg = cfg;
740 rm->startTime = GNUNET_get_time ();
741 rm->anonymityLevel = anonymityLevel;
742 rm->offset = offset;
743 rm->length = length;
744 rm->dpcb = dpcb;
745 rm->dpcbClosure = dpcbClosure;
746 rm->main = GNUNET_thread_get_self ();
747 rm->total = GNUNET_ntohll (uri->data.fi.file_length);
748 rm->filename =
749 filename != NULL ? get_real_download_filename (ectx, filename) : NULL;
750
751 if ((rm->filename != NULL) &&
752 (GNUNET_SYSERR ==
753 GNUNET_disk_directory_create_for_file (ectx, rm->filename)))
754 {
755 free_request_manager (rm);
756 return NULL;
757 }
758 if (0 == rm->total)
759 {
760 if (rm->filename != NULL)
761 {
762 ret = GNUNET_disk_file_open (ectx,
763 rm->filename,
764 O_CREAT | O_WRONLY | O_TRUNC,
765 S_IRUSR | S_IWUSR);
766 if (ret == -1)
767 {
768 free_request_manager (rm);
769 return NULL;
770 }
771 CLOSE (ret);
772 }
773 dpcb (0, 0, rm->startTime, 0, NULL, 0, dpcbClosure);
774 free_request_manager (rm);
775 return NULL;
776 }
777 rm->treedepth = GNUNET_ECRS_compute_depth (rm->total);
778 if ((NULL != rm->filename) &&
779 ((0 == STAT (rm->filename, &buf))
780 && ((size_t) buf.st_size > rm->total)))
781 {
782 /* if exists and oversized, truncate */
783 if (truncate (rm->filename, rm->total) != 0)
784 {
785 GNUNET_GE_LOG_STRERROR_FILE (ectx,
786 GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
787 GNUNET_GE_BULK, "truncate",
788 rm->filename);
789 free_request_manager (rm);
790 return NULL;
791 }
792 }
793 if (rm->filename != NULL)
794 {
795 rm->handle = GNUNET_disk_file_open (ectx,
796 rm->filename,
797 O_CREAT | O_RDWR,
798 S_IRUSR | S_IWUSR);
799 if (rm->handle < 0)
800 {
801 free_request_manager (rm);
802 return NULL;
803 }
804 }
805 else
806 rm->handle = -1;
807 if (GNUNET_ECRS_uri_test_loc (uri))
808 {
809 GNUNET_hash (&uri->data.loc.peer, sizeof (GNUNET_RSA_PublicKey),
810 &rm->target.hashPubKey);
811 rm->have_target = GNUNET_YES;
812 }
813 top = GNUNET_malloc (sizeof (struct Node));
814 memset (top, 0, sizeof (struct Node));
815 top->ctx = rm;
816 top->chk = uri->data.fi.chk;
817 top->offset = 0;
818 top->level = rm->treedepth;
819 if (GNUNET_NO == check_node_present (top))
820 add_request (top);
821 else
822 GNUNET_free (top);
823 return rm;
824}
825
826int
827GNUNET_ECRS_file_download_partial_stop (struct GNUNET_ECRS_DownloadContext
828 *rm)
829{
830 int ret;
831
832 ret = rm->abortFlag;
833 free_request_manager (rm);
834 if (ret == GNUNET_NO)
835 ret = GNUNET_OK; /* normal termination */
836 return ret;
837}
838
839/**
840 * Download parts of a file. Note that this will store
841 * the blocks at the respective offset in the given file.
842 * Also, the download is still using the blocking of the
843 * underlying ECRS encoding. As a result, the download
844 * may *write* outside of the given boundaries (if offset
845 * and length do not match the 32k ECRS block boundaries).
846 * <p>
847 *
848 * This function should be used to focus a download towards a
849 * particular portion of the file (optimization), not to strictly
850 * limit the download to exactly those bytes.
851 *
852 * @param uri the URI of the file (determines what to download)
853 * @param filename where to store the file
854 * @param no_temporaries set to GNUNET_YES to disallow generation of temporary files
855 * @param start starting offset
856 * @param length length of the download (starting at offset)
857 */
858int
859GNUNET_ECRS_file_download_partial (struct GNUNET_GE_Context *ectx,
860 struct GNUNET_GC_Configuration *cfg,
861 const struct GNUNET_ECRS_URI *uri,
862 const char *filename,
863 unsigned long long offset,
864 unsigned long long length,
865 unsigned int anonymityLevel,
866 int no_temporaries,
867 GNUNET_ECRS_DownloadProgressCallback dpcb,
868 void *dpcbClosure,
869 GNUNET_ECRS_TestTerminate tt,
870 void *ttClosure)
871{
872 struct GNUNET_ECRS_DownloadContext *rm;
873 int ret;
874
875 if (length == 0)
876 return GNUNET_OK;
877 rm = GNUNET_ECRS_file_download_partial_start (ectx,
878 cfg,
879 NULL,
880 uri,
881 filename,
882 offset,
883 length,
884 anonymityLevel,
885 no_temporaries,
886 dpcb, dpcbClosure);
887 if (rm == NULL)
888 return GNUNET_SYSERR;
889 while ((GNUNET_OK == tt (ttClosure)) &&
890 (GNUNET_YES != GNUNET_shutdown_test ()) &&
891 (rm->abortFlag == GNUNET_NO) && (rm->head != NULL))
892 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
893 ret = GNUNET_ECRS_file_download_partial_stop (rm);
894 return ret;
895}
896
897/**
898 * Download a file (simplified API).
899 *
900 * @param uri the URI of the file (determines what to download)
901 * @param filename where to store the file
902 */
903int
904GNUNET_ECRS_file_download (struct GNUNET_GE_Context *ectx,
905 struct GNUNET_GC_Configuration *cfg,
906 const struct GNUNET_ECRS_URI *uri,
907 const char *filename,
908 unsigned int anonymityLevel,
909 GNUNET_ECRS_DownloadProgressCallback dpcb,
910 void *dpcbClosure, GNUNET_ECRS_TestTerminate tt,
911 void *ttClosure)
912{
913 return GNUNET_ECRS_file_download_partial (ectx,
914 cfg,
915 uri,
916 filename,
917 0,
918 GNUNET_ECRS_uri_get_file_size
919 (uri), anonymityLevel, GNUNET_NO,
920 dpcb, dpcbClosure, tt, ttClosure);
921}
922
923/* end of download.c */
diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c
new file mode 100644
index 000000000..d565f4397
--- /dev/null
+++ b/src/fs/fs_file_information.c
@@ -0,0 +1,269 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
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#include "gnunet_fs_service.h"
28#include "fs.h"
29
30
31/**
32 * Create an entry for a file in a publish-structure.
33 *
34 * @param filename name of the file or directory to publish
35 * @param meta metadata for the file
36 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
37 * GNUNET_SYSERR for simulation
38 * @param anonymity what is the desired anonymity level for sharing?
39 * @param priority what is the priority for OUR node to
40 * keep this file available? Use 0 for maximum anonymity and
41 * minimum reliability...
42 * @param expirationTime when should this content expire?
43 * @return publish structure entry for the file
44 */
45struct GNUNET_FS_FileInformation *
46GNUNET_FS_file_information_create_from_file (void *client_info,
47 const char *filename,
48 const struct GNUNET_CONTAINER_MetaData *meta,
49 int do_index,
50 unsigned int anonymity,
51 unsigned int priority,
52 struct GNUNET_TIME_Absolute expirationTime)
53{
54 return NULL;
55}
56
57/**
58 * Create an entry for a file in a publish-structure.
59 *
60 * @param length length of the file
61 * @param data data for the file (should not be used afterwards by
62 * the caller; caller will "free")
63 * @param meta metadata for the file
64 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
65 * GNUNET_SYSERR for simulation
66 * @param anonymity what is the desired anonymity level for sharing?
67 * @param priority what is the priority for OUR node to
68 * keep this file available? Use 0 for maximum anonymity and
69 * minimum reliability...
70 * @param expirationTime when should this content expire?
71 * @return publish structure entry for the file
72 */
73struct GNUNET_FS_FileInformation *
74GNUNET_FS_file_information_create_from_data (void *client_info,
75 uint64_t length,
76 void *data,
77 const struct GNUNET_CONTAINER_MetaData *meta,
78 int do_index,
79 unsigned int anonymity,
80 unsigned int priority,
81 struct GNUNET_TIME_Absolute expirationTime)
82{
83 return NULL;
84}
85
86
87/**
88 * Create an entry for a file in a publish-structure.
89 *
90 * @param length length of the file
91 * @param reader function that can be used to obtain the data for the file
92 * @param reader_cls closure for "reader"
93 * @param keywords under which keywords should this file be available
94 * directly; can be NULL
95 * @param meta metadata for the file
96 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
97 * GNUNET_SYSERR for simulation
98 * @param anonymity what is the desired anonymity level for sharing?
99 * @param priority what is the priority for OUR node to
100 * keep this file available? Use 0 for maximum anonymity and
101 * minimum reliability...
102 * @param expirationTime when should this content expire?
103 * @return publish structure entry for the file
104 */
105struct GNUNET_FS_FileInformation *
106GNUNET_FS_file_information_create_from_reader (void *client_info,
107 uint64_t length,
108 GNUNET_FS_DataReader reader,
109 void *reader_cls,
110 const struct GNUNET_FS_Uri *keywords,
111 const struct GNUNET_CONTAINER_MetaData *meta,
112 int do_index,
113 unsigned int anonymity,
114 unsigned int priority,
115 struct GNUNET_TIME_Absolute expirationTime)
116{
117 return NULL;
118}
119
120
121
122/**
123 * Simple, useful default implementation of a directory scanner
124 * (GNUNET_FS_DirectoryScanner). This implementation expects to get a
125 * UNIX filename, will publish all files in the directory except hidden
126 * files (those starting with a "."). Metadata will be extracted
127 * using GNU libextractor; the specific list of plugins should be
128 * specified in "cls", passing NULL will disable (!) metadata
129 * extraction. Keywords will be derived from the metadata and be
130 * subject to default canonicalization. This is strictly a
131 * convenience function.
132 *
133 * @param cls must be of type "struct EXTRACTOR_Extractor*"
134 * @param dirname name of the directory to scan
135 * @param proc function called on each entry
136 * @param proc_cls closure for proc
137 * @param emsg where to store an error message (on errors)
138 * @return GNUNET_OK on success
139 */
140int
141GNUNET_FS_directory_scanner_default (void *cls,
142 const char *dirname,
143 GNUNET_FS_FileProcessor proc,
144 void *proc_cls)
145{
146 return GNUNET_SYSERR;
147}
148
149
150/**
151 * Create a publish-structure from an existing file hierarchy, inferring
152 * and organizing keywords and metadata as much as possible. This
153 * function primarily performs the recursive build and re-organizes
154 * keywords and metadata; for automatically getting metadata
155 * extraction, scanning of directories and creation of the respective
156 * GNUNET_FS_FileInformation entries the default scanner should be
157 * passed (GNUNET_FS_directory_scanner_default). This is strictly a
158 * convenience function.
159 *
160 * @param filename name of the top-level file or directory
161 * @param scanner function used to get a list of files in a directory
162 * @param scanner_cls closure for scanner
163 * @param anonymity what is the desired anonymity level for sharing?
164 * @param priority what is the priority for OUR node to
165 * keep this file available? Use 0 for maximum anonymity and
166 * minimum reliability...
167 * @param expirationTime when should this content expire?
168 * @return publish structure entry for the directory, NULL on error
169 */
170struct GNUNET_FS_FileInformation *
171GNUNET_FS_file_information_create_from_directory (void *client_info,
172 GNUNET_FS_DirectoryScanner scanner,
173 void *scanner_cls,
174 unsigned int anonymity,
175 unsigned int priority,
176 struct GNUNET_TIME_Absolute expirationTime)
177{
178 return NULL;
179}
180
181
182/**
183 * Create an entry for an empty directory in a publish-structure.
184 * This function should be used by applications for which the
185 * use of "GNUNET_FS_file_information_create_from_directory"
186 * is not appropriate.
187 *
188 * @param meta metadata for the directory
189 * @param keywords under which keywords should this directory be available
190 * directly; can be NULL
191 * @param anonymity what is the desired anonymity level for sharing?
192 * @param priority what is the priority for OUR node to
193 * keep this file available? Use 0 for maximum anonymity and
194 * minimum reliability...
195 * @param expirationTime when should this content expire?
196 * @return publish structure entry for the directory , NULL on error
197 */
198struct GNUNET_FS_FileInformation *
199GNUNET_FS_file_information_create_empty_directory (void *client_info,
200 const struct GNUNET_CONTAINER_MetaData *meta,
201 const struct GNUNET_FS_Uri *keywords,
202 unsigned int anonymity,
203 unsigned int priority,
204 struct GNUNET_TIME_Absolute expirationTime)
205{
206 return NULL;
207}
208
209
210/**
211 * Add an entry to a directory in a publish-structure. Clients
212 * should never modify publish structures that were passed to
213 * "GNUNET_FS_publish_start" already.
214 *
215 * @param dir the directory
216 * @param end the entry to add; the entry must not have been
217 * added to any other directory at this point and
218 * must not include "dir" in its structure
219 * @return GNUNET_OK on success, GNUNET_SYSERR on error
220 */
221int
222GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir,
223 struct GNUNET_FS_FileInformation *end)
224{
225 return GNUNET_SYSERR;
226}
227
228
229/**
230 * Inspect a file or directory in a publish-structure. Clients
231 * should never modify publish structures that were passed to
232 * "GNUNET_FS_publish_start" already. When called on a directory,
233 * this function will FIRST call "proc" with information about
234 * the directory itself and then for each of the files in the
235 * directory (but not for files in subdirectories). When called
236 * on a file, "proc" will be called exactly once (with information
237 * about the specific file).
238 *
239 * @param dir the directory
240 * @param proc function to call on each entry
241 * @param proc_cls closure for proc
242 */
243void
244GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir,
245 GNUNET_FS_FileInformationProcessor proc,
246 void *proc_cls)
247{
248}
249
250
251/**
252 * Destroy publish-structure. Clients should never destroy publish
253 * structures that were passed to "GNUNET_FS_publish_start" already.
254 *
255 * @param fi structure to destroy
256 * @param cleaner function to call on each entry in the structure
257 * (useful to clean up client_info); can be NULL; return
258 * values are ignored
259 * @param cleaner_cls closure for cleaner
260 */
261void
262GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi,
263 GNUNET_FS_FileInformationProcessor cleaner,
264 void *cleaner_cls)
265{
266}
267
268
269/* end of fs_file_information.c */
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c
new file mode 100644
index 000000000..fb45d99e9
--- /dev/null
+++ b/src/fs/fs_namespace.c
@@ -0,0 +1,729 @@
1/*
2 This file is part of GNUnet
3 (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/fs_namespace.c
23 * @brief create and destroy namespaces
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_fs_service.h"
28
29
30/**
31 * Publish an advertismement for a namespace.
32 *
33 * @param h handle to the file sharing subsystem
34 * @param namespace handle for the namespace that should be advertised
35 * @param meta meta-data for the namespace advertisement
36 * @param anonymity for the namespace advertismement
37 * @param priority for the namespace advertisement
38 * @param expiration for the namespace advertisement
39 * @param advertisementURI the keyword (!) URI to advertise the
40 * namespace under (we will create a GNUNET_EC_KNBlock)
41 * @param rootEntry name of the root entry in the namespace (for
42 * the namespace advertisement)
43 *
44 * @return uri of the advertisement
45 */
46struct GNUNET_FS_Uri *
47GNUNET_FS_namespace_advertise (struct GNUNET_FS_Handle *h,
48 struct GNUNET_FS_Namespace *namespace,
49 const struct GNUNET_MetaData *meta,
50 unsigned int anonymity,
51 unsigned int priority,
52 struct GNUNET_TIME_Absolute expiration,
53 const struct GNUNET_FS_Uri *advertisementURI,
54 const char *rootEntry)
55{
56 return NULL;
57}
58
59
60/**
61 * Create a namespace with the given name; if one already
62 * exists, return a handle to the existing namespace.
63 *
64 * @param h handle to the file sharing subsystem
65 * @param name name to use for the namespace
66 * @return handle to the namespace, NULL on error
67 */
68struct GNUNET_FS_Namespace *
69GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h,
70 const char *name)
71{
72 return NULL;
73}
74
75
76/**
77 * Delete a namespace handle. Can be used for a clean shutdown (free
78 * memory) or also to freeze the namespace to prevent further
79 * insertions by anyone.
80 *
81 * @param namespace handle to the namespace that should be deleted / freed
82 * @param freeze prevents future insertions; creating a namespace
83 * with the same name again will create a fresh namespace instead
84 *
85 * @return GNUNET_OK on success, GNUNET_SYSERR on error
86 */
87int
88GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *namespace,
89 int freeze)
90{
91 return GNUNET_SYSERR;
92}
93
94
95/**
96 * Build a list of all available local (!) namespaces The returned
97 * names are only the nicknames since we only iterate over the local
98 * namespaces.
99 *
100 * @param h handle to the file sharing subsystem
101 * @param cb function to call on each known namespace
102 * @param cb_cls closure for cb
103 */
104void
105GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
106 GNUNET_FS_NamespaceInfoProcessor cb,
107 void *cb_cls)
108{
109}
110
111/* end of fs_namespace.c */
112
113#if 0
114/*
115 This file is part of GNUnet
116 (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
117
118 GNUnet is free software; you can redistribute it and/or modify
119 it under the terms of the GNU General Public License as published
120 by the Free Software Foundation; either version 2, or (at your
121 option) any later version.
122
123 GNUnet is distributed in the hope that it will be useful, but
124 WITHOUT ANY WARRANTY; without even the implied warranty of
125 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
126 General Public License for more details.
127
128 You should have received a copy of the GNU General Public License
129 along with GNUnet; see the file COPYING. If not, write to the
130 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
131 Boston, MA 02111-1307, USA.
132*/
133
134/**
135 * @file applications/fs/ecrs/namespace.c
136 * @brief creation, deletion and advertising of namespaces
137 * @author Christian Grothoff
138 */
139
140#include "platform.h"
141#include "gnunet_directories.h"
142#include "gnunet_protocols.h"
143#include "gnunet_ecrs_lib.h"
144#include "gnunet_fs_lib.h"
145#include "ecrs_core.h"
146#include "ecrs.h"
147
148#define PSEUDODIR "data/namespace/keys/"
149#define INITVALUE "GNUnet!!"
150#define MAX_SBLOCK_SIZE 32000
151
152static char *
153getPseudonymFileName (struct GNUNET_GE_Context *ectx,
154 struct GNUNET_GC_Configuration *cfg,
155 const GNUNET_HashCode * pid)
156{
157 char *gnHome;
158 char *fileName;
159 GNUNET_EncName enc;
160
161 GNUNET_GC_get_configuration_value_filename (cfg,
162 "GNUNET",
163 "GNUNET_HOME",
164 GNUNET_DEFAULT_HOME_DIRECTORY,
165 &fileName);
166 gnHome = GNUNET_expand_file_name (ectx, fileName);
167 GNUNET_free (fileName);
168 fileName =
169 GNUNET_malloc (strlen (gnHome) + strlen (PSEUDODIR) +
170 sizeof (GNUNET_EncName) + 2);
171 strcpy (fileName, gnHome);
172 GNUNET_free (gnHome);
173 strcat (fileName, DIR_SEPARATOR_STR);
174 strcat (fileName, PSEUDODIR);
175 GNUNET_disk_directory_create (ectx, fileName);
176 if (pid != NULL)
177 {
178 GNUNET_hash_to_enc (pid, &enc);
179 strcat (fileName, (char *) &enc);
180 }
181 return fileName;
182}
183
184
185/**
186 * Check if the given namespace exists (locally).
187 *
188 * @return GNUNET_OK if the namespace exists, GNUNET_SYSERR if not
189 */
190int
191GNUNET_ECRS_namespace_test_exists (struct GNUNET_GE_Context *ectx,
192 struct GNUNET_GC_Configuration *cfg,
193 const GNUNET_HashCode * pid)
194{
195 char *fileName;
196 int ret;
197
198 fileName = getPseudonymFileName (ectx, cfg, pid);
199 ret = GNUNET_disk_file_test (ectx, fileName);
200 GNUNET_free (fileName);
201 return ret;
202}
203
204/**
205 * Delete a local namespace.
206 *
207 * @return GNUNET_OK on success, GNUNET_SYSERR on error
208 */
209int
210GNUNET_ECRS_namespace_delete (struct GNUNET_GE_Context *ectx,
211 struct GNUNET_GC_Configuration *cfg,
212 const GNUNET_HashCode * pid)
213{
214 char *fileName;
215
216 fileName = getPseudonymFileName (ectx, cfg, pid);
217 if (GNUNET_YES != GNUNET_disk_file_test (ectx, fileName))
218 {
219 GNUNET_free (fileName);
220 return GNUNET_SYSERR; /* no such namespace */
221 }
222 if (0 != UNLINK (fileName))
223 {
224 GNUNET_GE_LOG_STRERROR_FILE (ectx,
225 GNUNET_GE_WARNING | GNUNET_GE_USER |
226 GNUNET_GE_BULK, "unlink", fileName);
227 GNUNET_free (fileName);
228 return GNUNET_SYSERR;
229 }
230 GNUNET_free (fileName);
231 return GNUNET_OK;
232}
233
234/**
235 * Write the private key of the namespace to a file.
236 */
237static int
238write_namespace_key (struct GNUNET_GC_Configuration *cfg,
239 const struct GNUNET_RSA_PrivateKey *key)
240{
241 GNUNET_RSA_PrivateKeyEncoded *namespace_priv_key_encoded;
242 char *fileName;
243 GNUNET_RSA_PublicKey pubk;
244 GNUNET_HashCode pid;
245
246 GNUNET_RSA_get_public_key (key, &pubk);
247 GNUNET_hash (&pubk, sizeof (GNUNET_RSA_PublicKey), &pid);
248 fileName = getPseudonymFileName (NULL, cfg, &pid);
249 if (GNUNET_YES == GNUNET_disk_file_test (NULL, fileName))
250 {
251 GNUNET_GE_BREAK (NULL, 0); /* hash collision!? */
252 GNUNET_free (fileName);
253 return GNUNET_SYSERR;
254 }
255 namespace_priv_key_encoded = GNUNET_RSA_encode_key (key);
256 GNUNET_disk_file_write (NULL, fileName,
257 (const char *) namespace_priv_key_encoded,
258 ntohs (namespace_priv_key_encoded->len), "600");
259 GNUNET_free (fileName);
260 GNUNET_free (namespace_priv_key_encoded);
261 return GNUNET_OK;
262}
263
264/**
265 * Create a new namespace (and publish an advertismement).
266 * This publishes both an GNUNET_EC_NBlock in the namespace itself
267 * as well as KNBlocks under all keywords specified in
268 * the advertisementURI.
269 *
270 * @param anonymity_level for the namespace advertismement
271 * @param priority for the namespace advertisement
272 * @param expiration for the namespace advertisement
273 * @param advertisementURI the keyword (!) URI to advertise the
274 * namespace under (GNUNET_EC_KNBlock)
275 * @param meta meta-data for the namespace advertisement
276 * (will be used to derive a name)
277 * @param rootEntry name of the root entry in the namespace (for
278 * the namespace advertisement)
279 * @param rootURI set to the URI of the namespace, NULL if
280 * no advertisement was created
281 *
282 * @return URI on success, NULL on error
283 */
284struct GNUNET_ECRS_URI *
285GNUNET_ECRS_namespace_create (struct GNUNET_GE_Context *ectx,
286 struct GNUNET_GC_Configuration *cfg,
287 const struct GNUNET_MetaData *meta,
288 unsigned int anonymityLevel,
289 unsigned int priority,
290 GNUNET_CronTime expiration,
291 const struct GNUNET_ECRS_URI *advertisementURI,
292 const char *rootEntry)
293{
294 struct GNUNET_ECRS_URI *rootURI;
295 struct GNUNET_RSA_PrivateKey *namespace_priv_key;
296 GNUNET_HashCode hc;
297 struct GNUNET_ClientServerConnection *sock;
298 GNUNET_DatastoreValue *value;
299 GNUNET_DatastoreValue *knvalue;
300 unsigned int size;
301 unsigned int mdsize;
302 struct GNUNET_RSA_PrivateKey *pk;
303 GNUNET_EC_SBlock *sb;
304 GNUNET_EC_KSBlock *ksb;
305 char **keywords;
306 const char *keyword;
307 unsigned int keywordCount;
308 int i;
309 char *cpy;
310 char *rtgt;
311
312 if ((advertisementURI != NULL)
313 && (!GNUNET_ECRS_uri_test_ksk (advertisementURI)))
314 {
315 GNUNET_GE_BREAK (ectx, 0);
316 return NULL;
317 }
318 namespace_priv_key = GNUNET_RSA_create_key ();
319 if (GNUNET_OK != write_namespace_key (cfg, namespace_priv_key))
320 {
321 GNUNET_RSA_free_key (namespace_priv_key);
322 return NULL;
323 }
324
325 /* create advertisements */
326 mdsize = GNUNET_meta_data_get_serialized_size (meta, GNUNET_SERIALIZE_PART);
327 size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
328 if (size > MAX_SBLOCK_SIZE)
329 {
330 size = MAX_SBLOCK_SIZE;
331 mdsize = size - sizeof (GNUNET_EC_SBlock) - strlen (rootEntry) - 2;
332 }
333 value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
334 memset (value, 0, sizeof (GNUNET_DatastoreValue) + size);
335 sb = (GNUNET_EC_SBlock *) & value[1];
336 sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
337 GNUNET_RSA_get_public_key (namespace_priv_key, &sb->subspace);
338 rtgt = (char *) &sb[1];
339 memcpy (rtgt, rootEntry, strlen (rootEntry) + 1);
340 mdsize = GNUNET_meta_data_serialize (ectx,
341 meta,
342 &rtgt[strlen (rootEntry) + 2],
343 mdsize, GNUNET_SERIALIZE_PART);
344 if (mdsize == -1)
345 {
346 GNUNET_GE_BREAK (ectx, 0);
347 GNUNET_RSA_free_key (namespace_priv_key);
348 GNUNET_free (value);
349 return NULL;
350 }
351 size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (rootEntry) + 2;
352 GNUNET_GE_ASSERT (ectx,
353 GNUNET_OK == GNUNET_RSA_sign (namespace_priv_key,
354 size
355 -
356 sizeof
357 (GNUNET_RSA_Signature) -
358 sizeof
359 (GNUNET_RSA_PublicKey) -
360 sizeof (unsigned int),
361 &sb->identifier,
362 &sb->signature));
363 value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
364 value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
365 value->priority = htonl (priority);
366 value->anonymity_level = htonl (anonymityLevel);
367 value->expiration_time = GNUNET_htonll (expiration);
368 sock = GNUNET_client_connection_create (ectx, cfg);
369 if (sock == NULL)
370 {
371 GNUNET_free (value);
372 GNUNET_RSA_free_key (namespace_priv_key);
373 return NULL;
374 }
375 if (GNUNET_OK != GNUNET_FS_insert (sock, value))
376 {
377 GNUNET_free (value);
378 GNUNET_client_connection_destroy (sock);
379 GNUNET_RSA_free_key (namespace_priv_key);
380 return NULL;
381 }
382
383
384 /* publish KNBlocks */
385 size += sizeof (GNUNET_EC_KSBlock) - sizeof (GNUNET_EC_SBlock);
386 knvalue = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
387 *knvalue = *value;
388 knvalue->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
389 knvalue->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
390 ksb = (GNUNET_EC_KSBlock *) & knvalue[1];
391 ksb->type = htonl (GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED);
392 memcpy (&ksb->sblock,
393 sb, sizeof (GNUNET_EC_SBlock) + mdsize + strlen (rootEntry) + 2);
394
395 if (advertisementURI != NULL)
396 {
397 keywords = advertisementURI->data.ksk.keywords;
398 keywordCount = advertisementURI->data.ksk.keywordCount;
399 cpy =
400 GNUNET_malloc (size - sizeof (GNUNET_EC_KBlock) -
401 sizeof (unsigned int));
402 memcpy (cpy,
403 &ksb->sblock,
404 size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
405 for (i = 0; i < keywordCount; i++)
406 {
407 keyword = keywords[i];
408 /* first character of keyword indicates
409 mandatory or not -- ignore for hashing! */
410 GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc);
411 pk = GNUNET_RSA_create_key_from_hash (&hc);
412 GNUNET_RSA_get_public_key (pk, &ksb->kblock.keyspace);
413 GNUNET_GE_ASSERT (ectx,
414 size - sizeof (GNUNET_EC_KBlock) -
415 sizeof (unsigned int) ==
416 sizeof (GNUNET_EC_SBlock) + mdsize +
417 strlen (rootEntry) + 2);
418 GNUNET_ECRS_encryptInPlace (&hc, &ksb->sblock,
419 size - sizeof (GNUNET_EC_KBlock) -
420 sizeof (unsigned int));
421
422 GNUNET_GE_ASSERT (ectx,
423 GNUNET_OK == GNUNET_RSA_sign (pk,
424 size -
425 sizeof
426 (GNUNET_EC_KBlock) -
427 sizeof (unsigned
428 int),
429 &ksb->sblock,
430 &ksb->
431 kblock.signature));
432 /* extra check: verify sig */
433 GNUNET_RSA_free_key (pk);
434 if (GNUNET_OK != GNUNET_FS_insert (sock, knvalue))
435 {
436 GNUNET_GE_BREAK (ectx, 0);
437 GNUNET_free (cpy);
438 GNUNET_free (knvalue);
439 GNUNET_free (value);
440 GNUNET_client_connection_destroy (sock);
441 GNUNET_RSA_free_key (namespace_priv_key);
442 return NULL;
443 }
444 /* restore nblock to avoid re-encryption! */
445 memcpy (&ksb->sblock,
446 cpy,
447 size - sizeof (GNUNET_EC_KBlock) - sizeof (unsigned int));
448 }
449 GNUNET_free (cpy);
450 }
451 rootURI = GNUNET_malloc (sizeof (URI));
452 rootURI->type = sks;
453 GNUNET_hash (&sb->subspace,
454 sizeof (GNUNET_RSA_PublicKey), &rootURI->data.sks.namespace);
455 rootURI->data.sks.identifier = GNUNET_strdup (rootEntry);
456 GNUNET_free (knvalue);
457 GNUNET_free (value);
458 GNUNET_client_connection_destroy (sock);
459 GNUNET_RSA_free_key (namespace_priv_key);
460
461 return rootURI;
462}
463
464static struct GNUNET_RSA_PrivateKey *
465read_namespace_key (struct GNUNET_GC_Configuration *cfg,
466 const GNUNET_HashCode * pid)
467{
468 char *fileName;
469 GNUNET_RSA_PrivateKeyEncoded *hke;
470 struct GNUNET_RSA_PrivateKey *hk;
471 char *dst;
472 unsigned long long len;
473
474 fileName = getPseudonymFileName (NULL, cfg, pid);
475 if (GNUNET_OK != GNUNET_disk_file_size (NULL, fileName, &len, GNUNET_YES))
476 {
477 GNUNET_free (fileName);
478 return NULL;
479 }
480 if (len < 2)
481 {
482 GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
483 _("File `%s' does not contain a pseudonym.\n"),
484 fileName);
485 GNUNET_free (fileName);
486 return NULL;
487 }
488 dst = GNUNET_malloc (len);
489 len = GNUNET_disk_file_read (NULL, fileName, len, dst);
490 hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
491 if (ntohs (hke->len) != len)
492 {
493 GNUNET_GE_LOG (NULL, GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
494 _("Format of pseudonym `%s' is invalid.\n"), fileName);
495 GNUNET_free (fileName);
496 GNUNET_free (hke);
497 return NULL;
498 }
499 GNUNET_free (fileName);
500 hk = GNUNET_RSA_decode_key (hke);
501 GNUNET_free (hke);
502 return hk;
503}
504
505
506/**
507 * Add an entry into a namespace.
508 *
509 * @param dstU to which URI should the namespace entry refer?
510 * @param md what meta-data should be associated with the
511 * entry?
512 * @param thisId name of this entry in the namespace (keyword/identifier)
513 * @param nextId name of the update for this entry (to be published in
514 * the future; maybe NULL)
515 * @param pid unique identifier of the namespace/pseudonym
516 * @return URI on success, NULL on error
517 */
518struct GNUNET_ECRS_URI *
519GNUNET_ECRS_namespace_add_content (struct GNUNET_GE_Context *ectx,
520 struct GNUNET_GC_Configuration *cfg,
521 const GNUNET_HashCode * pid,
522 unsigned int anonymityLevel,
523 unsigned int priority,
524 GNUNET_CronTime expiration,
525 const char *thisId,
526 const char *nextId,
527 const struct GNUNET_ECRS_URI *dstU,
528 const struct GNUNET_MetaData *md)
529{
530 struct GNUNET_ECRS_URI *uri;
531 struct GNUNET_ClientServerConnection *sock;
532 GNUNET_DatastoreValue *value;
533 unsigned int size;
534 unsigned int mdsize;
535 struct GNUNET_RSA_PrivateKey *hk;
536 GNUNET_EC_SBlock *sb;
537 char *dstURI;
538 char *destPos;
539 GNUNET_HashCode hc; /* hash of thisId = key */
540 GNUNET_HashCode hc2; /* hash of hc = identifier */
541 int ret;
542 unsigned int nidlen;
543
544 hk = read_namespace_key (cfg, pid);
545 if (hk == NULL)
546 return NULL;
547
548 /* THEN: construct GNUNET_EC_SBlock */
549 dstURI = GNUNET_ECRS_uri_to_string (dstU);
550 mdsize = GNUNET_meta_data_get_serialized_size (md, GNUNET_SERIALIZE_PART);
551 if (nextId == NULL)
552 nextId = "";
553 nidlen = strlen (nextId) + 1;
554 size = mdsize + sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen;
555 if (size > MAX_SBLOCK_SIZE)
556 {
557 size = MAX_SBLOCK_SIZE;
558 mdsize =
559 size - (sizeof (GNUNET_EC_SBlock) + strlen (dstURI) + 1 + nidlen);
560 }
561 value = GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + size);
562 sb = (GNUNET_EC_SBlock *) & value[1];
563 sb->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
564 destPos = (char *) &sb[1];
565 memcpy (destPos, nextId, nidlen);
566 destPos += nidlen;
567 memcpy (destPos, dstURI, strlen (dstURI) + 1);
568 destPos += strlen (dstURI) + 1;
569 mdsize = GNUNET_meta_data_serialize (ectx,
570 md,
571 destPos,
572 mdsize, GNUNET_SERIALIZE_PART);
573 if (mdsize == -1)
574 {
575 GNUNET_GE_BREAK (ectx, 0);
576 GNUNET_free (dstURI);
577 GNUNET_RSA_free_key (hk);
578 GNUNET_free (value);
579 return NULL;
580 }
581 size = sizeof (GNUNET_EC_SBlock) + mdsize + strlen (dstURI) + 1 + nidlen;
582 value->size = htonl (sizeof (GNUNET_DatastoreValue) + size);
583 value->type = htonl (GNUNET_ECRS_BLOCKTYPE_SIGNED);
584 value->priority = htonl (priority);
585 value->anonymity_level = htonl (anonymityLevel);
586 value->expiration_time = GNUNET_htonll (expiration);
587 GNUNET_hash (thisId, strlen (thisId), &hc);
588 GNUNET_hash (&hc, sizeof (GNUNET_HashCode), &hc2);
589 uri = GNUNET_malloc (sizeof (URI));
590 uri->type = sks;
591 GNUNET_RSA_get_public_key (hk, &sb->subspace);
592 GNUNET_hash (&sb->subspace,
593 sizeof (GNUNET_RSA_PublicKey), &uri->data.sks.namespace);
594 GNUNET_GE_BREAK (ectx, 0 == memcmp (&uri->data.sks.namespace,
595 pid, sizeof (GNUNET_HashCode)));
596 uri->data.sks.identifier = GNUNET_strdup (thisId);
597 GNUNET_hash_xor (&hc2, &uri->data.sks.namespace, &sb->identifier);
598 GNUNET_ECRS_encryptInPlace (&hc, &sb[1], size - sizeof (GNUNET_EC_SBlock));
599 GNUNET_GE_ASSERT (ectx,
600 GNUNET_OK == GNUNET_RSA_sign (hk,
601 size
602 -
603 sizeof
604 (GNUNET_RSA_Signature) -
605 sizeof
606 (GNUNET_RSA_PublicKey) -
607 sizeof (unsigned int),
608 &sb->identifier,
609 &sb->signature));
610 GNUNET_RSA_free_key (hk);
611 sock = GNUNET_client_connection_create (ectx, cfg);
612 ret = GNUNET_FS_insert (sock, value);
613 if (ret != GNUNET_OK)
614 {
615 GNUNET_free (uri);
616 uri = NULL;
617 }
618 GNUNET_client_connection_destroy (sock);
619 GNUNET_free (value);
620 GNUNET_free (dstURI);
621
622 return uri;
623}
624
625struct lNCLS
626{
627 struct GNUNET_GE_Context *ectx;
628 struct GNUNET_GC_Configuration *cfg;
629 GNUNET_ECRS_NamespaceInfoProcessor cb;
630 void *cls;
631 int cnt;
632};
633
634static int
635processFile_ (void *cls, const char *fileName)
636{
637 struct lNCLS *c = cls;
638 struct GNUNET_RSA_PrivateKey *hk;
639 GNUNET_RSA_PrivateKeyEncoded *hke;
640 char *dst;
641 unsigned long long len;
642 GNUNET_HashCode namespace;
643 GNUNET_RSA_PublicKey pk;
644 const char *name;
645
646 if (GNUNET_OK !=
647 GNUNET_disk_file_size (c->ectx, fileName, &len, GNUNET_YES))
648 return GNUNET_OK;
649 if (len < 2)
650 {
651 GNUNET_GE_LOG (c->ectx,
652 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
653 _("Format of file `%s' is invalid, trying to remove.\n"),
654 fileName);
655 UNLINK (fileName);
656 return GNUNET_OK;
657 }
658 dst = GNUNET_malloc (len);
659 len = GNUNET_disk_file_read (c->ectx, fileName, len, dst);
660 hke = (GNUNET_RSA_PrivateKeyEncoded *) dst;
661 if (ntohs (hke->len) != len)
662 {
663 GNUNET_GE_LOG (c->ectx,
664 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
665 _("Format of file `%s' is invalid, trying to remove.\n"),
666 fileName);
667 UNLINK (fileName);
668 GNUNET_free (hke);
669 return GNUNET_OK;
670 }
671 hk = GNUNET_RSA_decode_key (hke);
672 GNUNET_free (hke);
673 if (hk == NULL)
674 {
675 GNUNET_GE_LOG (c->ectx,
676 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
677 _("Format of file `%s' is invalid, trying to remove.\n"),
678 fileName);
679 UNLINK (fileName);
680 GNUNET_GE_BREAK (c->ectx, 0);
681 return GNUNET_SYSERR;
682 }
683 GNUNET_RSA_get_public_key (hk, &pk);
684 GNUNET_RSA_free_key (hk);
685 GNUNET_hash (&pk, sizeof (GNUNET_RSA_PublicKey), &namespace);
686 if (NULL != c->cb)
687 {
688 name = fileName;
689 while (NULL != strstr (name, DIR_SEPARATOR_STR))
690 name = 1 + strstr (name, DIR_SEPARATOR_STR);
691 if (GNUNET_OK == c->cb (&namespace, name, c->cls))
692 c->cnt++;
693 else
694 c->cnt = GNUNET_SYSERR;
695 }
696 else
697 c->cnt++;
698 return GNUNET_OK;
699}
700
701/**
702 * Build a list of all available namespaces
703 *
704 * @param list where to store the names (is allocated, caller frees)
705 * @return GNUNET_SYSERR on error, otherwise the number of pseudonyms in list
706 */
707int
708GNUNET_ECRS_get_namespaces (struct GNUNET_GE_Context *ectx,
709 struct GNUNET_GC_Configuration *cfg,
710 GNUNET_ECRS_NamespaceInfoProcessor cb, void *cls)
711{
712 char *dirName;
713 struct lNCLS myCLS;
714
715 myCLS.cls = cls;
716 myCLS.cb = cb;
717 myCLS.cnt = 0;
718 myCLS.ectx = ectx;
719 myCLS.cfg = cfg;
720 dirName = getPseudonymFileName (ectx, cfg, NULL);
721 GNUNET_disk_directory_scan (ectx, dirName, &processFile_, &myCLS);
722 GNUNET_free (dirName);
723 return myCLS.cnt;
724}
725
726
727
728/* end of namespace.c */
729#endif
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c
new file mode 100644
index 000000000..ac71c8f21
--- /dev/null
+++ b/src/fs/fs_publish.c
@@ -0,0 +1,459 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file fs/fs_publish.c
23 * @brief publish a file or directory in GNUnet
24 * @see http://gnunet.org/encoding.php3
25 * @author Krista Bennett
26 * @author Christian Grothoff
27 */
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_fs_service.h"
32#include "fs.h"
33
34#define DEBUG_PUBLISH GNUNET_YES
35
36
37
38#if 0
39
40/**
41 * Append the given key and query to the iblock[level]. If
42 * iblock[level] is already full, compute its chk and push it to
43 * level+1 and clear the level. iblocks is guaranteed to be big
44 * enough.
45 */
46static int
47pushBlock (struct GNUNET_ClientServerConnection *sock,
48 const GNUNET_EC_ContentHashKey * chk,
49 unsigned int level,
50 GNUNET_DatastoreValue ** iblocks,
51 unsigned int prio, GNUNET_CronTime expirationTime)
52{
53 unsigned int size;
54 unsigned int present;
55 GNUNET_DatastoreValue *value;
56 GNUNET_EC_DBlock *db;
57 GNUNET_EC_ContentHashKey ichk;
58
59 size = ntohl (iblocks[level]->size);
60 GNUNET_GE_ASSERT (NULL, size > sizeof (GNUNET_DatastoreValue));
61 size -= sizeof (GNUNET_DatastoreValue);
62 GNUNET_GE_ASSERT (NULL,
63 size - sizeof (GNUNET_EC_DBlock) <=
64 GNUNET_ECRS_IBLOCK_SIZE);
65 present =
66 (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);
67 db = (GNUNET_EC_DBlock *) & iblocks[level][1];
68 if (present == GNUNET_ECRS_CHK_PER_INODE)
69 {
70 GNUNET_EC_file_block_get_key (db, size, &ichk.key);
71 GNUNET_EC_file_block_get_query (db, size, &ichk.query);
72 if (GNUNET_OK != pushBlock (sock,
73 &ichk, level + 1, iblocks, prio,
74 expirationTime))
75 return GNUNET_SYSERR;
76 GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);
77 if (value == NULL)
78 {
79 GNUNET_GE_BREAK (NULL, 0);
80 return GNUNET_SYSERR;
81 }
82 value->priority = htonl (prio);
83 value->expiration_time = GNUNET_htonll (expirationTime);
84 if (GNUNET_OK != GNUNET_FS_insert (sock, value))
85 {
86 GNUNET_free (value);
87 return GNUNET_SYSERR;
88 }
89 GNUNET_free (value);
90 size = sizeof (GNUNET_EC_DBlock); /* type */
91 }
92 /* append GNUNET_EC_ContentHashKey */
93 memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));
94 size += sizeof (GNUNET_EC_ContentHashKey) + sizeof (GNUNET_DatastoreValue);
95 GNUNET_GE_ASSERT (NULL, size < GNUNET_MAX_BUFFER_SIZE);
96 iblocks[level]->size = htonl (size);
97
98 return GNUNET_OK;
99}
100
101/**
102 * Index or insert a file.
103 *
104 * @param priority what is the priority for OUR node to
105 * keep this file available? Use 0 for maximum anonymity and
106 * minimum reliability...
107 * @param doIndex GNUNET_YES for index, GNUNET_NO for insertion,
108 * GNUNET_SYSERR for simulation
109 * @param uri set to the URI of the uploaded file
110 * @return GNUNET_SYSERR if the upload failed (i.e. not enough space
111 * or gnunetd not running)
112 */
113int
114GNUNET_ECRS_file_upload (struct GNUNET_GE_Context *ectx,
115 struct GNUNET_GC_Configuration *cfg,
116 const char *filename,
117 int doIndex,
118 unsigned int anonymityLevel,
119 unsigned int priority,
120 GNUNET_CronTime expirationTime,
121 GNUNET_ECRS_UploadProgressCallback upcb,
122 void *upcbClosure,
123 GNUNET_ECRS_TestTerminate tt,
124 void *ttClosure, struct GNUNET_ECRS_URI **uri)
125{
126 unsigned long long filesize;
127 unsigned long long pos;
128 unsigned int treedepth;
129 int fd;
130 int i;
131 int ret;
132 unsigned int size;
133 GNUNET_DatastoreValue **iblocks;
134 GNUNET_DatastoreValue *dblock;
135 GNUNET_EC_DBlock *db;
136 GNUNET_DatastoreValue *value;
137 struct GNUNET_ClientServerConnection *sock;
138 GNUNET_HashCode fileId;
139 GNUNET_EC_ContentHashKey mchk;
140 GNUNET_CronTime eta;
141 GNUNET_CronTime start;
142 GNUNET_CronTime now;
143 GNUNET_EC_FileIdentifier fid;
144#if DEBUG_UPLOAD
145 GNUNET_EncName enc;
146#endif
147
148 GNUNET_GE_ASSERT (ectx, cfg != NULL);
149 start = GNUNET_get_time ();
150 memset (&mchk, 0, sizeof (GNUNET_EC_ContentHashKey));
151 if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))
152 {
153 GNUNET_GE_LOG (ectx,
154 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
155 _("`%s' is not a file.\n"), filename);
156 return GNUNET_SYSERR;
157 }
158 if (GNUNET_OK !=
159 GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))
160 {
161 GNUNET_GE_LOG (ectx,
162 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
163 _("Cannot get size of file `%s'"), filename);
164
165 return GNUNET_SYSERR;
166 }
167 sock = GNUNET_client_connection_create (ectx, cfg);
168 if (sock == NULL)
169 {
170 GNUNET_GE_LOG (ectx,
171 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
172 _("Failed to connect to gnunetd."));
173 return GNUNET_SYSERR;
174 }
175 eta = 0;
176 if (upcb != NULL)
177 upcb (filesize, 0, eta, upcbClosure);
178 if (doIndex == GNUNET_YES)
179 {
180 if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))
181 {
182 GNUNET_GE_LOG (ectx,
183 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
184 _("Cannot hash `%s'.\n"), filename);
185
186 GNUNET_client_connection_destroy (sock);
187 return GNUNET_SYSERR;
188 }
189 if (GNUNET_YES == GNUNET_FS_test_indexed (sock, &fileId))
190 {
191 /* file already indexed; simulate only to get the URI! */
192 doIndex = GNUNET_SYSERR;
193 }
194 }
195 if (doIndex == GNUNET_YES)
196 {
197 now = GNUNET_get_time ();
198 eta = now + 2 * (now - start);
199 /* very rough estimate: GNUNET_hash reads once through the file,
200 we'll do that once more and write it. But of course
201 the second read may be cached, and we have the encryption,
202 so a factor of two is really, really just a rough estimate */
203 start = now;
204 /* reset the counter since the formula later does not
205 take the time for GNUNET_hash_file into account */
206
207 switch (GNUNET_FS_prepare_to_index (sock, &fileId, filename))
208 {
209 case GNUNET_SYSERR:
210 GNUNET_GE_LOG (ectx,
211 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
212 _("Initialization for indexing file `%s' failed.\n"),
213 filename);
214 GNUNET_client_connection_destroy (sock);
215 return GNUNET_SYSERR;
216 case GNUNET_NO:
217 GNUNET_GE_LOG (ectx,
218 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
219 _
220 ("Indexing file `%s' failed. Suggestion: try to insert the file.\n"),
221 filename);
222 GNUNET_client_connection_destroy (sock);
223 return GNUNET_SYSERR;
224 default:
225 break;
226 }
227 }
228 treedepth = GNUNET_ECRS_compute_depth (filesize);
229 fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);
230 if (fd == -1)
231 {
232 GNUNET_GE_LOG (ectx,
233 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
234 _("Cannot open file `%s': `%s'"), filename,
235 STRERROR (errno));
236
237 GNUNET_client_connection_destroy (sock);
238 return GNUNET_SYSERR;
239 }
240
241 dblock =
242 GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
243 sizeof (GNUNET_EC_DBlock));
244 dblock->size =
245 htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
246 sizeof (GNUNET_EC_DBlock));
247 dblock->anonymity_level = htonl (anonymityLevel);
248 dblock->priority = htonl (priority);
249 dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
250 dblock->expiration_time = GNUNET_htonll (expirationTime);
251 db = (GNUNET_EC_DBlock *) & dblock[1];
252 db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
253 iblocks =
254 GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));
255 for (i = 0; i <= treedepth; i++)
256 {
257 iblocks[i] =
258 GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
259 GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));
260 iblocks[i]->size =
261 htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));
262 iblocks[i]->anonymity_level = htonl (anonymityLevel);
263 iblocks[i]->priority = htonl (priority);
264 iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
265 iblocks[i]->expiration_time = GNUNET_htonll (expirationTime);
266 ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =
267 htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
268 }
269
270 pos = 0;
271 while (pos < filesize)
272 {
273 if (upcb != NULL)
274 upcb (filesize, pos, eta, upcbClosure);
275 if (tt != NULL)
276 if (GNUNET_OK != tt (ttClosure))
277 goto FAILURE;
278 size = GNUNET_ECRS_DBLOCK_SIZE;
279 if (size > filesize - pos)
280 {
281 size = filesize - pos;
282 memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);
283 }
284 GNUNET_GE_ASSERT (ectx,
285 sizeof (GNUNET_DatastoreValue) + size +
286 sizeof (GNUNET_EC_DBlock) < GNUNET_MAX_BUFFER_SIZE);
287 dblock->size =
288 htonl (sizeof (GNUNET_DatastoreValue) + size +
289 sizeof (GNUNET_EC_DBlock));
290 if (size != READ (fd, &db[1], size))
291 {
292 GNUNET_GE_LOG_STRERROR_FILE (ectx,
293 GNUNET_GE_ERROR | GNUNET_GE_BULK |
294 GNUNET_GE_ADMIN | GNUNET_GE_USER,
295 "READ", filename);
296 goto FAILURE;
297 }
298 if (tt != NULL)
299 if (GNUNET_OK != tt (ttClosure))
300 goto FAILURE;
301 GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),
302 &mchk.key);
303 GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),
304 &mchk.query);
305#if DEBUG_UPLOAD
306 GNUNET_hash_to_enc (&mchk.query, &enc);
307 fprintf (stderr,
308 "Query for current block of size %u is `%s'\n", size,
309 (const char *) &enc);
310#endif
311 if (doIndex == GNUNET_YES)
312 {
313 if (GNUNET_SYSERR == GNUNET_FS_index (sock, &fileId, dblock, pos))
314 {
315 GNUNET_GE_LOG (ectx,
316 GNUNET_GE_ERROR | GNUNET_GE_BULK |
317 GNUNET_GE_USER,
318 _
319 ("Indexing data of file `%s' failed at position %llu.\n"),
320 filename, pos);
321 goto FAILURE;
322 }
323 }
324 else
325 {
326 value = NULL;
327 if (GNUNET_OK !=
328 GNUNET_EC_file_block_encode (db,
329 size + sizeof (GNUNET_EC_DBlock),
330 &mchk.query, &value))
331 {
332 GNUNET_GE_BREAK (ectx, 0);
333 goto FAILURE;
334 }
335 GNUNET_GE_ASSERT (ectx, value != NULL);
336 *value = *dblock; /* copy options! */
337 if ((doIndex == GNUNET_NO) &&
338 (GNUNET_OK != (ret = GNUNET_FS_insert (sock, value))))
339 {
340 GNUNET_GE_BREAK (ectx, ret == GNUNET_NO);
341 GNUNET_free (value);
342 goto FAILURE;
343 }
344 GNUNET_free (value);
345 }
346 pos += size;
347 now = GNUNET_get_time ();
348 if (pos > 0)
349 {
350 eta = (GNUNET_CronTime) (start +
351 (((double) (now - start) / (double) pos))
352 * (double) filesize);
353 }
354 if (GNUNET_OK != pushBlock (sock, &mchk, 0, /* dblocks are on level 0 */
355 iblocks, priority, expirationTime))
356 goto FAILURE;
357 }
358 if (tt != NULL)
359 if (GNUNET_OK != tt (ttClosure))
360 goto FAILURE;
361#if DEBUG_UPLOAD
362 GNUNET_GE_LOG (ectx,
363 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
364 "Tree depth is %u, walking up tree.\n", treedepth);
365#endif
366 for (i = 0; i < treedepth; i++)
367 {
368 size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);
369 GNUNET_GE_ASSERT (ectx, size < GNUNET_MAX_BUFFER_SIZE);
370 if (size == sizeof (GNUNET_EC_DBlock))
371 {
372#if DEBUG_UPLOAD
373 GNUNET_GE_LOG (ectx,
374 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
375 "Level %u is empty\n", i);
376#endif
377 continue;
378 }
379 db = (GNUNET_EC_DBlock *) & iblocks[i][1];
380 GNUNET_EC_file_block_get_key (db, size, &mchk.key);
381#if DEBUG_UPLOAD
382 GNUNET_GE_LOG (ectx,
383 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
384 "Computing query for %u bytes content.\n", size);
385#endif
386 GNUNET_EC_file_block_get_query (db, size, &mchk.query);
387#if DEBUG_UPLOAD
388 IF_GELOG (ectx,
389 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
390 GNUNET_hash_to_enc (&mchk.query, &enc));
391 GNUNET_GE_LOG (ectx,
392 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
393 "Query for current block at level %u is `%s'.\n", i,
394 &enc);
395#endif
396 if (GNUNET_OK != pushBlock (sock,
397 &mchk, i + 1, iblocks, priority,
398 expirationTime))
399 {
400 GNUNET_GE_BREAK (ectx, 0);
401 goto FAILURE;
402 }
403 GNUNET_EC_file_block_encode (db, size, &mchk.query, &value);
404 if (value == NULL)
405 {
406 GNUNET_GE_BREAK (ectx, 0);
407 goto FAILURE;
408 }
409 value->expiration_time = GNUNET_htonll (expirationTime);
410 value->priority = htonl (priority);
411 if ((doIndex != GNUNET_SYSERR) &&
412 (GNUNET_SYSERR == GNUNET_FS_insert (sock, value)))
413 {
414 GNUNET_GE_BREAK (ectx, 0);
415 GNUNET_free (value);
416 goto FAILURE;
417 }
418 GNUNET_free (value);
419 GNUNET_free (iblocks[i]);
420 iblocks[i] = NULL;
421 }
422#if DEBUG_UPLOAD
423 IF_GELOG (ectx,
424 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
425 GNUNET_hash_to_enc (&mchk.query, &enc));
426 GNUNET_GE_LOG (ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
427 "Query for top block is %s\n", &enc);
428#endif
429 /* build URI */
430 fid.file_length = GNUNET_htonll (filesize);
431 db = (GNUNET_EC_DBlock *) & iblocks[treedepth][1];
432
433 fid.chk = *(GNUNET_EC_ContentHashKey *) & (db[1]);
434 *uri = GNUNET_malloc (sizeof (URI));
435 (*uri)->type = chk;
436 (*uri)->data.fi = fid;
437
438 /* free resources */
439 GNUNET_free_non_null (iblocks[treedepth]);
440 GNUNET_free (iblocks);
441 GNUNET_free (dblock);
442 if (upcb != NULL)
443 upcb (filesize, filesize, eta, upcbClosure);
444 CLOSE (fd);
445 GNUNET_client_connection_destroy (sock);
446 return GNUNET_OK;
447FAILURE:
448 for (i = 0; i <= treedepth; i++)
449 GNUNET_free_non_null (iblocks[i]);
450 GNUNET_free (iblocks);
451 GNUNET_free (dblock);
452 CLOSE (fd);
453 GNUNET_client_connection_destroy (sock);
454 return GNUNET_SYSERR;
455}
456
457#endif
458
459/* end of fs_publish.c */
diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c
new file mode 100644
index 000000000..56240af69
--- /dev/null
+++ b/src/fs/fs_search.c
@@ -0,0 +1,572 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/ecrs/search.c
23 * @brief Helper functions for searching.
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_protocols.h"
29#include "gnunet_fs_lib.h"
30#include "gnunet_ecrs_lib.h"
31#include "ecrs_core.h"
32#include "ecrs.h"
33
34#define DEBUG_SEARCH GNUNET_NO
35
36/**
37 * Context for an individual search. Followed
38 * by keyCount keys of type GNUNET_HashCode.
39 */
40struct PendingSearch
41{
42 struct PendingSearch *next;
43
44 struct GNUNET_ECRS_SearchContext *context;
45
46 /**
47 * The key (for decryption)
48 */
49 GNUNET_HashCode decryptKey;
50
51 unsigned int keyCount;
52
53 /**
54 * What type of query is it?
55 */
56 unsigned int type;
57
58};
59
60/**
61 * Context for search operation.
62 */
63struct GNUNET_ECRS_SearchContext
64{
65 /**
66 * Time when the cron-job was first started.
67 */
68 GNUNET_CronTime start;
69
70 /**
71 * What is the global timeout?
72 */
73 GNUNET_CronTime timeout;
74
75 /**
76 * Search context
77 */
78 struct GNUNET_FS_SearchContext *sctx;
79
80 /**
81 * Active searches.
82 */
83 struct PendingSearch *queries;
84
85 GNUNET_ECRS_SearchResultProcessor spcb;
86
87 void *spcbClosure;
88
89 struct GNUNET_GE_Context *ectx;
90
91 struct GNUNET_GC_Configuration *cfg;
92
93 int aborted;
94
95 int my_sctx;
96
97 unsigned int anonymityLevel;
98
99};
100
101static int
102receive_response_callback (const GNUNET_HashCode * key,
103 const GNUNET_DatastoreValue * value,
104 void *cls, unsigned long long uid);
105
106/**
107 * Add a query to the SQC.
108 */
109static void
110add_search (unsigned int type,
111 unsigned int keyCount,
112 const GNUNET_HashCode * keys,
113 const GNUNET_HashCode * dkey,
114 struct GNUNET_ECRS_SearchContext *sqc)
115{
116 struct PendingSearch *ps;
117
118 ps =
119 GNUNET_malloc (sizeof (struct PendingSearch) +
120 sizeof (GNUNET_HashCode) * keyCount);
121 ps->type = type;
122 ps->keyCount = keyCount;
123 memcpy (&ps[1], keys, sizeof (GNUNET_HashCode) * keyCount);
124 ps->decryptKey = *dkey;
125 ps->context = sqc;
126 ps->next = sqc->queries;
127 sqc->queries = ps;
128 GNUNET_FS_start_search (sqc->sctx,
129 NULL,
130 type,
131 keyCount,
132 keys,
133 sqc->anonymityLevel,
134 &receive_response_callback, ps);
135}
136
137/**
138 * Add the query that corresponds to the given URI
139 * to the SQC.
140 */
141static void
142add_search_for_uri (const struct GNUNET_ECRS_URI *uri,
143 struct GNUNET_ECRS_SearchContext *sqc)
144{
145 struct GNUNET_GE_Context *ectx = sqc->ectx;
146
147 switch (uri->type)
148 {
149 case chk:
150 GNUNET_GE_LOG (ectx,
151 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
152 _("CHK URI not allowed for search.\n"));
153 break;
154 case sks:
155 {
156 GNUNET_HashCode keys[2];
157 GNUNET_HashCode hk; /* hk = GNUNET_hash(identifier) */
158 GNUNET_HashCode hk2; /* hk2 = GNUNET_hash(hk) */
159
160 GNUNET_hash (uri->data.sks.identifier,
161 strlen (uri->data.sks.identifier), &hk);
162 GNUNET_hash (&hk, sizeof (GNUNET_HashCode), &hk2);
163 /* compute routing key keys[0] = H(key) ^ namespace */
164 GNUNET_hash_xor (&hk2, &uri->data.sks.namespace, &keys[0]);
165 keys[1] = uri->data.sks.namespace;
166 add_search (GNUNET_ECRS_BLOCKTYPE_SIGNED, 2, &keys[0], &hk, sqc);
167 break;
168 }
169 case ksk:
170 {
171 GNUNET_HashCode hc;
172 GNUNET_HashCode query;
173 struct GNUNET_RSA_PrivateKey *pk;
174 GNUNET_RSA_PublicKey pub;
175 int i;
176 const char *keyword;
177
178#if DEBUG_SEARCH
179 GNUNET_GE_LOG (ectx,
180 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
181 "Computing queries (this may take a while).\n");
182#endif
183 for (i = 0; i < uri->data.ksk.keywordCount; i++)
184 {
185 keyword = uri->data.ksk.keywords[i];
186 /* first character of the keyword is
187 "+" or " " to indicate mandatory or
188 not -- ignore for hashing! */
189 GNUNET_hash (&keyword[1], strlen (&keyword[1]), &hc);
190 pk = GNUNET_RSA_create_key_from_hash (&hc);
191 GNUNET_RSA_get_public_key (pk, &pub);
192 GNUNET_hash (&pub, sizeof (GNUNET_RSA_PublicKey), &query);
193 add_search (GNUNET_ECRS_BLOCKTYPE_ANY, /* GNUNET_ECRS_BLOCKTYPE_KEYWORD, GNUNET_ECRS_BLOCKTYPE_NAMESPACE or GNUNET_ECRS_BLOCKTYPE_KEYWORD_FOR_NAMESPACE ok */
194 1, &query, &hc, sqc);
195 GNUNET_RSA_free_key (pk);
196 }
197#if DEBUG_SEARCH
198 GNUNET_GE_LOG (ectx,
199 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
200 "Queries ready.\n");
201#endif
202 break;
203 }
204 case loc:
205 GNUNET_GE_LOG (ectx,
206 GNUNET_GE_ERROR | GNUNET_GE_BULK | GNUNET_GE_USER,
207 _("LOC URI not allowed for search.\n"));
208 break;
209 default:
210 GNUNET_GE_BREAK (ectx, 0);
211 /* unknown URI type */
212 break;
213 }
214}
215
216/**
217 * We found an GNUNET_EC_SBlock. Decode the meta-data and call
218 * the callback of the SQC with the root-URI for the namespace,
219 * together with the namespace advertisement. Also, if this is
220 * a result with updates, automatically start the search for
221 * updates.
222 */
223static int
224process_sblock_result (const GNUNET_EC_SBlock * sb,
225 const GNUNET_HashCode * key,
226 unsigned int size,
227 struct GNUNET_ECRS_SearchContext *sqc)
228{
229 static GNUNET_HashCode allZeros;
230 struct GNUNET_GE_Context *ectx = sqc->ectx;
231 GNUNET_ECRS_FileInfo fi;
232 URI updateURI;
233 int ret;
234 const char *id;
235 const char *uris;
236 unsigned int len;
237 unsigned int off;
238 int isRoot;
239
240 len = size - sizeof (GNUNET_EC_SBlock);
241 off = GNUNET_string_buffer_tokenize ((const char *) &sb[1],
242 len, 2, &id, &uris);
243 if (off == 0)
244 {
245 GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
246 return GNUNET_SYSERR;
247 }
248 fi.meta = GNUNET_meta_data_deserialize (ectx, &id[off], len - off);
249 if (fi.meta == NULL)
250 {
251 GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
252 return GNUNET_SYSERR;
253 }
254 isRoot = 0 == memcmp (&sb->identifier, &allZeros, sizeof (GNUNET_HashCode));
255 fi.uri = GNUNET_ECRS_string_to_uri (ectx, uris);
256 if ((isRoot) && (fi.uri == NULL))
257 {
258 fi.uri = GNUNET_malloc (sizeof (URI));
259 fi.uri->type = sks;
260 GNUNET_hash (&sb->subspace,
261 sizeof (GNUNET_RSA_PublicKey),
262 &fi.uri->data.sks.namespace);
263 fi.uri->data.sks.identifier = GNUNET_strdup (id);
264 }
265 if (fi.uri == NULL)
266 {
267 GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
268 GNUNET_meta_data_destroy (fi.meta);
269 return GNUNET_SYSERR;
270 }
271 if (sqc->spcb != NULL)
272 {
273 ret = sqc->spcb (&fi, key, isRoot, sqc->spcbClosure);
274 if (ret == GNUNET_SYSERR)
275 sqc->aborted = GNUNET_YES;
276 }
277 else
278 ret = GNUNET_OK;
279 if ((strlen (id) > 0) && (strlen (uris) > 0))
280 {
281 updateURI.type = sks;
282 GNUNET_hash (&sb->subspace,
283 sizeof (GNUNET_RSA_PublicKey),
284 &updateURI.data.sks.namespace);
285 updateURI.data.sks.identifier = GNUNET_strdup (id);
286 add_search_for_uri (&updateURI, sqc);
287 GNUNET_free (updateURI.data.sks.identifier);
288 }
289 GNUNET_meta_data_destroy (fi.meta);
290 GNUNET_ECRS_uri_destroy (fi.uri);
291 return ret;
292}
293
294/**
295 * Process replies received in response to our
296 * queries. Verifies, decrypts and passes valid
297 * replies to the callback.
298 *
299 * @return GNUNET_SYSERR if the entry is malformed
300 */
301static int
302receive_response_callback (const GNUNET_HashCode * key,
303 const GNUNET_DatastoreValue * value,
304 void *cls, unsigned long long uid)
305{
306 struct PendingSearch *ps = cls;
307 struct GNUNET_ECRS_SearchContext *sqc = ps->context;
308 struct GNUNET_GE_Context *ectx = sqc->ectx;
309 unsigned int type;
310 GNUNET_ECRS_FileInfo fi;
311 unsigned int size;
312 int ret;
313 GNUNET_HashCode query;
314 GNUNET_CronTime expiration;
315
316 expiration = GNUNET_ntohll (value->expiration_time);
317 if (expiration < GNUNET_get_time ())
318 return GNUNET_OK; /* expired, ignore! */
319 type = ntohl (value->type);
320 size = ntohl (value->size) - sizeof (GNUNET_DatastoreValue);
321#if DEBUG_SEARCH
322 GNUNET_GE_LOG (ectx,
323 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
324 "Search received reply of type %u and size %u.\n", type,
325 size);
326#endif
327 if (GNUNET_OK !=
328 GNUNET_EC_file_block_check_and_get_query (size,
329 (const GNUNET_EC_DBlock *)
330 &value[1], GNUNET_YES,
331 &query))
332 {
333 GNUNET_GE_BREAK_OP (NULL, 0);
334 return GNUNET_SYSERR;
335 }
336 if (!((0 == memcmp (&query,
337 (GNUNET_HashCode *) & ps[1], sizeof (GNUNET_HashCode)))
338 && ((ps->type == type) || (ps->type == GNUNET_ECRS_BLOCKTYPE_ANY))
339 && (GNUNET_YES ==
340 GNUNET_EC_is_block_applicable_for_query (type, size,
341 (const GNUNET_EC_DBlock
342 *) &value[1], &query,
343 ps->keyCount,
344 (GNUNET_HashCode *) &
345 ps[1]))))
346 {
347 return GNUNET_OK; /* not a match */
348 }
349
350 switch (type)
351 {
352 case GNUNET_ECRS_BLOCKTYPE_KEYWORD:
353 {
354 GNUNET_EC_KBlock *kb;
355 const char *dstURI;
356#if DEBUG_SEARCH
357 GNUNET_EncName enc;
358#endif
359 int j;
360
361 if (size < sizeof (GNUNET_EC_KBlock))
362 {
363 GNUNET_GE_BREAK_OP (NULL, 0);
364 return GNUNET_SYSERR;
365 }
366 kb = GNUNET_malloc (size);
367 memcpy (kb, &value[1], size);
368#if DEBUG_SEARCH
369 IF_GELOG (ectx,
370 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
371 GNUNET_GE_USER, GNUNET_hash_to_enc (&ps->decryptKey, &enc));
372 GNUNET_GE_LOG (ectx,
373 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
374 GNUNET_GE_USER,
375 "Decrypting KBlock with key %s.\n", &enc);
376#endif
377 GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
378 &kb[1], size - sizeof (GNUNET_EC_KBlock));
379 j = sizeof (GNUNET_EC_KBlock);
380 while ((j < size) && (((const char *) kb)[j] != '\0'))
381 j++;
382 if (j == size)
383 {
384 GNUNET_GE_BREAK_OP (ectx, 0); /* kblock malformed */
385 GNUNET_free (kb);
386 return GNUNET_SYSERR;
387 }
388 dstURI = (const char *) &kb[1];
389 j++;
390 fi.meta = GNUNET_meta_data_deserialize (ectx,
391 &((const char *)
392 kb)[j], size - j);
393 if (fi.meta == NULL)
394 {
395 GNUNET_GE_BREAK_OP (ectx, 0); /* kblock malformed */
396 GNUNET_free (kb);
397 return GNUNET_SYSERR;
398 }
399 fi.uri = GNUNET_ECRS_string_to_uri (ectx, dstURI);
400 if (fi.uri == NULL)
401 {
402 GNUNET_GE_BREAK_OP (ectx, 0); /* kblock malformed */
403 GNUNET_meta_data_destroy (fi.meta);
404 GNUNET_free (kb);
405 return GNUNET_SYSERR;
406 }
407 if (sqc->spcb != NULL)
408 {
409 ret = sqc->spcb (&fi,
410 &ps->decryptKey, GNUNET_NO, sqc->spcbClosure);
411 if (ret == GNUNET_SYSERR)
412 sqc->aborted = GNUNET_YES;
413 }
414 else
415 ret = GNUNET_OK;
416 GNUNET_ECRS_uri_destroy (fi.uri);
417 GNUNET_meta_data_destroy (fi.meta);
418 GNUNET_free (kb);
419 return ret;
420 }
421 case GNUNET_ECRS_BLOCKTYPE_SIGNED:
422 {
423 GNUNET_EC_SBlock *sb;
424 int ret;
425
426 if (size < sizeof (GNUNET_EC_SBlock))
427 {
428 GNUNET_GE_BREAK_OP (ectx, 0); /* sblock malformed */
429 return GNUNET_SYSERR;
430 }
431 sb = GNUNET_malloc (size);
432 memcpy (sb, &value[1], size);
433 GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
434 &sb[1], size - sizeof (GNUNET_EC_SBlock));
435 ret = process_sblock_result (sb, &ps->decryptKey, size, sqc);
436 GNUNET_free (sb);
437 return ret;
438 }
439 case GNUNET_ECRS_BLOCKTYPE_KEYWORD_SIGNED:
440 {
441 GNUNET_EC_KSBlock *kb;
442 int ret;
443
444 if (size < sizeof (GNUNET_EC_KSBlock))
445 {
446 GNUNET_GE_BREAK_OP (ectx, 0); /* ksblock malformed */
447 return GNUNET_SYSERR;
448 }
449 kb = GNUNET_malloc (size);
450 memcpy (kb, &value[1], size);
451 GNUNET_ECRS_decryptInPlace (&ps->decryptKey,
452 &kb->sblock,
453 size - sizeof (GNUNET_EC_KBlock) -
454 sizeof (unsigned int));
455 ret =
456 process_sblock_result (&kb->sblock, &ps->decryptKey,
457 size - sizeof (GNUNET_EC_KSBlock) +
458 sizeof (GNUNET_EC_SBlock), sqc);
459 GNUNET_free (kb);
460 return ret;
461 }
462 default:
463 GNUNET_GE_BREAK_OP (ectx, 0);
464 break;
465 } /* end switch */
466 return GNUNET_OK;
467}
468
469/**
470 * Start search for content.
471 *
472 * @param uri specifies the search parameters
473 * @param uri set to the URI of the uploaded file
474 */
475struct GNUNET_ECRS_SearchContext *
476GNUNET_ECRS_search_start (struct GNUNET_GE_Context *ectx,
477 struct GNUNET_GC_Configuration *cfg,
478 struct GNUNET_FS_SearchContext *sc,
479 const struct GNUNET_ECRS_URI *uri,
480 unsigned int anonymityLevel,
481 GNUNET_ECRS_SearchResultProcessor spcb,
482 void *spcbClosure)
483{
484 struct GNUNET_ECRS_SearchContext *ctx;
485
486 if (GNUNET_YES == GNUNET_ECRS_uri_test_ksk (uri))
487 {
488 if (1 != GNUNET_ECRS_uri_get_keyword_count_from_ksk (uri))
489 return NULL;
490 }
491 else
492 {
493 if (GNUNET_YES != GNUNET_ECRS_uri_test_sks (uri))
494 return NULL;
495 }
496 ctx = GNUNET_malloc (sizeof (struct GNUNET_ECRS_SearchContext));
497 ctx->start = GNUNET_get_time ();
498 ctx->anonymityLevel = anonymityLevel;
499 ctx->ectx = ectx;
500 ctx->cfg = cfg;
501 ctx->queries = NULL;
502 ctx->spcb = spcb;
503 ctx->spcbClosure = spcbClosure;
504 ctx->aborted = GNUNET_NO;
505 ctx->sctx = sc == NULL ? GNUNET_FS_create_search_context (ectx, cfg) : sc;
506 if (ctx->sctx == NULL)
507 {
508 GNUNET_free (ctx);
509 return NULL;
510 }
511 ctx->my_sctx = (sc == NULL);
512 add_search_for_uri (uri, ctx);
513 return ctx;
514}
515
516/**
517 * Stop search for content.
518 *
519 * @param uri specifies the search parameters
520 * @param uri set to the URI of the uploaded file
521 */
522void
523GNUNET_ECRS_search_stop (struct GNUNET_ECRS_SearchContext *ctx)
524{
525 struct PendingSearch *pos;
526
527 while (ctx->queries != NULL)
528 {
529 pos = ctx->queries;
530 ctx->queries = pos->next;
531 if (!ctx->my_sctx)
532 GNUNET_FS_stop_search (ctx->sctx, &receive_response_callback, pos);
533 GNUNET_free (pos);
534 }
535 if (ctx->my_sctx)
536 GNUNET_FS_destroy_search_context (ctx->sctx);
537 GNUNET_free (ctx);
538}
539
540/**
541 * Search for content.
542 *
543 * @param timeout how long to wait (relative)
544 * @param uri specifies the search parameters
545 * @param uri set to the URI of the uploaded file
546 */
547int
548GNUNET_ECRS_search (struct GNUNET_GE_Context *ectx,
549 struct GNUNET_GC_Configuration *cfg,
550 const struct GNUNET_ECRS_URI *uri,
551 unsigned int anonymityLevel,
552 GNUNET_ECRS_SearchResultProcessor spcb,
553 void *spcbClosure, GNUNET_ECRS_TestTerminate tt,
554 void *ttClosure)
555{
556 struct GNUNET_ECRS_SearchContext *ctx;
557
558 ctx =
559 GNUNET_ECRS_search_start (ectx, cfg, NULL,
560 uri, anonymityLevel, spcb, spcbClosure);
561 if (ctx == NULL)
562 return GNUNET_SYSERR;
563 while (((NULL == tt) || (GNUNET_OK == tt (ttClosure)))
564 && (GNUNET_NO == GNUNET_shutdown_test ())
565 && (ctx->aborted == GNUNET_NO))
566 GNUNET_thread_sleep (100 * GNUNET_CRON_MILLISECONDS);
567 GNUNET_ECRS_search_stop (ctx);
568 return GNUNET_OK;
569}
570
571
572/* end of search.c */
diff --git a/src/fs/fs_test.c b/src/fs/fs_test.c
new file mode 100644
index 000000000..5eedda982
--- /dev/null
+++ b/src/fs/fs_test.c
@@ -0,0 +1,259 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/fsui/basic_fsui_test.c
23 * @brief testcase for fsui (upload-search-download-unindex)
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "gnunet_fsui_lib.h"
30
31#define DEBUG_VERBOSE GNUNET_NO
32
33#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(NULL, 0); goto FAILURE; }
34
35static char *
36makeName (unsigned int i)
37{
38 char *fn;
39
40 fn =
41 GNUNET_malloc (strlen ("/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST") +
42 14);
43 GNUNET_snprintf (fn,
44 strlen ("/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST") +
45 14, "/tmp/gnunet-basic_fsui_test/BASIC_FSUI_TEST%u", i);
46 GNUNET_disk_directory_create_for_file (NULL, fn);
47 return fn;
48}
49
50static volatile enum GNUNET_FSUI_EventType lastEvent;
51
52static struct GNUNET_MetaData *search_meta;
53
54static struct GNUNET_ECRS_URI *search_uri;
55
56static struct GNUNET_FSUI_Context *ctx;
57
58static void *
59eventCallback (void *cls, const GNUNET_FSUI_Event * event)
60{
61 static char unused;
62
63 switch (event->type)
64 {
65 case GNUNET_FSUI_search_resumed:
66 case GNUNET_FSUI_download_resumed:
67 case GNUNET_FSUI_upload_resumed:
68 case GNUNET_FSUI_unindex_resumed:
69 return &unused;
70 case GNUNET_FSUI_search_result:
71#if DEBUG_VERBOSE
72 printf ("Received search result\n");
73#endif
74 search_uri =
75 GNUNET_ECRS_uri_duplicate (event->data.SearchResult.fi.uri);
76 search_meta =
77 GNUNET_meta_data_duplicate (event->data.SearchResult.fi.meta);
78 break;
79 case GNUNET_FSUI_upload_completed:
80#if DEBUG_VERBOSE
81 printf ("Upload complete.\n");
82#endif
83 break;
84 case GNUNET_FSUI_download_completed:
85#if DEBUG_VERBOSE
86 printf ("Download complete.\n");
87#endif
88 break;
89 case GNUNET_FSUI_unindex_completed:
90#if DEBUG_VERBOSE
91 printf ("Unindex complete.\n");
92#endif
93 break;
94 default:
95 break;
96 }
97 lastEvent = event->type;
98 return NULL;
99}
100
101#define START_DAEMON 1
102
103int
104main (int argc, char *argv[])
105{
106#if START_DAEMON
107 pid_t daemon;
108#endif
109 int ok;
110 struct GNUNET_ECRS_URI *uri;
111 char *filename = NULL;
112 char *keywords[] = {
113 "fsui_foo",
114 "fsui_bar",
115 };
116 char keyword[40];
117 char *fn;
118 int prog;
119 struct GNUNET_MetaData *meta;
120 struct GNUNET_ECRS_URI *kuri;
121 struct GNUNET_GC_Configuration *cfg;
122 struct GNUNET_FSUI_UploadList *upload = NULL;
123 struct GNUNET_FSUI_SearchList *search = NULL;
124 struct GNUNET_FSUI_UnindexList *unindex = NULL;
125 struct GNUNET_FSUI_DownloadList *download = NULL;
126
127 cfg = GNUNET_GC_create ();
128 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
129 {
130 GNUNET_GC_free (cfg);
131 return -1;
132 }
133#if START_DAEMON
134 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
135 GNUNET_GE_ASSERT (NULL, daemon > 0);
136 CHECK (GNUNET_OK ==
137 GNUNET_wait_for_daemon_running (NULL, cfg,
138 60 * GNUNET_CRON_SECONDS));
139#endif
140 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to start */
141 ok = GNUNET_YES;
142
143 /* ACTUAL TEST CODE */
144 ctx = GNUNET_FSUI_start (NULL, cfg, "basic_fsui_test", 32, /* thread pool size */
145 GNUNET_NO, /* no resume */
146 &eventCallback, NULL);
147 CHECK (ctx != NULL);
148 filename = makeName (42);
149 GNUNET_disk_file_write (NULL,
150 filename,
151 "foo bar test!", strlen ("foo bar test!"), "600");
152 meta = GNUNET_meta_data_create ();
153 kuri =
154 GNUNET_ECRS_keyword_command_line_to_uri (NULL, 2,
155 (const char **) keywords);
156 /* upload */
157 upload = GNUNET_FSUI_upload_start (ctx, filename, (GNUNET_FSUI_DirectoryScanCallback) & GNUNET_disk_directory_scan, NULL, 0, /* anonymity */
158 0, /* priority */
159 GNUNET_YES,
160 GNUNET_NO,
161 GNUNET_NO,
162 GNUNET_get_time () +
163 5 * GNUNET_CRON_HOURS, meta, kuri, kuri);
164 CHECK (upload != NULL);
165 GNUNET_ECRS_uri_destroy (kuri);
166 GNUNET_meta_data_destroy (meta);
167 prog = 0;
168 while (lastEvent != GNUNET_FSUI_upload_completed)
169 {
170 prog++;
171 CHECK (prog <
172 10000) GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
173 if (GNUNET_shutdown_test () == GNUNET_YES)
174 break;
175 }
176
177 /* search */
178 GNUNET_snprintf (keyword, 40, "+%s +%s", keywords[0], keywords[1]);
179 uri = GNUNET_ECRS_keyword_string_to_uri (NULL, keyword);
180 search = GNUNET_FSUI_search_start (ctx, 0, uri);
181 GNUNET_ECRS_uri_destroy (uri);
182 CHECK (search != NULL);
183 prog = 0;
184 while (lastEvent != GNUNET_FSUI_search_result)
185 {
186 prog++;
187 CHECK (prog < 10000);
188 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
189 if (GNUNET_shutdown_test () == GNUNET_YES)
190 break;
191 }
192 GNUNET_FSUI_search_abort (search);
193 GNUNET_FSUI_search_stop (search);
194
195 /* download */
196 fn = makeName (43);
197 download = GNUNET_FSUI_download_start (ctx,
198 0,
199 GNUNET_NO,
200 search_uri,
201 search_meta, fn, NULL, NULL);
202 GNUNET_free (fn);
203 prog = 0;
204 while (lastEvent != GNUNET_FSUI_download_completed)
205 {
206 prog++;
207 CHECK (prog < 10000);
208 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
209 if (GNUNET_shutdown_test () == GNUNET_YES)
210 break;
211 }
212 GNUNET_FSUI_download_stop (download);
213 download = NULL;
214 GNUNET_ECRS_uri_destroy (search_uri);
215 GNUNET_meta_data_destroy (search_meta);
216 /* unindex */
217 unindex = GNUNET_FSUI_unindex_start (ctx, filename);
218 prog = 0;
219 while (lastEvent != GNUNET_FSUI_unindex_completed)
220 {
221 prog++;
222 CHECK (prog < 10000);
223 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
224 if (GNUNET_shutdown_test () == GNUNET_YES)
225 break;
226 }
227 if (lastEvent != GNUNET_FSUI_unindex_completed)
228 GNUNET_FSUI_unindex_abort (unindex);
229 GNUNET_FSUI_unindex_stop (unindex);
230
231
232 /* END OF TEST CODE */
233FAILURE:
234 if (ctx != NULL)
235 GNUNET_FSUI_stop (ctx);
236 if (filename != NULL)
237 {
238 UNLINK (filename);
239 GNUNET_free (filename);
240 }
241 if (download != NULL)
242 {
243 GNUNET_FSUI_download_abort (download);
244 GNUNET_FSUI_download_stop (download);
245 }
246 filename = makeName (43);
247 /* TODO: verify file 'filename(42)' == file 'filename(43)' */
248 UNLINK (filename);
249 GNUNET_free (filename);
250
251#if START_DAEMON
252 GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
253#endif
254 GNUNET_GC_free (cfg);
255
256 return (ok == GNUNET_YES) ? 0 : 1;
257}
258
259/* end of basic_fsui_test.c */
diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c
new file mode 100644
index 000000000..ef63e798e
--- /dev/null
+++ b/src/fs/fs_unindex.c
@@ -0,0 +1,394 @@
1/*
2 This file is part of GNUnet.
3 (C) 2003, 2004, 2006 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/ecrs/unindex.c
23 * @author Krista Bennett
24 * @author Christian Grothoff
25 *
26 * Unindex file.
27 *
28 * TODO:
29 * - code cleanup (share more with upload.c)
30 */
31
32#include "platform.h"
33#include "gnunet_protocols.h"
34#include "gnunet_ecrs_lib.h"
35#include "gnunet_fs_lib.h"
36#include "gnunet_getoption_lib.h"
37#include "ecrs_core.h"
38#include "ecrs.h"
39#include "fs.h"
40#include "tree.h"
41
42#define STRICT_CHECKS GNUNET_NO
43
44/**
45 * Append the given key and query to the iblock[level].
46 * If iblock[level] is already full, compute its chk
47 * and push it to level+1. iblocks is guaranteed to
48 * be big enough.
49 *
50 * This function matches exactly upload.c::pushBlock,
51 * except in the call to 'GNUNET_FS_delete'. TODO: refactor
52 * to avoid code duplication (move to block.c, pass
53 * GNUNET_FS_delete as argument!).
54 */
55static int
56pushBlock (struct GNUNET_ClientServerConnection *sock,
57 const GNUNET_EC_ContentHashKey * chk, unsigned int level,
58 GNUNET_DatastoreValue ** iblocks)
59{
60 unsigned int size;
61 unsigned int present;
62 GNUNET_DatastoreValue *value;
63 GNUNET_EC_DBlock *db;
64 GNUNET_EC_ContentHashKey ichk;
65
66 size = ntohl (iblocks[level]->size) - sizeof (GNUNET_DatastoreValue);
67 present =
68 (size - sizeof (GNUNET_EC_DBlock)) / sizeof (GNUNET_EC_ContentHashKey);
69 db = (GNUNET_EC_DBlock *) & iblocks[level][1];
70 if (present == GNUNET_ECRS_CHK_PER_INODE)
71 {
72 GNUNET_EC_file_block_get_key (db, size, &ichk.key);
73 GNUNET_EC_file_block_get_query (db, size, &ichk.query);
74 if (GNUNET_OK != pushBlock (sock, &ichk, level + 1, iblocks))
75 {
76 GNUNET_GE_BREAK (NULL, 0);
77 return GNUNET_SYSERR;
78 }
79 GNUNET_EC_file_block_encode (db, size, &ichk.query, &value);
80#if STRICT_CHECKS
81 if (GNUNET_SYSERR == GNUNET_FS_delete (sock, value))
82 {
83 GNUNET_free (value);
84 GNUNET_GE_BREAK (NULL, 0);
85 return GNUNET_SYSERR;
86 }
87#else
88 GNUNET_FS_delete (sock, value);
89#endif
90 GNUNET_free (value);
91 size = sizeof (GNUNET_EC_DBlock);
92 }
93 /* append GNUNET_EC_ContentHashKey */
94 memcpy (&((char *) db)[size], chk, sizeof (GNUNET_EC_ContentHashKey));
95 iblocks[level]->size = htonl (size +
96 sizeof (GNUNET_EC_ContentHashKey) +
97 sizeof (GNUNET_DatastoreValue));
98 return GNUNET_OK;
99}
100
101
102
103/**
104 * Undo sym-linking operation:
105 * a) check if we have a symlink
106 * b) delete symbolic link
107 */
108static int
109undoSymlinking (struct GNUNET_GE_Context *ectx,
110 const char *fn,
111 const GNUNET_HashCode * fileId,
112 struct GNUNET_ClientServerConnection *sock)
113{
114 GNUNET_EncName enc;
115 char *serverDir;
116 char *serverFN;
117 struct stat buf;
118
119#ifndef S_ISLNK
120 if (1)
121 return GNUNET_OK; /* symlinks do not exist? */
122#endif
123 if (0 != LSTAT (fn, &buf))
124 {
125 GNUNET_GE_LOG_STRERROR_FILE (ectx,
126 GNUNET_GE_ERROR | GNUNET_GE_BULK |
127 GNUNET_GE_USER | GNUNET_GE_ADMIN, "stat",
128 fn);
129 return GNUNET_SYSERR;
130 }
131#ifdef S_ISLNK
132 if (!S_ISLNK (buf.st_mode))
133 return GNUNET_OK;
134#endif
135 serverDir =
136 GNUNET_get_daemon_configuration_value (sock, "FS", "INDEX-DIRECTORY");
137 if (serverDir == NULL)
138 return GNUNET_OK;
139 serverFN = GNUNET_malloc (strlen (serverDir) + 2 + sizeof (GNUNET_EncName));
140 strcpy (serverFN, serverDir);
141 GNUNET_free (serverDir);
142 if (serverFN[strlen (serverFN) - 1] != DIR_SEPARATOR)
143 strcat (serverFN, DIR_SEPARATOR_STR);
144 GNUNET_hash_to_enc (fileId, &enc);
145 strcat (serverFN, (char *) &enc);
146
147 if (0 != UNLINK (serverFN))
148 {
149 GNUNET_GE_LOG_STRERROR_FILE (ectx,
150 GNUNET_GE_ERROR | GNUNET_GE_BULK |
151 GNUNET_GE_USER | GNUNET_GE_ADMIN, "unlink",
152 serverFN);
153 GNUNET_free (serverFN);
154 return GNUNET_SYSERR;
155 }
156 GNUNET_free (serverFN);
157 return GNUNET_OK;
158}
159
160
161
162/**
163 * Unindex a file.
164 *
165 * @return GNUNET_SYSERR if the unindexing failed (i.e. not indexed)
166 */
167int
168GNUNET_ECRS_file_unindex (struct GNUNET_GE_Context *ectx,
169 struct GNUNET_GC_Configuration *cfg,
170 const char *filename,
171 GNUNET_ECRS_UploadProgressCallback upcb,
172 void *upcbClosure, GNUNET_ECRS_TestTerminate tt,
173 void *ttClosure)
174{
175 unsigned long long filesize;
176 unsigned long long pos;
177 unsigned int treedepth;
178 int fd;
179 int i;
180 unsigned int size;
181 GNUNET_DatastoreValue **iblocks;
182 GNUNET_DatastoreValue *dblock;
183 GNUNET_EC_DBlock *db;
184 GNUNET_DatastoreValue *value;
185 struct GNUNET_ClientServerConnection *sock;
186 GNUNET_HashCode fileId;
187 GNUNET_EC_ContentHashKey chk;
188 GNUNET_CronTime eta;
189 GNUNET_CronTime start;
190 GNUNET_CronTime now;
191 int wasIndexed;
192
193 start = GNUNET_get_time ();
194 if (GNUNET_YES != GNUNET_disk_file_test (ectx, filename))
195 {
196 GNUNET_GE_BREAK (ectx, 0);
197 return GNUNET_SYSERR;
198 }
199 if (GNUNET_OK !=
200 GNUNET_disk_file_size (ectx, filename, &filesize, GNUNET_YES))
201 return GNUNET_SYSERR;
202 sock = GNUNET_client_connection_create (ectx, cfg);
203 if (sock == NULL)
204 return GNUNET_SYSERR;
205 eta = 0;
206 if (upcb != NULL)
207 upcb (filesize, 0, eta, upcbClosure);
208 if (GNUNET_SYSERR == GNUNET_hash_file (ectx, filename, &fileId))
209 {
210 GNUNET_client_connection_destroy (sock);
211 GNUNET_GE_BREAK (ectx, 0);
212 return GNUNET_SYSERR;
213 }
214 now = GNUNET_get_time ();
215 eta = now + 2 * (now - start);
216 /* very rough estimate: GNUNET_hash reads once through the file,
217 we'll do that once more and write it. But of course
218 the second read may be cached, and we have the encryption,
219 so a factor of two is really, really just a rough estimate */
220 start = now;
221 /* reset the counter since the formula later does not
222 take the time for GNUNET_hash_file into account */
223 treedepth = GNUNET_ECRS_compute_depth (filesize);
224
225 /* Test if file is indexed! */
226 wasIndexed = GNUNET_FS_test_indexed (sock, &fileId);
227
228 fd = GNUNET_disk_file_open (ectx, filename, O_RDONLY | O_LARGEFILE);
229 if (fd == -1)
230 {
231 GNUNET_client_connection_destroy (sock);
232 return GNUNET_SYSERR;
233 }
234 dblock =
235 GNUNET_malloc (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
236 sizeof (GNUNET_EC_DBlock));
237 dblock->size =
238 htonl (sizeof (GNUNET_DatastoreValue) + GNUNET_ECRS_DBLOCK_SIZE +
239 sizeof (GNUNET_EC_DBlock));
240 dblock->anonymity_level = htonl (0);
241 dblock->priority = htonl (0);
242 dblock->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
243 dblock->expiration_time = GNUNET_htonll (0);
244 db = (GNUNET_EC_DBlock *) & dblock[1];
245 db->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
246 iblocks =
247 GNUNET_malloc (sizeof (GNUNET_DatastoreValue *) * (treedepth + 1));
248 for (i = 0; i <= treedepth; i++)
249 {
250 iblocks[i] =
251 GNUNET_malloc (sizeof (GNUNET_DatastoreValue) +
252 GNUNET_ECRS_IBLOCK_SIZE + sizeof (GNUNET_EC_DBlock));
253 iblocks[i]->size =
254 htonl (sizeof (GNUNET_DatastoreValue) + sizeof (GNUNET_EC_DBlock));
255 iblocks[i]->anonymity_level = htonl (0);
256 iblocks[i]->priority = htonl (0);
257 iblocks[i]->type = htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
258 iblocks[i]->expiration_time = GNUNET_htonll (0);
259 ((GNUNET_EC_DBlock *) & iblocks[i][1])->type =
260 htonl (GNUNET_ECRS_BLOCKTYPE_DATA);
261 }
262
263 pos = 0;
264 while (pos < filesize)
265 {
266 if (upcb != NULL)
267 upcb (filesize, pos, eta, upcbClosure);
268 if (tt != NULL)
269 if (GNUNET_OK != tt (ttClosure))
270 goto FAILURE;
271 size = GNUNET_ECRS_DBLOCK_SIZE;
272 if (size > filesize - pos)
273 {
274 size = filesize - pos;
275 memset (&db[1], 0, GNUNET_ECRS_DBLOCK_SIZE);
276 }
277 dblock->size =
278 htonl (sizeof (GNUNET_DatastoreValue) + size +
279 sizeof (GNUNET_EC_DBlock));
280 if (size != READ (fd, &db[1], size))
281 {
282 GNUNET_GE_LOG_STRERROR_FILE (ectx,
283 GNUNET_GE_ERROR | GNUNET_GE_USER |
284 GNUNET_GE_ADMIN | GNUNET_GE_BULK,
285 "READ", filename);
286 goto FAILURE;
287 }
288 if (tt != NULL)
289 if (GNUNET_OK != tt (ttClosure))
290 goto FAILURE;
291 GNUNET_EC_file_block_get_key (db, size + sizeof (GNUNET_EC_DBlock),
292 &chk.key);
293 GNUNET_EC_file_block_get_query (db, size + sizeof (GNUNET_EC_DBlock),
294 &chk.query);
295 if (GNUNET_OK != pushBlock (sock, &chk, 0, /* dblocks are on level 0 */
296 iblocks))
297 {
298 GNUNET_GE_BREAK (ectx, 0);
299 goto FAILURE;
300 }
301 if (!wasIndexed)
302 {
303 if (GNUNET_OK ==
304 GNUNET_EC_file_block_encode (db, size, &chk.query, &value))
305 {
306 *value = *dblock; /* copy options! */
307#if STRICT_CHECKS
308 if (GNUNET_OK != GNUNET_FS_delete (sock, value))
309 {
310 GNUNET_free (value);
311 GNUNET_GE_BREAK (ectx, 0);
312 goto FAILURE;
313 }
314#else
315 GNUNET_FS_delete (sock, value);
316#endif
317 GNUNET_free (value);
318 }
319 else
320 {
321 goto FAILURE;
322 }
323 }
324 pos += size;
325 now = GNUNET_get_time ();
326 eta = (GNUNET_CronTime) (start +
327 (((double) (now - start) / (double) pos))
328 * (double) filesize);
329 }
330 if (tt != NULL)
331 if (GNUNET_OK != tt (ttClosure))
332 goto FAILURE;
333 for (i = 0; i < treedepth; i++)
334 {
335 size = ntohl (iblocks[i]->size) - sizeof (GNUNET_DatastoreValue);
336 db = (GNUNET_EC_DBlock *) & iblocks[i][1];
337 GNUNET_EC_file_block_get_key (db, size, &chk.key);
338 GNUNET_EC_file_block_get_query (db, size, &chk.query);
339 if (GNUNET_OK != pushBlock (sock, &chk, i + 1, iblocks))
340 {
341 GNUNET_GE_BREAK (ectx, 0);
342 goto FAILURE;
343 }
344 GNUNET_EC_file_block_encode (db, size, &chk.query, &value);
345#if STRICT_CHECKS
346 if (GNUNET_OK != GNUNET_FS_delete (sock, value))
347 {
348 GNUNET_free (value);
349 GNUNET_GE_BREAK (ectx, 0);
350 goto FAILURE;
351 }
352#else
353 GNUNET_FS_delete (sock, value);
354#endif
355 GNUNET_free (value);
356 GNUNET_free (iblocks[i]);
357 iblocks[i] = NULL;
358 }
359
360 if (wasIndexed)
361 {
362 if (GNUNET_OK == undoSymlinking (ectx, filename, &fileId, sock))
363 {
364 if (GNUNET_OK !=
365 GNUNET_FS_unindex (sock, GNUNET_ECRS_DBLOCK_SIZE, &fileId))
366 {
367 GNUNET_GE_BREAK (ectx, 0);
368 goto FAILURE;
369 }
370 }
371 else
372 {
373 GNUNET_GE_BREAK (ectx, 0);
374 goto FAILURE;
375 }
376 }
377 GNUNET_free (iblocks[treedepth]);
378 /* free resources */
379 GNUNET_free (iblocks);
380 GNUNET_free (dblock);
381 CLOSE (fd);
382 GNUNET_client_connection_destroy (sock);
383 return GNUNET_OK;
384FAILURE:
385 for (i = 0; i <= treedepth; i++)
386 GNUNET_free_non_null (iblocks[i]);
387 GNUNET_free (iblocks);
388 GNUNET_free (dblock);
389 CLOSE (fd);
390 GNUNET_client_connection_destroy (sock);
391 return GNUNET_SYSERR;
392}
393
394/* end of unindex.c */
diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c
index f2351af1b..8e69a8425 100644
--- a/src/fs/fs_uri.c
+++ b/src/fs/fs_uri.c
@@ -26,10 +26,10 @@
26 * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER". 26 * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER".
27 * The specific structure of "IDENTIFIER" depends on the module and 27 * The specific structure of "IDENTIFIER" depends on the module and
28 * maybe differenciated into additional subcategories if applicable. 28 * maybe differenciated into additional subcategories if applicable.
29 * This module only deals with ecrs identifiers (MODULE = "ecrs"). 29 * This module only deals with fs identifiers (MODULE = "fs").
30 * <p> 30 * <p>
31 * 31 *
32 * This module only parses URIs for the AFS module. The ECRS URIs fall 32 * This module only parses URIs for the AFS module. The FS URIs fall
33 * into four categories, "chk", "sks", "ksk" and "loc". The first three 33 * into four categories, "chk", "sks", "ksk" and "loc". The first three
34 * categories were named in analogy (!) to Freenet, but they do NOT 34 * categories were named in analogy (!) to Freenet, but they do NOT
35 * work in exactly the same way. They are very similar from the user's 35 * work in exactly the same way. They are very similar from the user's
@@ -40,7 +40,7 @@
40 * <ul><li> 40 * <ul><li>
41 * 41 *
42 * First, there are URIs that identify a file. They have the format 42 * First, there are URIs that identify a file. They have the format
43 * "gnunet://ecrs/chk/HEX1.HEX2.SIZE". These URIs can be used to 43 * "gnunet://fs/chk/HEX1.HEX2.SIZE". These URIs can be used to
44 * download the file. The description, filename, mime-type and other 44 * download the file. The description, filename, mime-type and other
45 * meta-data is NOT part of the file-URI since a URI uniquely 45 * meta-data is NOT part of the file-URI since a URI uniquely
46 * identifies a resource (and the contents of the file would be the 46 * identifies a resource (and the contents of the file would be the
@@ -49,7 +49,7 @@
49 * </li><li> 49 * </li><li>
50 * 50 *
51 * The second category identifies entries in a namespace. The format 51 * The second category identifies entries in a namespace. The format
52 * is "gnunet://ecrs/sks/NAMESPACE/IDENTIFIER" where the namespace 52 * is "gnunet://fs/sks/NAMESPACE/IDENTIFIER" where the namespace
53 * should be given in HEX. Applications may allow using a nickname 53 * should be given in HEX. Applications may allow using a nickname
54 * for the namespace if the nickname is not ambiguous. The identifier 54 * for the namespace if the nickname is not ambiguous. The identifier
55 * can be either an ASCII sequence or a HEX-encoding. If the 55 * can be either an ASCII sequence or a HEX-encoding. If the
@@ -59,7 +59,7 @@
59 * </li> <li> 59 * </li> <li>
60 * 60 *
61 * The third category identifies ordinary searches. The format is 61 * The third category identifies ordinary searches. The format is
62 * "gnunet://ecrs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax 62 * "gnunet://fs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax
63 * it is possible to encode searches with the boolean "AND" operator. 63 * it is possible to encode searches with the boolean "AND" operator.
64 * "+" is used since it indicates a commutative 'and' operation and 64 * "+" is used since it indicates a commutative 'and' operation and
65 * is unlikely to be used in a keyword by itself. 65 * is unlikely to be used in a keyword by itself.
@@ -67,7 +67,7 @@
67 * </li><li> 67 * </li><li>
68 * 68 *
69 * The last category identifies a datum on a specific machine. The 69 * The last category identifies a datum on a specific machine. The
70 * format is "gnunet://ecrs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is 70 * format is "gnunet://fs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is
71 * the BinName of the public key of the peer storing the datum. The 71 * the BinName of the public key of the peer storing the datum. The
72 * signature (SIG) certifies that this peer has this content. 72 * signature (SIG) certifies that this peer has this content.
73 * HEX1, HEX2 and SIZE correspond to a 'chk' URI. 73 * HEX1, HEX2 and SIZE correspond to a 'chk' URI.
@@ -211,6 +211,7 @@ percent_decode_keyword (const char *in, char **emsg)
211 if (1 != sscanf (&out[rpos + 1], "%2X", &hx)) 211 if (1 != sscanf (&out[rpos + 1], "%2X", &hx))
212 { 212 {
213 GNUNET_free (out); 213 GNUNET_free (out);
214 *emsg = GNUNET_strdup (_("`%' must be followed by HEX number"));
214 return NULL; 215 return NULL;
215 } 216 }
216 rpos += 3; 217 rpos += 3;
@@ -265,11 +266,14 @@ uri_ksk_parse (const char *s, char **emsg)
265 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX); 266 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX);
266 if ( (slen <= pos) || 267 if ( (slen <= pos) ||
267 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX, 268 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX,
268 pos) ) || 269 pos) ) )
269 (s[slen - 1] == '+') || 270 return NULL; /* not KSK URI */
271 if ( (s[slen - 1] == '+') ||
270 (s[pos] == '+') ) 272 (s[pos] == '+') )
271 return NULL; /* no keywords / malformed */ 273 {
272 274 *emsg = GNUNET_strdup (_("Malformed KSK URI (must not begin or end with `+')"));
275 return NULL;
276 }
273 max = 1; 277 max = 1;
274 saw_quote = 0; 278 saw_quote = 0;
275 for (i = pos; i < slen; i++) 279 for (i = pos; i < slen; i++)
@@ -284,11 +288,17 @@ uri_ksk_parse (const char *s, char **emsg)
284 { 288 {
285 max++; 289 max++;
286 if (s[i - 1] == '+') 290 if (s[i - 1] == '+')
287 return NULL; /* "++" not allowed */ 291 {
292 *emsg = GNUNET_strdup (_("`++' not allowed in KSK URI"));
293 return NULL;
294 }
288 } 295 }
289 } 296 }
290 if (saw_quote == 1) 297 if (saw_quote == 1)
291 return NULL; /* quotes not balanced */ 298 {
299 *emsg = GNUNET_strdup (_("Quotes not balanced in KSK URI"));
300 return NULL;
301 }
292 iret = max; 302 iret = max;
293 dup = GNUNET_strdup (s); 303 dup = GNUNET_strdup (s);
294 keywords = GNUNET_malloc (max * sizeof (char *)); 304 keywords = GNUNET_malloc (max * sizeof (char *));
@@ -304,7 +314,7 @@ uri_ksk_parse (const char *s, char **emsg)
304 { 314 {
305 keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg); 315 keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg);
306 if (NULL == keywords[max]) 316 if (NULL == keywords[max])
307 goto CLEANUP; 317 goto CLEANUP;
308 dup[i] = '\0'; 318 dup[i] = '\0';
309 } 319 }
310 } 320 }
@@ -349,14 +359,21 @@ uri_sks_parse (const char *s, char **emsg)
349 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX); 359 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX);
350 if ( (slen <= pos) || 360 if ( (slen <= pos) ||
351 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX, 361 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX,
352 pos) ) || 362 pos) ) )
353 (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || 363 return NULL; /* not an SKS URI */
364 if ( (slen < pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
354 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/') ) 365 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '/') )
355 return NULL; 366 {
367 *emsg = GNUNET_strdup (_("Malformed SKS URI"));
368 return NULL;
369 }
356 memcpy (enc, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); 370 memcpy (enc, &s[pos], sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
357 enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0'; 371 enc[sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)-1] = '\0';
358 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace)) 372 if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (enc, &namespace))
359 return NULL; 373 {
374 *emsg = GNUNET_strdup (_("Malformed SKS URI"));
375 return NULL;
376 }
360 identifier = GNUNET_strdup (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]); 377 identifier = GNUNET_strdup (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]);
361 ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); 378 ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
362 ret->type = sks; 379 ret->type = sks;
@@ -389,11 +406,14 @@ uri_chk_parse (const char *s, char **emsg)
389 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX); 406 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX);
390 if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || 407 if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
391 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX, 408 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX,
392 pos) ) || 409 pos) ) )
393 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || 410 return NULL; /* not a CHK URI */
411 if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
394 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') ) 412 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') )
395 return NULL; 413 {
396 414 *emsg = GNUNET_strdup (_("Malformed CHK URI"));
415 return NULL;
416 }
397 memcpy (h1, 417 memcpy (h1,
398 &s[pos], 418 &s[pos],
399 sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); 419 sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
@@ -410,9 +430,11 @@ uri_chk_parse (const char *s, char **emsg)
410 (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], 430 (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
411 "%llu", 431 "%llu",
412 &fi.file_length))) 432 &fi.file_length)))
413 return NULL; 433 {
434 *emsg = GNUNET_strdup (_("Malformed CHK URI"));
435 return NULL;
436 }
414 fi.file_length = GNUNET_htonll (fi.file_length); 437 fi.file_length = GNUNET_htonll (fi.file_length);
415
416 ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); 438 ret = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
417 ret->type = chk; 439 ret->type = chk;
418 ret->data.chk = fi; 440 ret->data.chk = fi;
@@ -527,18 +549,20 @@ uri_loc_parse (const char *s, char **emsg)
527 struct LocUriAssembly ass; 549 struct LocUriAssembly ass;
528 int ret; 550 int ret;
529 size_t slen; 551 size_t slen;
530 char *addr;
531 552
532 GNUNET_assert (s != NULL); 553 GNUNET_assert (s != NULL);
533 slen = strlen (s); 554 slen = strlen (s);
534 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX); 555 pos = strlen (GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX);
535 if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || 556 if ( (slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) ||
536 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX, 557 (0 != strncmp (s, GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX,
537 pos) ) || 558 pos) ) )
538 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || 559 return NULL; /* not an SKS URI */
560 if ( (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') ||
539 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') ) 561 (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.') )
540 return NULL; 562 {
541 563 *emsg = GNUNET_strdup (_("SKS URI malformed"));
564 return NULL;
565 }
542 memcpy (h1, 566 memcpy (h1,
543 &s[pos], 567 &s[pos],
544 sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded)); 568 sizeof(struct GNUNET_CRYPTO_HashAsciiEncoded));
@@ -555,32 +579,54 @@ uri_loc_parse (const char *s, char **emsg)
555 (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], 579 (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2],
556 "%llu", 580 "%llu",
557 &ass.fi.file_length)) ) 581 &ass.fi.file_length)) )
558 return NULL; 582 {
583 *emsg = GNUNET_strdup (_("SKS URI malformed"));
584 return NULL;
585 }
559 ass.fi.file_length = GNUNET_htonll (ass.fi.file_length); 586 ass.fi.file_length = GNUNET_htonll (ass.fi.file_length);
560 587
561 npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2; 588 npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2;
562 while ((s[npos] != '\0') && (s[npos] != '.')) 589 while ((s[npos] != '\0') && (s[npos] != '.'))
563 npos++; 590 npos++;
564 if (s[npos] == '\0') 591 if (s[npos] == '\0')
565 goto ERR; 592 {
593 *emsg = GNUNET_strdup (_("SKS URI malformed"));
594 goto ERR;
595 }
596 npos++;
566 ret = enc2bin (&s[npos], 597 ret = enc2bin (&s[npos],
567 &ass.peer, 598 &ass.peer,
568 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); 599 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
569 if (ret == -1) 600 if (ret == -1)
570 goto ERR; 601 {
602 *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode public key)"));
603 goto ERR;
604 }
571 npos += ret; 605 npos += ret;
572 if (s[npos++] != '.') 606 if (s[npos++] != '.')
573 goto ERR; 607 {
608 *emsg = GNUNET_strdup (_("SKS URI malformed (could not find signature)"));
609 goto ERR;
610 }
574 ret = enc2bin (&s[npos], 611 ret = enc2bin (&s[npos],
575 &sig, 612 &sig,
576 sizeof (struct GNUNET_CRYPTO_RsaSignature)); 613 sizeof (struct GNUNET_CRYPTO_RsaSignature));
577 if (ret == -1) 614 if (ret == -1)
578 goto ERR; 615 {
579 npos += ret; 616 *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode signature)"));
617 goto ERR;
618 }
619 npos += ret;
580 if (s[npos++] != '.') 620 if (s[npos++] != '.')
581 goto ERR; 621 {
622 *emsg = GNUNET_strdup (_("SKS URI malformed"));
623 goto ERR;
624 }
582 if (1 != SSCANF (&s[npos], "%llu", &exptime)) 625 if (1 != SSCANF (&s[npos], "%llu", &exptime))
583 goto ERR; 626 {
627 *emsg = GNUNET_strdup (_("SKS URI malformed (could not parse expiration time)"));
628 goto ERR;
629 }
584 ass.purpose.size = htonl(sizeof(struct LocUriAssembly)); 630 ass.purpose.size = htonl(sizeof(struct LocUriAssembly));
585 ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_NAMESPACE_PLACEMENT); 631 ass.purpose.purpose = htonl(GNUNET_SIGNATURE_PURPOSE_NAMESPACE_PLACEMENT);
586 et.value = exptime; 632 et.value = exptime;
@@ -590,8 +636,10 @@ uri_loc_parse (const char *s, char **emsg)
590 &ass.purpose, 636 &ass.purpose,
591 &sig, 637 &sig,
592 &ass.peer)) 638 &ass.peer))
593 goto ERR; 639 {
594 640 *emsg = GNUNET_strdup (_("SKS URI malformed (signature failed validation)"));
641 goto ERR;
642 }
595 uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri)); 643 uri = GNUNET_malloc (sizeof(struct GNUNET_FS_Uri));
596 uri->type = loc; 644 uri->type = loc;
597 uri->data.loc.fi = ass.fi; 645 uri->data.loc.fi = ass.fi;
@@ -601,7 +649,6 @@ uri_loc_parse (const char *s, char **emsg)
601 649
602 return uri; 650 return uri;
603ERR: 651ERR:
604 GNUNET_free_non_null (addr);
605 return NULL; 652 return NULL;
606} 653}
607 654
@@ -618,12 +665,20 @@ GNUNET_FS_uri_parse (const char *uri,
618 char **emsg) 665 char **emsg)
619{ 666{
620 struct GNUNET_FS_Uri *ret; 667 struct GNUNET_FS_Uri *ret;
668 char *msg;
621 669
670 if (NULL == emsg)
671 emsg = &msg;
672 *emsg = NULL;
622 if ( (NULL != (ret = uri_chk_parse (uri, emsg))) || 673 if ( (NULL != (ret = uri_chk_parse (uri, emsg))) ||
623 (NULL != (ret = uri_ksk_parse (uri, emsg))) || 674 (NULL != (ret = uri_ksk_parse (uri, emsg))) ||
624 (NULL != (ret = uri_sks_parse (uri, emsg))) || 675 (NULL != (ret = uri_sks_parse (uri, emsg))) ||
625 (NULL != (ret = uri_loc_parse (uri, emsg))) ) 676 (NULL != (ret = uri_loc_parse (uri, emsg))) )
626 return ret; 677 return ret;
678 if (NULL == *emsg)
679 *emsg = GNUNET_strdup (_("Unrecognized URI type"));
680 if (emsg == &msg)
681 GNUNET_free (msg);
627 return NULL; 682 return NULL;
628} 683}
629 684
diff --git a/src/fs/test_fs_collection.c b/src/fs/test_fs_collection.c
index 421cb5060..6857dfc25 100644
--- a/src/fs/test_fs_collection.c
+++ b/src/fs/test_fs_collection.c
@@ -28,75 +28,87 @@
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29#include "gnunet_fs_service.h" 29#include "gnunet_fs_service.h"
30 30
31#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_break(0); goto FAILURE; } 31static struct GNUNET_CONFIGURATION_Handle *cfg;
32 32
33int 33static void* progress_cb (void *cls,
34main (int argc, char *argv[]) 34 const struct GNUNET_FS_ProgressInfo *info)
35{ 35{
36 struct GNUNET_CONFIGURATION_Handle *cfg; 36 GNUNET_break (0);
37 int ok; 37 return NULL;
38 struct GNUNET_ClientServerConnection *sock; 38}
39 struct GNUNET_CONTAINER_MetaData *meta; 39
40 struct GNUNET_CONTAINER_MetaData *have; 40
41static void
42task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
43{
44 struct GNUNET_FS_Namespace *have;
45 struct GNUNET_FS_Namespace *ns;
41 char *emsg; 46 char *emsg;
42 struct GNUNET_FS_Uri *uri; 47 struct GNUNET_FS_Uri *uri;
43 struct GNUNET_CONTAINER_MetaData *md;
44 struct GNUNET_FS_Handle *fsh; 48 struct GNUNET_FS_Handle *fsh;
49 struct GNUNET_CONTAINER_MetaData *md;
45 50
46 GNUNET_CRYPTO_random_disable_entropy_gathering (); 51 fsh = GNUNET_FS_start (tc->sched,
47 cfg = GNUNET_CONFIGURATION_create ();
48 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (cfg, "check.conf"))
49 {
50 GNUNET_CONFIGURATION_destroy (cfg);
51 return -1;
52 }
53 sock = NULL;
54 meta = NULL;
55 ok = GNUNET_YES;
56 meta = GNUNET_CONTAINER_meta_data_create ();
57 GNUNET_CONTAINER_meta_data_insert (meta, EXTRACTOR_MIMETYPE, "test/foo");
58
59
60 fsh = GNUNET_FS_start (sched,
61 cfg, 52 cfg,
62 "test-fs-collection", 53 "test-fs-collection",
63 &progress_cb, 54 &progress_cb,
64 NULL); 55 NULL);
65 56 GNUNET_assert (NULL != fsh);
66 /* ACTUAL TEST CODE */
67 GNUNET_FS_collection_stop (fsh); 57 GNUNET_FS_collection_stop (fsh);
68 CHECK (NULL == GNUNET_FS_collection_get (fsh)); 58 GNUNET_assert (NULL == GNUNET_FS_collection_get (fsh));
69 CHECK (GNUNET_OK == GNUNET_FS_collection_start (fsh, 59 ns = GNUNET_FS_namespace_create (fsh, "test-namespace");
70 namespace)); 60 GNUNET_assert (NULL != ns);
61 GNUNET_assert (GNUNET_OK == GNUNET_FS_collection_start (fsh,
62 ns));
63 GNUNET_FS_namespace_delete (ns, GNUNET_NO);
71 have = GNUNET_FS_collection_get (fsh); 64 have = GNUNET_FS_collection_get (fsh);
72 CHECK (NULL != have); 65 GNUNET_assert (NULL != have);
73 CHECK (GNUNET_CONTAINER_meta_data_test_equal (have, meta)); 66 GNUNET_FS_namespace_delete (have, GNUNET_NO);
74 GNUNET_CONTAINER_meta_data_destroy (have);
75 md = meta;
76 uri = 67 uri =
77 GNUNET_FS_uri_parse ("gnunet://ecrs/chk/0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", &emsg); 68 GNUNET_FS_uri_parse ("gnunet://fs/chk/0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", &emsg);
69 GNUNET_assert (NULL != uri);
70 md = GNUNET_CONTAINER_meta_data_create ();
78 GNUNET_FS_collection_add (fsh, uri, md); 71 GNUNET_FS_collection_add (fsh, uri, md);
72 GNUNET_CONTAINER_meta_data_destroy (md);
79 GNUNET_FS_uri_destroy (uri); 73 GNUNET_FS_uri_destroy (uri);
80 GNUNET_FS_stop (fsh); 74 GNUNET_FS_stop (fsh);
81 fsh = GNUNET_FS_start (sched, cfg, 75 fsh = GNUNET_FS_start (tc->sched,
76 cfg,
82 "test-fs-collection", 77 "test-fs-collection",
83 &progress_cb, 78 &progress_cb,
84 NULL); 79 NULL);
85 have = GNUNET_FS_collection_get (fsh); 80 have = GNUNET_FS_collection_get (fsh);
86 CHECK (NULL != have); 81 GNUNET_assert (NULL != have);
87 CHECK (GNUNET_CONTAINER_meta_data_test_equal (have, meta)); 82 GNUNET_FS_namespace_delete (have, GNUNET_NO);
88 GNUNET_CONTAINER_meta_data_destroy (have);
89 GNUNET_FS_collection_publish (fsh); 83 GNUNET_FS_collection_publish (fsh);
90 GNUNET_FS_collection_stop (fsh); 84 GNUNET_FS_collection_stop (fsh);
91 CHECK (NULL == GNUNET_FS_collection_get (fsh)); 85 GNUNET_assert (NULL == GNUNET_FS_collection_get (fsh));
92 GNUNET_FS_stop (fsh); 86 GNUNET_FS_stop (fsh);
87}
88
93 89
94 /* END OF TEST CODE */ 90int
95FAILURE: 91main (int argc, char *argv[])
96 if (meta != NULL) 92{
97 GNUNET_CONTAINER_meta_data_destroy (meta); 93 int ok;
94
95 GNUNET_log_setup ("test_fs_collection",
96#if VERBOSE
97 "DEBUG",
98#else
99 "WARNING",
100#endif
101 NULL);
102 GNUNET_CRYPTO_random_disable_entropy_gathering ();
103 cfg = GNUNET_CONFIGURATION_create ();
104 if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (cfg, "test_fs_collection_data.conf"))
105 {
106 GNUNET_CONFIGURATION_destroy (cfg);
107 return -1;
108 }
109 ok = GNUNET_YES;
110 GNUNET_SCHEDULER_run (&task, &ok);
98 GNUNET_CONFIGURATION_destroy (cfg); 111 GNUNET_CONFIGURATION_destroy (cfg);
99
100 return (ok == GNUNET_YES) ? 0 : 1; 112 return (ok == GNUNET_YES) ? 0 : 1;
101} 113}
102 114
diff --git a/src/fs/test_fs_collection_data.conf b/src/fs/test_fs_collection_data.conf
new file mode 100644
index 000000000..12cf53b93
--- /dev/null
+++ b/src/fs/test_fs_collection_data.conf
@@ -0,0 +1,9 @@
1[PATHS]
2SERVICEHOME = /tmp/gnunet-test-fs-uri/
3DEFAULTCONFIG = /etc/gnunetd.conf
4
5[gnunetd]
6HOSTKEY = $SERVICEHOME/.hostkey
7
8[TESTING]
9WEAKRANDOM = YES
diff --git a/src/fs/test_fs_directory.c b/src/fs/test_fs_directory.c
index d643e6ed9..22dfa22cf 100644
--- a/src/fs/test_fs_directory.c
+++ b/src/fs/test_fs_directory.c
@@ -152,6 +152,13 @@ main (int argc, char *argv[])
152 int failureCount = 0; 152 int failureCount = 0;
153 int i; 153 int i;
154 154
155 GNUNET_log_setup ("test_fs_directory",
156#if VERBOSE
157 "DEBUG",
158#else
159 "WARNING",
160#endif
161 NULL);
155 for (i = 17; i < 2000; i *= 2) 162 for (i = 17; i < 2000; i *= 2)
156 { 163 {
157 fprintf (stderr, "."); 164 fprintf (stderr, ".");
diff --git a/src/fs/test_fs_download.c b/src/fs/test_fs_download.c
new file mode 100644
index 000000000..302dfaaa2
--- /dev/null
+++ b/src/fs/test_fs_download.c
@@ -0,0 +1,324 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/fsui/download_persistence_test.c
23 * @brief testcase for fsui download persistence (upload-download)
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "gnunet_fsui_lib.h"
30
31#define DEBUG_VERBOSE GNUNET_NO
32
33#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto FAILURE; }
34
35static volatile int suspendRestart = 0;
36
37static struct GNUNET_GE_Context *ectx;
38
39static char *
40makeName (unsigned int i)
41{
42 char *fn;
43
44 fn =
45 GNUNET_malloc (strlen
46 ("/tmp/gnunet-fsui-download_persistence_test/FSUITEST") +
47 14);
48 GNUNET_snprintf (fn,
49 strlen
50 ("/tmp/gnunet-fsui-download_persistence_test/FSUITEST") +
51 14,
52 "/tmp/gnunet-fsui-download_persistence_test/FSUITEST%u",
53 i);
54 GNUNET_disk_directory_create_for_file (NULL, fn);
55 return fn;
56}
57
58static volatile enum GNUNET_FSUI_EventType lastEvent;
59static volatile enum GNUNET_FSUI_EventType waitForEvent;
60static volatile int download_done;
61static struct GNUNET_FSUI_Context *ctx;
62static struct GNUNET_ECRS_URI *upURI;
63static struct GNUNET_FSUI_DownloadList *download;
64
65static void *
66eventCallback (void *cls, const GNUNET_FSUI_Event * event)
67{
68 switch (event->type)
69 {
70 case GNUNET_FSUI_download_suspended:
71 download = NULL;
72 break;
73 case GNUNET_FSUI_download_resumed:
74#if DEBUG_VERBOSE
75 printf ("Download resuming\n");
76#endif
77 download = event->data.DownloadResumed.dc.pos;
78 break;
79 case GNUNET_FSUI_upload_progress:
80#if DEBUG_VERBOSE > 1
81 printf ("Upload is progressing (%llu/%llu)...\n",
82 event->data.UploadProgress.completed,
83 event->data.UploadProgress.total);
84#endif
85 break;
86 case GNUNET_FSUI_upload_completed:
87 upURI = GNUNET_ECRS_uri_duplicate (event->data.UploadCompleted.uri);
88#if DEBUG_VERBOSE
89 printf ("Upload complete.\n");
90#endif
91 break;
92 case GNUNET_FSUI_download_completed:
93#if DEBUG_VERBOSE
94 printf ("Download complete.\n");
95#endif
96 download_done = 1;
97 break;
98 case GNUNET_FSUI_download_progress:
99#if DEBUG_VERBOSE > 1
100 printf ("Download is progressing (%llu/%llu)...\n",
101 event->data.DownloadProgress.completed,
102 event->data.DownloadProgress.total);
103#endif
104 break;
105 case GNUNET_FSUI_unindex_progress:
106#if DEBUG_VERBOSE > 1
107 printf ("Unindex is progressing (%llu/%llu)...\n",
108 event->data.UnindexProgress.completed,
109 event->data.UnindexProgress.total);
110#endif
111 break;
112 case GNUNET_FSUI_unindex_completed:
113#if DEBUG_VERBOSE
114 printf ("Unindex complete.\n");
115#endif
116 break;
117 case GNUNET_FSUI_unindex_error:
118 case GNUNET_FSUI_upload_error:
119 case GNUNET_FSUI_download_error:
120 fprintf (stderr, "Received ERROR: %d\n", event->type);
121 GNUNET_GE_BREAK (ectx, 0);
122 break;
123 case GNUNET_FSUI_download_aborted:
124#if DEBUG_VERBOSE
125 printf ("Received download aborted event.\n");
126#endif
127 break;
128 case GNUNET_FSUI_unindex_suspended:
129 case GNUNET_FSUI_upload_suspended:
130#if DEBUG_VERBOSE
131 fprintf (stderr, "Received SUSPENDING: %d\n", event->type);
132#endif
133 break;
134 case GNUNET_FSUI_upload_started:
135 case GNUNET_FSUI_upload_stopped:
136 case GNUNET_FSUI_download_started:
137 case GNUNET_FSUI_download_stopped:
138 case GNUNET_FSUI_unindex_started:
139 case GNUNET_FSUI_unindex_stopped:
140 break;
141 default:
142 printf ("Unexpected event: %d\n", event->type);
143 break;
144 }
145 if (lastEvent == waitForEvent)
146 return NULL; /* ignore all other events */
147 lastEvent = event->type;
148 return NULL;
149}
150
151#define FILESIZE (1024 * 1024 * 2)
152
153#define START_DAEMON 1
154
155int
156main (int argc, char *argv[])
157{
158#if START_DAEMON
159 pid_t daemon;
160#endif
161 int ok;
162 int i;
163 char *fn = NULL;
164 char *keywords[] = {
165 "down_foo",
166 "down_bar",
167 };
168 int prog;
169 char *buf;
170 struct GNUNET_MetaData *meta = NULL;
171 struct GNUNET_ECRS_URI *kuri = NULL;
172 struct GNUNET_GC_Configuration *cfg;
173 struct GNUNET_FSUI_UnindexList *unindex = NULL;
174 struct GNUNET_FSUI_UploadList *upload = NULL;
175
176 ok = GNUNET_YES;
177 cfg = GNUNET_GC_create ();
178 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
179 {
180 GNUNET_GC_free (cfg);
181 return -1;
182 }
183#if START_DAEMON
184 GNUNET_disk_directory_remove (NULL,
185 "/tmp/gnunet-fsui-download_persistence_test/");
186 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
187 GNUNET_GE_ASSERT (NULL, daemon > 0);
188 CHECK (GNUNET_OK ==
189 GNUNET_wait_for_daemon_running (NULL, cfg,
190 30 * GNUNET_CRON_SECONDS));
191 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to start */
192 /* ACTUAL TEST CODE */
193#endif
194 ctx = GNUNET_FSUI_start (NULL,
195 cfg, "fsuidownload_persistence_test", 32,
196 GNUNET_YES, &eventCallback, NULL);
197 CHECK (ctx != NULL);
198
199 /* upload */
200 fn = makeName (42);
201 buf = GNUNET_malloc (FILESIZE);
202 for (i = 0; i < FILESIZE; i++)
203 buf[i] = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 256);
204 GNUNET_disk_file_write (ectx, fn, buf, FILESIZE, "600");
205 GNUNET_free (buf);
206 meta = GNUNET_meta_data_create ();
207 kuri =
208 GNUNET_ECRS_keyword_command_line_to_uri (ectx, 2,
209 (const char **) keywords);
210 waitForEvent = GNUNET_FSUI_upload_completed;
211 upload = GNUNET_FSUI_upload_start (ctx,
212 fn,
213 (GNUNET_FSUI_DirectoryScanCallback) &
214 GNUNET_disk_directory_scan, NULL, 0, 0,
215 GNUNET_YES, GNUNET_NO, GNUNET_NO,
216 GNUNET_get_time () +
217 5 * GNUNET_CRON_HOURS, meta, kuri, kuri);
218 CHECK (upload != NULL);
219 GNUNET_ECRS_uri_destroy (kuri);
220 kuri = NULL;
221 prog = 0;
222 while (lastEvent != GNUNET_FSUI_upload_completed)
223 {
224 prog++;
225 CHECK (prog < 5000);
226 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
227 if (GNUNET_shutdown_test () == GNUNET_YES)
228 break;
229 }
230 GNUNET_FSUI_upload_stop (upload);
231
232 /* download */
233 waitForEvent = GNUNET_FSUI_download_completed;
234 GNUNET_free (fn);
235 fn = makeName (43);
236 download_done = 0;
237 download = GNUNET_FSUI_download_start (ctx,
238 0,
239 GNUNET_NO,
240 upURI, meta, fn, NULL, NULL);
241 CHECK (download != NULL);
242 GNUNET_free (fn);
243 suspendRestart = 4;
244 prog = 0;
245 while (download_done == 0)
246 {
247 prog++;
248 CHECK (prog < 1000);
249 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
250 if ((suspendRestart > 0)
251 && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 4) == 0))
252 {
253#if 1
254#if DEBUG_VERBOSE
255 printf ("Testing FSUI suspend-resume\n");
256#endif
257 GNUNET_FSUI_stop (ctx); /* download possibly incomplete
258 at this point, thus testing resume */
259 ctx = GNUNET_FSUI_start (NULL,
260 cfg,
261 "fsuidownload_persistence_test",
262 32, GNUNET_YES, &eventCallback, NULL);
263#if DEBUG_VERBOSE
264 printf ("Resumed...\n");
265#endif
266#endif
267 suspendRestart--;
268 }
269 if (GNUNET_shutdown_test () == GNUNET_YES)
270 break;
271 }
272 GNUNET_FSUI_download_stop (download);
273 download = NULL;
274
275 /* unindex */
276 waitForEvent = GNUNET_FSUI_unindex_completed;
277 fn = makeName (42);
278 unindex = GNUNET_FSUI_unindex_start (ctx, fn);
279 CHECK (unindex != NULL);
280 prog = 0;
281 while (lastEvent != GNUNET_FSUI_unindex_completed)
282 {
283 prog++;
284 CHECK (prog < 5000);
285 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
286 CHECK (lastEvent != GNUNET_FSUI_unindex_error);
287 if (GNUNET_shutdown_test () == GNUNET_YES)
288 break;
289 }
290 CHECK (lastEvent == GNUNET_FSUI_unindex_completed);
291 /* END OF TEST CODE */
292FAILURE:
293 if (meta != NULL)
294 GNUNET_meta_data_destroy (meta);
295 if (ctx != NULL)
296 {
297 if (unindex != NULL)
298 GNUNET_FSUI_unindex_stop (unindex);
299 if (download != NULL)
300 GNUNET_FSUI_download_stop (download);
301 GNUNET_FSUI_stop (ctx);
302 }
303 if (fn != NULL)
304 {
305 UNLINK (fn);
306 GNUNET_free (fn);
307 }
308 if (kuri != NULL)
309 GNUNET_ECRS_uri_destroy (kuri);
310 fn = makeName (43);
311 /* TODO: verify file 'fn(42)' == file 'fn(43)' */
312 UNLINK (fn);
313 GNUNET_free (fn);
314 if (upURI != NULL)
315 GNUNET_ECRS_uri_destroy (upURI);
316
317#if START_DAEMON
318 GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
319#endif
320 GNUNET_GC_free (cfg);
321 return (ok == GNUNET_YES) ? 0 : 1;
322}
323
324/* end of download_persistence_test.c */
diff --git a/src/fs/test_fs_download_recursive.c b/src/fs/test_fs_download_recursive.c
new file mode 100644
index 000000000..dd8b73e6a
--- /dev/null
+++ b/src/fs/test_fs_download_recursive.c
@@ -0,0 +1,380 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/fsui/recursive_download_test.c
23 * @brief testcase for fsui recursive upload-download
24 * @author Christian Grothoff
25 * @author Heikki Lindholm
26 */
27
28#include "platform.h"
29#include "gnunet_util.h"
30#include "gnunet_fsui_lib.h"
31
32#define DEBUG_VERBOSE GNUNET_NO
33
34#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto FAILURE; }
35
36#define FILESIZE (1024 * 1024 * 2)
37/* depth-first directory tree d=dir f=file .=end of level*/
38#define DIRECTORY_TREE_SPEC "dddf.f.d"
39
40static struct GNUNET_GE_Context *ectx;
41
42volatile int download_done;
43
44static char *
45makeName (unsigned int i)
46{
47 char *fn;
48
49 fn =
50 GNUNET_malloc (strlen
51 ("/tmp/gnunet-fsui-recursive_download_test/FSUITEST") +
52 15);
53 GNUNET_snprintf (fn,
54 strlen
55 ("/tmp/gnunet-fsui-recursive_download_test/FSUITEST") + 15,
56 "/tmp/gnunet-fsui-recursive_download_test/FSUITEST%u/", i);
57 return fn;
58}
59
60static int
61makeHierarchyHelper (const char *current, const char *tree, int index,
62 int check)
63{
64 unsigned int fi, i;
65 int done;
66 char *s, *buf;
67
68 fi = 0;
69 done = 0;
70 while (!done && tree[index] != '\0')
71 {
72 s = GNUNET_malloc (strlen (current) + strlen (DIR_SEPARATOR_STR) + 14);
73 GNUNET_snprintf (s, strlen (current) + strlen (DIR_SEPARATOR_STR) + 14,
74 "%s%s%u", current, DIR_SEPARATOR_STR, fi);
75 switch (tree[index++])
76 {
77 case 'd':
78 if (check)
79 {
80 if (GNUNET_disk_directory_test (NULL, s) == GNUNET_NO)
81 {
82 index = -1;
83 done = 1;
84 }
85 }
86 else
87 {
88 GNUNET_disk_directory_create (NULL, s);
89 }
90 if (!done)
91 index = makeHierarchyHelper (s, tree, index, check);
92 break;
93 case 'f':
94 if (check)
95 {
96 /* TODO: compare file contents */
97 if (GNUNET_disk_directory_test (NULL, s) != GNUNET_NO)
98 {
99 index = -1;
100 done = 1;
101 }
102 }
103 else
104 {
105 buf = GNUNET_malloc (FILESIZE);
106 for (i = 0; i < FILESIZE; i++)
107 buf[i] = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 256);
108 GNUNET_disk_file_write (ectx, s, buf, FILESIZE, "600");
109 GNUNET_free (buf);
110 }
111 break;
112 case '.':
113 done = 1;
114 break;
115 default:
116 break;
117 }
118 GNUNET_free (s);
119 fi++;
120 }
121 return index;
122}
123
124static char *
125makeHierarchy (unsigned int i, const char *tree)
126{
127 char *fn;
128
129 fn = makeName (i);
130 makeHierarchyHelper (fn, tree, 0, 0);
131 return fn;
132}
133
134static int
135checkHierarchy (unsigned int i, const char *tree)
136{
137 char *fn;
138 int res;
139
140 fn = makeName (i);
141 if (GNUNET_disk_directory_test (NULL, fn) != GNUNET_YES)
142 {
143 GNUNET_free (fn);
144 return GNUNET_SYSERR;
145 }
146 res = ((makeHierarchyHelper (fn, tree, 0, 1) == -1) ?
147 GNUNET_SYSERR : GNUNET_OK);
148 GNUNET_free (fn);
149 return res;
150}
151
152
153static volatile enum GNUNET_FSUI_EventType lastEvent;
154static volatile enum GNUNET_FSUI_EventType waitForEvent;
155static struct GNUNET_FSUI_Context *ctx;
156static struct GNUNET_ECRS_URI *upURI;
157static struct GNUNET_FSUI_DownloadList *download;
158
159static void *
160eventCallback (void *cls, const GNUNET_FSUI_Event * event)
161{
162 switch (event->type)
163 {
164 case GNUNET_FSUI_download_suspended:
165 download = NULL;
166 break;
167 case GNUNET_FSUI_download_resumed:
168 download = event->data.DownloadResumed.dc.pos;
169 break;
170 break;
171 case GNUNET_FSUI_upload_progress:
172#if DEBUG_VERBOSE > 1
173 printf ("Upload is progressing (%llu/%llu)...\n",
174 event->data.UploadProgress.completed,
175 event->data.UploadProgress.total);
176#endif
177 break;
178 case GNUNET_FSUI_upload_completed:
179 upURI = GNUNET_ECRS_uri_duplicate (event->data.UploadCompleted.uri);
180#if DEBUG_VERBOSE
181 printf ("Upload of `%s' complete.\n",
182 event->data.UploadCompleted.filename);
183#endif
184 break;
185 case GNUNET_FSUI_download_completed:
186#if DEBUG_VERBOSE
187 printf ("Download of `%s' complete.\n",
188 event->data.DownloadCompleted.filename);
189#endif
190 if (checkHierarchy (43, DIRECTORY_TREE_SPEC) == GNUNET_OK)
191 download_done = 1;
192#if DEBUG_VERBOSE
193 else
194 printf ("Hierarchy check not successful yet...\n");
195#endif
196 break;
197 case GNUNET_FSUI_download_progress:
198#if DEBUG_VERBOSE > 1
199 printf ("Download is progressing (%llu/%llu)...\n",
200 event->data.DownloadProgress.completed,
201 event->data.DownloadProgress.total);
202#endif
203 break;
204 case GNUNET_FSUI_unindex_progress:
205#if DEBUG_VERBOSE > 1
206 printf ("Unindex is progressing (%llu/%llu)...\n",
207 event->data.UnindexProgress.completed,
208 event->data.UnindexProgress.total);
209#endif
210 break;
211 case GNUNET_FSUI_unindex_completed:
212#if DEBUG_VERBOSE
213 printf ("Unindex complete.\n");
214#endif
215 break;
216 case GNUNET_FSUI_unindex_error:
217 fprintf (stderr, "Error unindexing: %s\n",
218 event->data.UnindexError.message);
219 break;
220 case GNUNET_FSUI_upload_error:
221 fprintf (stderr, "Error uploading: %s\n",
222 event->data.UploadError.message);
223 break;
224 case GNUNET_FSUI_download_error:
225 fprintf (stderr, "Error downloading: %s\n",
226 event->data.DownloadError.message);
227 break;
228 case GNUNET_FSUI_download_aborted:
229#if DEBUG_VERBOSE
230 printf ("Received download aborted event.\n");
231#endif
232 break;
233 case GNUNET_FSUI_unindex_suspended:
234 case GNUNET_FSUI_upload_suspended:
235 case GNUNET_FSUI_upload_started:
236 case GNUNET_FSUI_upload_stopped:
237 case GNUNET_FSUI_download_started:
238 case GNUNET_FSUI_download_stopped:
239 case GNUNET_FSUI_unindex_started:
240 case GNUNET_FSUI_unindex_stopped:
241 break;
242 default:
243 printf ("Unexpected event: %d\n", event->type);
244 break;
245 }
246 if (lastEvent == waitForEvent)
247 return NULL; /* ignore all other events */
248 lastEvent = event->type;
249 return NULL;
250}
251
252
253#define START_DAEMON 1
254
255int
256main (int argc, char *argv[])
257{
258#if START_DAEMON
259 pid_t daemon;
260#endif
261 int ok;
262 char *fn = NULL;
263 char *fn43 = NULL;
264 char *keywords[] = {
265 "down_foo",
266 "down_bar",
267 };
268 int prog;
269 struct GNUNET_MetaData *meta = NULL;
270 struct GNUNET_ECRS_URI *kuri = NULL;
271 struct GNUNET_GC_Configuration *cfg;
272 struct GNUNET_FSUI_UploadList *upload = NULL;
273
274 ok = GNUNET_YES;
275 cfg = GNUNET_GC_create ();
276 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
277 {
278 GNUNET_GC_free (cfg);
279 return -1;
280 }
281 fprintf(stderr,
282 "Setup...\n");
283#if START_DAEMON
284 GNUNET_disk_directory_remove (NULL,
285 "/tmp/gnunet-fsui-recursive_download_test/");
286 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
287 GNUNET_GE_ASSERT (NULL, daemon > 0);
288 CHECK (GNUNET_OK ==
289 GNUNET_wait_for_daemon_running (NULL, cfg,
290 30 * GNUNET_CRON_SECONDS));
291 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to start */
292 /* ACTUAL TEST CODE */
293#endif
294 ctx = GNUNET_FSUI_start (NULL,
295 cfg, "fsuirecursive_download_test", 32, GNUNET_YES,
296 &eventCallback, NULL);
297 CHECK (ctx != NULL);
298 fn = makeHierarchy (42, DIRECTORY_TREE_SPEC);
299 meta = GNUNET_meta_data_create ();
300 kuri =
301 GNUNET_ECRS_keyword_command_line_to_uri (ectx, 2,
302 (const char **) keywords);
303 fprintf(stderr,
304 "Uploading...\n");
305 waitForEvent = GNUNET_FSUI_upload_completed;
306 upload = GNUNET_FSUI_upload_start (ctx,
307 fn,
308 (GNUNET_FSUI_DirectoryScanCallback) &
309 GNUNET_disk_directory_scan, NULL, 0, 0,
310 GNUNET_YES, GNUNET_NO, GNUNET_NO,
311 GNUNET_get_time () +
312 5 * GNUNET_CRON_HOURS, meta, kuri, kuri);
313 CHECK (upload != NULL);
314 GNUNET_ECRS_uri_destroy (kuri);
315 kuri = NULL;
316 prog = 0;
317 while (lastEvent != GNUNET_FSUI_upload_completed)
318 {
319 prog++;
320 CHECK (prog < 5000);
321 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
322 if (GNUNET_shutdown_test () == GNUNET_YES)
323 break;
324 }
325 GNUNET_FSUI_upload_stop (upload);
326 upload = NULL;
327 CHECK (upURI != NULL);
328
329 fprintf(stderr,
330 "Downloading...\n");
331 waitForEvent = GNUNET_FSUI_download_completed;
332 fn43 = makeName (43);
333 download = GNUNET_FSUI_download_start (ctx,
334 0,
335 GNUNET_YES,
336 upURI, meta, fn43, NULL, NULL);
337 CHECK (download != NULL);
338 GNUNET_free (fn43);
339 fn43 = NULL;
340 prog = 0;
341 while (!download_done)
342 {
343 prog++;
344 CHECK (prog < 5000);
345 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
346 if (GNUNET_shutdown_test () == GNUNET_YES)
347 break;
348 }
349FAILURE:
350 fprintf(stderr,
351 "Cleanup...\n");
352 if (meta != NULL)
353 GNUNET_meta_data_destroy (meta);
354 if (ctx != NULL)
355 {
356 if (download != NULL)
357 GNUNET_FSUI_download_stop (download);
358 GNUNET_FSUI_stop (ctx);
359 }
360 if (fn != NULL)
361 {
362 GNUNET_disk_directory_remove (NULL, fn);
363 GNUNET_free (fn);
364 }
365 if (kuri != NULL)
366 GNUNET_ECRS_uri_destroy (kuri);
367 fn43 = makeName (43);
368 GNUNET_disk_directory_remove (NULL, fn43);
369 GNUNET_free (fn43);
370 if (upURI != NULL)
371 GNUNET_ECRS_uri_destroy (upURI);
372
373#if START_DAEMON
374 GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
375#endif
376 GNUNET_GC_free (cfg);
377 return (ok == GNUNET_YES) ? 0 : 1;
378}
379
380/* end of recursive_download_test.c */
diff --git a/src/fs/test_fs_getopt.c b/src/fs/test_fs_getopt.c
index d2e424b4a..4ce64b72f 100644
--- a/src/fs/test_fs_getopt.c
+++ b/src/fs/test_fs_getopt.c
@@ -28,6 +28,13 @@
28int 28int
29main (int argc, char *argv[]) 29main (int argc, char *argv[])
30{ 30{
31 GNUNET_log_setup ("test_fs_directory",
32#if VERBOSE
33 "DEBUG",
34#else
35 "WARNING",
36#endif
37 NULL);
31 fprintf (stderr, "WARNING: testcase not yet written.\n"); 38 fprintf (stderr, "WARNING: testcase not yet written.\n");
32 return 0; /* testcase passed */ 39 return 0; /* testcase passed */
33} 40}
diff --git a/src/fs/test_fs_search_persistence.c b/src/fs/test_fs_search_persistence.c
new file mode 100644
index 000000000..ad0e12b4b
--- /dev/null
+++ b/src/fs/test_fs_search_persistence.c
@@ -0,0 +1,213 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/fsui/search_persistence_test.c
23 * @brief testcase for fsui download persistence for search
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "gnunet_fsui_lib.h"
30
31#define DEBUG_VERBOSE GNUNET_NO
32
33#define UPLOAD_PREFIX "/tmp/gnunet-fsui-search_persistence_test"
34
35#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto FAILURE; }
36
37static struct GNUNET_GE_Context *ectx;
38
39static struct GNUNET_FSUI_Context *ctx;
40static struct GNUNET_FSUI_SearchList *search;
41static int have_error;
42
43static void *
44eventCallback (void *cls, const GNUNET_FSUI_Event * event)
45{
46 switch (event->type)
47 {
48 case GNUNET_FSUI_search_suspended:
49 search = NULL;
50 break;
51 case GNUNET_FSUI_search_resumed:
52#if DEBUG_VERBOSE
53 printf ("Search resuming\n");
54#endif
55 search = event->data.SearchResumed.sc.pos;
56 break;
57 case GNUNET_FSUI_search_result:
58#if DEBUG_VERBOSE
59 printf ("Received search result\n");
60#endif
61 break;
62 case GNUNET_FSUI_upload_progress:
63#if DEBUG_VERBOSE
64 printf ("Upload is progressing (%llu/%llu)...\n",
65 event->data.UploadProgress.completed,
66 event->data.UploadProgress.total);
67#endif
68 break;
69 case GNUNET_FSUI_upload_completed:
70#if DEBUG_VERBOSE
71 printf ("Upload complete.\n");
72#endif
73 break;
74 case GNUNET_FSUI_unindex_progress:
75#if DEBUG_VERBOSE
76 printf ("Unindex is progressing (%llu/%llu)...\n",
77 event->data.UnindexProgress.completed,
78 event->data.UnindexProgress.total);
79#endif
80 break;
81 case GNUNET_FSUI_unindex_completed:
82#if DEBUG_VERBOSE
83 printf ("Unindex complete.\n");
84#endif
85 break;
86 case GNUNET_FSUI_unindex_error:
87 case GNUNET_FSUI_upload_error:
88 case GNUNET_FSUI_download_error:
89 fprintf (stderr, "Received ERROR: %d\n", event->type);
90 GNUNET_GE_BREAK (ectx, 0);
91 break;
92 case GNUNET_FSUI_download_aborted:
93#if DEBUG_VERBOSE
94 printf ("Received download aborted event.\n");
95#endif
96 break;
97 case GNUNET_FSUI_unindex_suspended:
98 case GNUNET_FSUI_upload_suspended:
99#if DEBUG_VERBOSE
100 fprintf (stderr, "Received SUSPENDING: %d\n", event->type);
101#endif
102 break;
103 case GNUNET_FSUI_upload_started:
104 case GNUNET_FSUI_upload_stopped:
105 case GNUNET_FSUI_search_started:
106 case GNUNET_FSUI_search_aborted:
107 case GNUNET_FSUI_search_stopped:
108 case GNUNET_FSUI_search_update:
109 case GNUNET_FSUI_unindex_started:
110 case GNUNET_FSUI_unindex_stopped:
111 break;
112 default:
113 printf ("Unexpected event: %d\n", event->type);
114 break;
115 }
116 return NULL;
117}
118
119#define FILESIZE (1024)
120
121#define START_DAEMON 1
122
123int
124main (int argc, char *argv[])
125{
126#if START_DAEMON
127 pid_t daemon;
128#endif
129 int ok;
130 struct GNUNET_ECRS_URI *uri = NULL;
131 char *keywords[] = {
132 "down_foo",
133 "down_bar",
134 };
135 char keyword[40];
136 int prog;
137 struct GNUNET_GC_Configuration *cfg;
138 int suspendRestart = 0;
139
140
141 ok = GNUNET_YES;
142 cfg = GNUNET_GC_create ();
143 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
144 {
145 GNUNET_GC_free (cfg);
146 return -1;
147 }
148#if START_DAEMON
149 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
150 GNUNET_GE_ASSERT (NULL, daemon > 0);
151 CHECK (GNUNET_OK ==
152 GNUNET_wait_for_daemon_running (NULL, cfg,
153 30 * GNUNET_CRON_SECONDS));
154 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to start */
155 /* ACTUAL TEST CODE */
156#endif
157 ctx = GNUNET_FSUI_start (NULL,
158 cfg, "search_persistence_test", 32, GNUNET_YES,
159 &eventCallback, NULL);
160 CHECK (ctx != NULL);
161 GNUNET_snprintf (keyword, 40, "+%s +%s", keywords[0], keywords[1]);
162 uri = GNUNET_ECRS_keyword_string_to_uri (ectx, keyword);
163 search = GNUNET_FSUI_search_start (ctx, 0, uri);
164 CHECK (search != NULL);
165 prog = 0;
166 suspendRestart = 10;
167 while (prog < 100)
168 {
169 prog++;
170 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
171 if ((suspendRestart > 0)
172 && (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 10) == 0))
173 {
174#if 1
175#if DEBUG_VERBOSE
176 printf ("Testing FSUI suspend-resume\n");
177#endif
178 GNUNET_FSUI_stop (ctx); /* download possibly incomplete
179 at this point, thus testing resume */
180 CHECK (search == NULL);
181 ctx = GNUNET_FSUI_start (NULL,
182 cfg,
183 "search_persistence_test", 32, GNUNET_YES,
184 &eventCallback, NULL);
185#if DEBUG_VERBOSE
186 printf ("Resumed...\n");
187#endif
188#endif
189 suspendRestart--;
190 }
191 if (GNUNET_shutdown_test () == GNUNET_YES)
192 break;
193 }
194 GNUNET_FSUI_search_abort (search);
195 GNUNET_FSUI_search_stop (search);
196 search = NULL;
197 /* END OF TEST CODE */
198FAILURE:
199 if (ctx != NULL)
200 GNUNET_FSUI_stop (ctx);
201 if (uri != NULL)
202 GNUNET_ECRS_uri_destroy (uri);
203
204#if START_DAEMON
205 GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
206#endif
207 GNUNET_GC_free (cfg);
208 if (have_error)
209 ok = GNUNET_NO;
210 return (ok == GNUNET_YES) ? 0 : 1;
211}
212
213/* end of search_persistence_test.c */
diff --git a/src/fs/test_fs_search_ranking.c b/src/fs/test_fs_search_ranking.c
new file mode 100644
index 000000000..caaa0f9f1
--- /dev/null
+++ b/src/fs/test_fs_search_ranking.c
@@ -0,0 +1,250 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/fsui/search_ranking_test.c
23 * @brief testcase for search ranking (availability, etc)
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "gnunet_fsui_lib.h"
30
31#define CHECK_VERBOSE GNUNET_NO
32
33#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(NULL, 0); goto FAILURE; }
34
35static char *
36makeName (unsigned int i)
37{
38 char *fn;
39
40 fn =
41 GNUNET_malloc (strlen ("/tmp/gnunet-fsui-searchranktest/FSUITEST") + 14);
42 GNUNET_snprintf (fn,
43 strlen ("/tmp/gnunet-fsui-searchranktest/FSUITEST") + 14,
44 "/tmp/gnunet-fsui-searchranktest/FSUITEST%u", i);
45 GNUNET_disk_directory_create_for_file (NULL, fn);
46 return fn;
47}
48
49static struct GNUNET_FSUI_SearchList *search;
50
51static volatile enum GNUNET_FSUI_EventType lastEvent;
52
53static volatile struct GNUNET_ECRS_URI *uri;
54
55static volatile int availability;
56
57static volatile unsigned int rank;
58
59static volatile enum GNUNET_FSUI_EventType waitForEvent;
60
61static void *
62eventCallback (void *cls, const GNUNET_FSUI_Event * event)
63{
64 static char unused;
65
66 switch (event->type)
67 {
68 case GNUNET_FSUI_search_resumed:
69 search = event->data.SearchResumed.sc.pos;
70 break;
71 case GNUNET_FSUI_search_suspended:
72 search = NULL;
73 break;
74 case GNUNET_FSUI_search_update:
75 availability = event->data.SearchUpdate.availability_rank;
76 rank = event->data.SearchUpdate.applicability_rank;
77 break;
78 case GNUNET_FSUI_search_paused:
79 case GNUNET_FSUI_search_restarted:
80 break;
81 case GNUNET_FSUI_download_resumed:
82 case GNUNET_FSUI_upload_resumed:
83 case GNUNET_FSUI_unindex_resumed:
84 return &unused;
85 case GNUNET_FSUI_search_result:
86#if CHECK_VERBOSE
87 printf ("Received search result\n");
88#endif
89 uri = GNUNET_ECRS_uri_duplicate (event->data.SearchResult.fi.uri);
90 break;
91 case GNUNET_FSUI_upload_completed:
92#if CHECK_VERBOSE
93 printf ("Upload complete.\n");
94#endif
95 break;
96 case GNUNET_FSUI_download_completed:
97#if CHECK_VERBOSE
98 printf ("Download complete.\n");
99#endif
100 break;
101 case GNUNET_FSUI_unindex_completed:
102#if CHECK_VERBOSE
103 printf ("Unindex complete.\n");
104#endif
105 break;
106 case GNUNET_FSUI_upload_error:
107 printf ("Upload error.\n");
108 break;
109 case GNUNET_FSUI_download_error:
110 printf ("Download error.\n");
111 break;
112 case GNUNET_FSUI_unindex_error:
113 printf ("Unindex error.\n");
114 break;
115 default:
116 break;
117 }
118 if (lastEvent != waitForEvent)
119 lastEvent = event->type;
120 return NULL;
121}
122
123#define START_DAEMON 1
124
125int
126main (int argc, char *argv[])
127{
128#if START_DAEMON
129 pid_t daemon;
130#endif
131 int ok;
132 char *fn = NULL;
133 char *keywords[] = {
134 "search_foo",
135 "search_bar",
136 };
137 char keyword[40];
138 int prog;
139 struct GNUNET_MetaData *meta;
140 struct GNUNET_ECRS_URI *kuri;
141 struct GNUNET_GC_Configuration *cfg;
142 struct GNUNET_FSUI_UploadList *upload;
143 struct GNUNET_ECRS_URI *luri;
144 struct GNUNET_FSUI_Context *ctx = NULL;
145
146 ok = GNUNET_YES;
147 cfg = GNUNET_GC_create ();
148 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
149 {
150 GNUNET_GC_free (cfg);
151 return -1;
152 }
153#if START_DAEMON
154 GNUNET_disk_directory_remove (NULL, "/tmp/gnunet-fsui-searchranktest/");
155 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
156 GNUNET_GE_ASSERT (NULL, daemon > 0);
157 CHECK (GNUNET_OK ==
158 GNUNET_wait_for_daemon_running (NULL, cfg,
159 30 * GNUNET_CRON_SECONDS));
160 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to start */
161 /* ACTUAL TEST CODE */
162#endif
163 ctx = GNUNET_FSUI_start (NULL,
164 cfg, "fsuisearchranktest", 32, GNUNET_YES,
165 &eventCallback, NULL);
166 CHECK (ctx != NULL);
167 /* upload */
168 fn = makeName (42);
169 GNUNET_disk_file_write (NULL,
170 fn, "foo bar test!", strlen ("foo bar test!"),
171 "600");
172 meta = GNUNET_meta_data_create ();
173 kuri =
174 GNUNET_ECRS_keyword_command_line_to_uri (NULL, 2,
175 (const char **) keywords);
176 waitForEvent = GNUNET_FSUI_upload_completed;
177 upload =
178 GNUNET_FSUI_upload_start (ctx,
179 fn,
180 (GNUNET_FSUI_DirectoryScanCallback) &
181 GNUNET_disk_directory_scan, NULL, 0, 0,
182 GNUNET_YES, GNUNET_NO, GNUNET_NO,
183 GNUNET_get_time () + 5 * GNUNET_CRON_HOURS,
184 meta, kuri, kuri);
185 CHECK (NULL != upload);
186 GNUNET_free (fn);
187 fn = NULL;
188 GNUNET_ECRS_uri_destroy (kuri);
189 GNUNET_meta_data_destroy (meta);
190 prog = 0;
191 while (lastEvent != GNUNET_FSUI_upload_completed)
192 {
193 prog++;
194 if (prog == 10000)
195 {
196 fprintf (stderr,
197 "Upload failed to complete -- last event: %u\n",
198 lastEvent);
199 }
200 CHECK (prog < 10000);
201 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
202 if (GNUNET_shutdown_test () == GNUNET_YES)
203 break;
204 }
205 GNUNET_FSUI_upload_stop (upload);
206
207 /* search */
208 GNUNET_snprintf (keyword, 40, "%s %s", keywords[0], keywords[1]);
209 luri = GNUNET_ECRS_keyword_string_to_uri (NULL, keyword);
210 uri = NULL;
211 search = GNUNET_FSUI_search_start (ctx, 0, luri);
212 GNUNET_ECRS_uri_destroy (luri);
213 luri = NULL;
214 CHECK (NULL != search);
215 GNUNET_FSUI_search_pause (search);
216 GNUNET_FSUI_search_restart (search);
217 while ((uri == NULL) &&
218 (availability < 3) &&
219 (rank != 2) && (GNUNET_shutdown_test () != GNUNET_YES))
220 {
221 prog++;
222 CHECK (prog < 10000);
223 GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
224 }
225 GNUNET_FSUI_search_abort (search);
226 GNUNET_FSUI_search_stop (search);
227 CHECK (uri != NULL);
228
229
230 /* END OF TEST CODE */
231FAILURE:
232 if (ctx != NULL)
233 GNUNET_FSUI_stop (ctx);
234 GNUNET_free_non_null (fn);
235 /* TODO: verify file 'fn(42)' == file 'fn(43)' */
236 fn = makeName (42);
237 UNLINK (fn);
238 GNUNET_free (fn);
239 fn = makeName (43);
240 UNLINK (fn);
241 GNUNET_free (fn);
242
243#if START_DAEMON
244 GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
245#endif
246 GNUNET_GC_free (cfg);
247 return (ok == GNUNET_YES) ? 0 : 1;
248}
249
250/* end of searchtest.c */
diff --git a/src/fs/test_fs_start_stop.c b/src/fs/test_fs_start_stop.c
new file mode 100644
index 000000000..1ec1176a6
--- /dev/null
+++ b/src/fs/test_fs_start_stop.c
@@ -0,0 +1,89 @@
1/*
2 This file is part of GNUnet.
3 (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/fsui/fsui_start_stop_test.c
23 * @brief testcase for fsui (start-stop only)
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "gnunet_fsui_lib.h"
30
31#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(NULL, 0); goto FAILURE; }
32
33
34static struct GNUNET_FSUI_Context *ctx;
35
36static void *
37eventCallback (void *cls, const GNUNET_FSUI_Event * event)
38{
39 return NULL;
40}
41
42#define START_DAEMON 1
43
44int
45main (int argc, char *argv[])
46{
47#if START_DAEMON
48 pid_t daemon;
49#endif
50 int ok;
51 struct GNUNET_GC_Configuration *cfg;
52
53 cfg = GNUNET_GC_create ();
54 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
55 {
56 GNUNET_GC_free (cfg);
57 return -1;
58 }
59#if START_DAEMON
60 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
61 GNUNET_GE_ASSERT (NULL, daemon > 0);
62 CHECK (GNUNET_OK ==
63 GNUNET_wait_for_daemon_running (NULL, cfg,
64 60 * GNUNET_CRON_SECONDS));
65#endif
66 ok = GNUNET_YES;
67 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS); /* give apps time to start */
68
69 /* ACTUAL TEST CODE */
70 ctx = GNUNET_FSUI_start (NULL, cfg, "fsui_start_stop_test", 32, GNUNET_YES, /* do resume! */
71 &eventCallback, NULL);
72 CHECK (ctx != NULL);
73 GNUNET_FSUI_stop (ctx);
74 ctx =
75 GNUNET_FSUI_start (NULL, cfg, "fsui_start_stop_test", 32, GNUNET_YES,
76 &eventCallback, NULL);
77 CHECK (ctx != NULL);
78FAILURE:
79 if (ctx != NULL)
80 GNUNET_FSUI_stop (ctx);
81#if START_DAEMON
82 GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
83#endif
84 GNUNET_GC_free (cfg);
85
86 return (ok == GNUNET_YES) ? 0 : 1;
87}
88
89/* end of fsui_start_stop_test.c */
diff --git a/src/fs/test_fs_uri.c b/src/fs/test_fs_uri.c
index 6da56a742..ee587c92a 100644
--- a/src/fs/test_fs_uri.c
+++ b/src/fs/test_fs_uri.c
@@ -38,10 +38,10 @@ testKeyword ()
38 struct GNUNET_FS_Uri *ret; 38 struct GNUNET_FS_Uri *ret;
39 char *emsg; 39 char *emsg;
40 40
41 if (NULL != GNUNET_FS_uri_parse ("gnunet://ecrs/ksk/++", &emsg)) 41 if (NULL != GNUNET_FS_uri_parse ("gnunet://fs/ksk/++", &emsg))
42 ABORT (); 42 ABORT ();
43 GNUNET_free (emsg); 43 GNUNET_free (emsg);
44 ret = GNUNET_FS_uri_parse ("gnunet://ecrs/ksk/foo+bar", &emsg); 44 ret = GNUNET_FS_uri_parse ("gnunet://fs/ksk/foo+bar", &emsg);
45 if (ret == NULL) 45 if (ret == NULL)
46 ABORT (); 46 ABORT ();
47 if (!GNUNET_FS_uri_test_ksk (ret)) 47 if (!GNUNET_FS_uri_test_ksk (ret))
@@ -58,7 +58,7 @@ testKeyword ()
58 } 58 }
59 59
60 uri = GNUNET_FS_uri_to_string (ret); 60 uri = GNUNET_FS_uri_to_string (ret);
61 if (0 != strcmp (uri, "gnunet://ecrs/ksk/foo+bar")) 61 if (0 != strcmp (uri, "gnunet://fs/ksk/foo+bar"))
62 { 62 {
63 GNUNET_free (uri); 63 GNUNET_free (uri);
64 GNUNET_FS_uri_destroy (ret); 64 GNUNET_FS_uri_destroy (ret);
@@ -80,7 +80,7 @@ testLocation ()
80 struct GNUNET_CONFIGURATION_Handle *cfg; 80 struct GNUNET_CONFIGURATION_Handle *cfg;
81 81
82 baseURI = 82 baseURI =
83 GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg); 83 GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg);
84 GNUNET_assert (baseURI != NULL); 84 GNUNET_assert (baseURI != NULL);
85 cfg = GNUNET_CONFIGURATION_create (); 85 cfg = GNUNET_CONFIGURATION_create ();
86 if (GNUNET_OK != 86 if (GNUNET_OK !=
@@ -97,6 +97,7 @@ testLocation ()
97 { 97 {
98 GNUNET_break (0); 98 GNUNET_break (0);
99 GNUNET_FS_uri_destroy (baseURI); 99 GNUNET_FS_uri_destroy (baseURI);
100 GNUNET_CONFIGURATION_destroy (cfg);
100 return 1; 101 return 1;
101 } 102 }
102 if (!GNUNET_FS_uri_test_loc (uri)) 103 if (!GNUNET_FS_uri_test_loc (uri))
@@ -104,6 +105,7 @@ testLocation ()
104 GNUNET_break (0); 105 GNUNET_break (0);
105 GNUNET_FS_uri_destroy (uri); 106 GNUNET_FS_uri_destroy (uri);
106 GNUNET_FS_uri_destroy (baseURI); 107 GNUNET_FS_uri_destroy (baseURI);
108 GNUNET_CONFIGURATION_destroy (cfg);
107 return 1; 109 return 1;
108 } 110 }
109 uri2 = GNUNET_FS_uri_loc_get_uri (uri); 111 uri2 = GNUNET_FS_uri_loc_get_uri (uri);
@@ -113,6 +115,7 @@ testLocation ()
113 GNUNET_FS_uri_destroy (uri); 115 GNUNET_FS_uri_destroy (uri);
114 GNUNET_FS_uri_destroy (uri2); 116 GNUNET_FS_uri_destroy (uri2);
115 GNUNET_FS_uri_destroy (baseURI); 117 GNUNET_FS_uri_destroy (baseURI);
118 GNUNET_CONFIGURATION_destroy (cfg);
116 return 1; 119 return 1;
117 } 120 }
118 GNUNET_FS_uri_destroy (uri2); 121 GNUNET_FS_uri_destroy (uri2);
@@ -128,6 +131,7 @@ testLocation ()
128 { 131 {
129 GNUNET_break (0); 132 GNUNET_break (0);
130 GNUNET_FS_uri_destroy (uri); 133 GNUNET_FS_uri_destroy (uri);
134 GNUNET_CONFIGURATION_destroy (cfg);
131 return 1; 135 return 1;
132 } 136 }
133 if (GNUNET_YES != GNUNET_FS_uri_test_equal (uri, uri2)) 137 if (GNUNET_YES != GNUNET_FS_uri_test_equal (uri, uri2))
@@ -135,10 +139,12 @@ testLocation ()
135 GNUNET_break (0); 139 GNUNET_break (0);
136 GNUNET_FS_uri_destroy (uri); 140 GNUNET_FS_uri_destroy (uri);
137 GNUNET_FS_uri_destroy (uri2); 141 GNUNET_FS_uri_destroy (uri2);
142 GNUNET_CONFIGURATION_destroy (cfg);
138 return 1; 143 return 1;
139 } 144 }
140 GNUNET_FS_uri_destroy (uri2); 145 GNUNET_FS_uri_destroy (uri2);
141 GNUNET_FS_uri_destroy (uri); 146 GNUNET_FS_uri_destroy (uri);
147 GNUNET_CONFIGURATION_destroy (cfg);
142 return 0; 148 return 0;
143} 149}
144 150
@@ -150,15 +156,18 @@ testNamespace (int i)
150 char *emsg; 156 char *emsg;
151 157
152 if (NULL != 158 if (NULL !=
153 GNUNET_FS_uri_parse ("gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK", &emsg)) 159 GNUNET_FS_uri_parse ("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK", &emsg))
154 ABORT (); 160 ABORT ();
161 GNUNET_free (emsg);
155 if (NULL != 162 if (NULL !=
156 GNUNET_FS_uri_parse ("gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test", &emsg)) 163 GNUNET_FS_uri_parse ("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test", &emsg))
157 ABORT (); 164 ABORT ();
158 if (NULL != GNUNET_FS_uri_parse ("gnunet://ecrs/sks/test", &emsg)) 165 GNUNET_free (emsg);
166 if (NULL != GNUNET_FS_uri_parse ("gnunet://fs/sks/test", &emsg))
159 ABORT (); 167 ABORT ();
168 GNUNET_free (emsg);
160 ret = 169 ret =
161 GNUNET_FS_uri_parse ("gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test", &emsg); 170 GNUNET_FS_uri_parse ("gnunet://fs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test", &emsg);
162 if (ret == NULL) 171 if (ret == NULL)
163 ABORT (); 172 ABORT ();
164 if (GNUNET_FS_uri_test_ksk (ret)) 173 if (GNUNET_FS_uri_test_ksk (ret))
@@ -174,7 +183,7 @@ testNamespace (int i)
174 183
175 uri = GNUNET_FS_uri_to_string (ret); 184 uri = GNUNET_FS_uri_to_string (ret);
176 if (0 != strcmp (uri, 185 if (0 != strcmp (uri,
177 "gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test")) 186 "gnunet://fs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test"))
178 { 187 {
179 GNUNET_FS_uri_destroy (ret); 188 GNUNET_FS_uri_destroy (ret);
180 GNUNET_free (uri); 189 GNUNET_free (uri);
@@ -193,19 +202,19 @@ testFile (int i)
193 char *emsg; 202 char *emsg;
194 203
195 if (NULL != 204 if (NULL !=
196 GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42", &emsg)) 205 GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42", &emsg))
197 ABORT (); 206 ABORT ();
198 GNUNET_free (emsg); 207 GNUNET_free (emsg);
199 if (NULL != 208 if (NULL !=
200 GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000", &emsg)) 209 GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000", &emsg))
201 ABORT (); 210 ABORT ();
202 GNUNET_free (emsg); 211 GNUNET_free (emsg);
203 if (NULL != 212 if (NULL !=
204 GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH", &emsg)) 213 GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH", &emsg))
205 ABORT (); 214 ABORT ();
206 GNUNET_free (emsg); 215 GNUNET_free (emsg);
207 ret = 216 ret =
208 GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg); 217 GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg);
209 if (ret == NULL) 218 if (ret == NULL)
210 ABORT (); 219 ABORT ();
211 if (GNUNET_FS_uri_test_ksk (ret)) 220 if (GNUNET_FS_uri_test_ksk (ret))
@@ -226,7 +235,7 @@ testFile (int i)
226 235
227 uri = GNUNET_FS_uri_to_string (ret); 236 uri = GNUNET_FS_uri_to_string (ret);
228 if (0 != strcmp (uri, 237 if (0 != strcmp (uri,
229 "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42")) 238 "gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"))
230 { 239 {
231 GNUNET_free (uri); 240 GNUNET_free (uri);
232 GNUNET_FS_uri_destroy (ret); 241 GNUNET_FS_uri_destroy (ret);
@@ -243,14 +252,23 @@ main (int argc, char *argv[])
243 int failureCount = 0; 252 int failureCount = 0;
244 int i; 253 int i;
245 254
255 GNUNET_log_setup ("test_fs_uri",
256#if VERBOSE
257 "DEBUG",
258#else
259 "WARNING",
260#endif
261 NULL);
246 GNUNET_CRYPTO_random_disable_entropy_gathering (); 262 GNUNET_CRYPTO_random_disable_entropy_gathering ();
247 failureCount += testKeyword (); 263 failureCount += testKeyword ();
248 failureCount += testLocation (); 264 failureCount += testLocation ();
249 for (i = 0; i < 255; i++) 265 for (i = 0; i < 255; i++)
250 { 266 {
267 /* fprintf (stderr, "."); */
251 failureCount += testNamespace (i); 268 failureCount += testNamespace (i);
252 failureCount += testFile (i); 269 failureCount += testFile (i);
253 } 270 }
271 /* fprintf (stderr, "\n"); */
254 if (failureCount != 0) 272 if (failureCount != 0)
255 return 1; 273 return 1;
256 return 0; 274 return 0;
diff --git a/src/fs/test_namespace.c b/src/fs/test_namespace.c
new file mode 100644
index 000000000..81c0e1559
--- /dev/null
+++ b/src/fs/test_namespace.c
@@ -0,0 +1,136 @@
1/*
2 This file is part of GNUnet.
3 (C) 2005, 2006, 2008 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file applications/fs/ecrs/namespacetest.c
23 * @brief Test for namespace.c
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_util.h"
29#include "gnunet_ecrs_lib.h"
30#include "ecrs.h"
31
32#define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); return 1; }
33#define CHECK(c) { do { if (!(c)) ABORT(); } while(0); }
34
35#define CHECKNAME "gnunet-namespace-test"
36
37static struct GNUNET_GC_Configuration *cfg;
38
39static int match;
40
41static int
42spcb (const GNUNET_ECRS_FileInfo * fi,
43 const GNUNET_HashCode * key, int isRoot, void *closure)
44{
45 struct GNUNET_ECRS_URI *want = closure;
46
47 if (GNUNET_ECRS_uri_test_equal (want, fi->uri))
48 match = 1;
49 else
50 fprintf (stderr,
51 "Namespace search returned unexpected result: \nHAVE: %s\nWANT: %s...\n",
52 GNUNET_ECRS_uri_to_string (fi->uri),
53 GNUNET_ECRS_uri_to_string (want));
54 return GNUNET_OK;
55}
56
57static int
58tt (void *unused)
59{
60 if (match == 1)
61 return GNUNET_SYSERR;
62 return GNUNET_OK;
63}
64
65static int
66testNamespace ()
67{
68 GNUNET_HashCode pid;
69 struct GNUNET_ECRS_URI *adv;
70 struct GNUNET_ECRS_URI *advURI;
71 struct GNUNET_ECRS_URI *rootURI;
72 struct GNUNET_MetaData *meta;
73
74 meta = GNUNET_meta_data_create ();
75 adv = GNUNET_ECRS_keyword_string_to_uri (NULL, "testNamespace");
76 rootURI =
77 GNUNET_ECRS_namespace_create (NULL,
78 cfg,
79 meta,
80 0, 0,
81 GNUNET_get_time () +
82 15 * GNUNET_CRON_MINUTES, adv, "root");
83 CHECK (NULL != rootURI);
84 GNUNET_ECRS_uri_get_namespace_from_sks (rootURI, &pid);
85 advURI = GNUNET_ECRS_namespace_add_content (NULL, cfg, &pid, 1, /* anonymity */
86 1000, /* priority */
87 5 * GNUNET_CRON_MINUTES +
88 GNUNET_get_time (),
89 "this", "next", rootURI, meta);
90 CHECK (NULL != advURI);
91 fprintf (stderr, "Starting namespace search...\n");
92 CHECK (GNUNET_OK == GNUNET_ECRS_search (NULL,
93 cfg,
94 advURI, 1, &spcb, rootURI, &tt,
95 NULL));
96 fprintf (stderr, "Completed namespace search...\n");
97 CHECK (GNUNET_OK == GNUNET_ECRS_namespace_delete (NULL, cfg, &pid));
98 CHECK (GNUNET_SYSERR == GNUNET_ECRS_namespace_delete (NULL, cfg, &pid));
99 GNUNET_meta_data_destroy (meta);
100 GNUNET_ECRS_uri_destroy (rootURI);
101 GNUNET_ECRS_uri_destroy (advURI);
102 CHECK (match == 1);
103 return 0;
104}
105
106int
107main (int argc, char *argv[])
108{
109 pid_t daemon;
110 int failureCount = 0;
111
112 GNUNET_disable_entropy_gathering ();
113 cfg = GNUNET_GC_create ();
114 if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
115 {
116 GNUNET_GC_free (cfg);
117 return -1;
118 }
119 daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
120 GNUNET_GE_ASSERT (NULL, daemon > 0);
121 if (GNUNET_OK !=
122 GNUNET_wait_for_daemon_running (NULL, cfg, 60 * GNUNET_CRON_SECONDS))
123 {
124 failureCount++;
125 }
126 else
127 {
128 GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);
129 failureCount += testNamespace ();
130 }
131 GNUNET_GE_ASSERT (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
132
133 return (failureCount == 0) ? 0 : 1;
134}
135
136/* end of namespacetest.c */
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h
index ea76860c3..236bdd083 100644
--- a/src/include/gnunet_fs_service.h
+++ b/src/include/gnunet_fs_service.h
@@ -441,45 +441,45 @@ GNUNET_FS_getopt_configure_set_metadata (struct GNUNET_GETOPT_CommandLineProcess
441enum GNUNET_FS_Status 441enum GNUNET_FS_Status
442{ 442{
443 /** 443 /**
444 * Notification that we have started to share a file structure. 444 * Notification that we have started to publish a file structure.
445 */ 445 */
446 GNUNET_FS_STATUS_SHARE_START, 446 GNUNET_FS_STATUS_PUBLISH_START,
447 447
448 /** 448 /**
449 * Notification that we have resumed sharing a file structure. 449 * Notification that we have resumed sharing a file structure.
450 */ 450 */
451 GNUNET_FS_STATUS_SHARE_RESUME, 451 GNUNET_FS_STATUS_PUBLISH_RESUME,
452 452
453 /** 453 /**
454 * Notification that we have suspended sharing a file structure. 454 * Notification that we have suspended sharing a file structure.
455 */ 455 */
456 GNUNET_FS_STATUS_SHARE_SUSPEND, 456 GNUNET_FS_STATUS_PUBLISH_SUSPEND,
457 457
458 /** 458 /**
459 * Notification that we are making progress sharing a file structure. 459 * Notification that we are making progress sharing a file structure.
460 */ 460 */
461 GNUNET_FS_STATUS_SHARE_PROGRESS, 461 GNUNET_FS_STATUS_PUBLISH_PROGRESS,
462 462
463 /** 463 /**
464 * Notification that an error was encountered sharing a file structure. 464 * Notification that an error was encountered sharing a file structure.
465 * The application will continue to receive resume/suspend events for 465 * The application will continue to receive resume/suspend events for
466 * this structure until "GNUNET_FS_share_stop" is called. 466 * this structure until "GNUNET_FS_publish_stop" is called.
467 */ 467 */
468 GNUNET_FS_STATUS_SHARE_ERROR, 468 GNUNET_FS_STATUS_PUBLISH_ERROR,
469 469
470 /** 470 /**
471 * Notification that we completed sharing a file structure. 471 * Notification that we completed sharing a file structure.
472 * The application will continue to receive resume/suspend events for 472 * The application will continue to receive resume/suspend events for
473 * this structure until "GNUNET_FS_share_stop" is called. 473 * this structure until "GNUNET_FS_publish_stop" is called.
474 */ 474 */
475 GNUNET_FS_STATUS_SHARE_COMPLETED, 475 GNUNET_FS_STATUS_PUBLISH_COMPLETED,
476 476
477 /** 477 /**
478 * Notification that we have stopped 478 * Notification that we have stopped
479 * the process of uploading a file structure; no 479 * the process of uploading a file structure; no
480 * futher events will be generated for this action. 480 * futher events will be generated for this action.
481 */ 481 */
482 GNUNET_FS_STATUS_SHARE_STOPPED, 482 GNUNET_FS_STATUS_PUBLISH_STOPPED,
483 483
484 /** 484 /**
485 * Notification that we have started this download. 485 * Notification that we have started this download.
@@ -640,7 +640,7 @@ struct GNUNET_FS_Namespace;
640/** 640/**
641 * Handle for controlling an upload. 641 * Handle for controlling an upload.
642 */ 642 */
643struct GNUNET_FS_ShareContext; 643struct GNUNET_FS_PublishContext;
644 644
645 645
646/** 646/**
@@ -662,7 +662,7 @@ struct GNUNET_FS_DownloadContext;
662 662
663 663
664/** 664/**
665 * Handle for detail information about a file that is being shared. 665 * Handle for detail information about a file that is being publishd.
666 * Specifies metadata, keywords, how to get the contents of the file 666 * Specifies metadata, keywords, how to get the contents of the file
667 * (i.e. data-buffer in memory, filename on disk) and other options. 667 * (i.e. data-buffer in memory, filename on disk) and other options.
668 */ 668 */
@@ -682,17 +682,17 @@ struct GNUNET_FS_ProgressInfo
682 union { 682 union {
683 683
684 /** 684 /**
685 * Values for all "GNUNET_FS_STATUS_SHARE_*" events. 685 * Values for all "GNUNET_FS_STATUS_PUBLISH_*" events.
686 */ 686 */
687 struct { 687 struct {
688 688
689 /** 689 /**
690 * Context for controlling the upload. 690 * Context for controlling the upload.
691 */ 691 */
692 struct GNUNET_FS_ShareContext *sc; 692 struct GNUNET_FS_PublishContext *sc;
693 693
694 /** 694 /**
695 * Information about the file that is being shared. 695 * Information about the file that is being publishd.
696 */ 696 */
697 const struct GNUNET_FS_FileInformation *fi; 697 const struct GNUNET_FS_FileInformation *fi;
698 698
@@ -747,7 +747,7 @@ struct GNUNET_FS_ProgressInfo
747 747
748 /** 748 /**
749 * These values are only valid for 749 * These values are only valid for
750 * GNUNET_FS_STATUS_SHARE_PROGRESS events. 750 * GNUNET_FS_STATUS_PUBLISH_PROGRESS events.
751 */ 751 */
752 struct { 752 struct {
753 753
@@ -770,7 +770,7 @@ struct GNUNET_FS_ProgressInfo
770 770
771 /** 771 /**
772 * These values are only valid for 772 * These values are only valid for
773 * GNUNET_FS_STATUS_SHARE_RESUME events. 773 * GNUNET_FS_STATUS_PUBLISH_RESUME events.
774 */ 774 */
775 struct { 775 struct {
776 776
@@ -783,7 +783,7 @@ struct GNUNET_FS_ProgressInfo
783 783
784 /** 784 /**
785 * These values are only valid for 785 * These values are only valid for
786 * GNUNET_FS_STATUS_SHARE_ERROR events. 786 * GNUNET_FS_STATUS_PUBLISH_ERROR events.
787 */ 787 */
788 struct { 788 struct {
789 789
@@ -796,7 +796,7 @@ struct GNUNET_FS_ProgressInfo
796 796
797 } specifics; 797 } specifics;
798 798
799 } share; 799 } publish;
800 800
801 801
802 /** 802 /**
@@ -1348,7 +1348,7 @@ struct GNUNET_FS_ProgressInfo
1348 * will be passed to future callbacks in the respective 1348 * will be passed to future callbacks in the respective
1349 * field in the GNUNET_FS_ProgressInfo struct. 1349 * field in the GNUNET_FS_ProgressInfo struct.
1350 */ 1350 */
1351typedef int (*GNUNET_FS_ProgressCallback) 1351typedef void* (*GNUNET_FS_ProgressCallback)
1352 (void *cls, 1352 (void *cls,
1353 const struct GNUNET_FS_ProgressInfo *info); 1353 const struct GNUNET_FS_ProgressInfo *info);
1354 1354
@@ -1388,10 +1388,10 @@ GNUNET_FS_stop (struct GNUNET_FS_Handle *h);
1388 1388
1389 1389
1390/** 1390/**
1391 * Function called on entries in a GNUNET_FS_FileInformation share-structure. 1391 * Function called on entries in a GNUNET_FS_FileInformation publish-structure.
1392 * 1392 *
1393 * @param cls closure 1393 * @param cls closure
1394 * @param fi the entry in the share-structure 1394 * @param fi the entry in the publish-structure
1395 * @param length length of the file or directory 1395 * @param length length of the file or directory
1396 * @param meta metadata for the file or directory (can be modified) 1396 * @param meta metadata for the file or directory (can be modified)
1397 * @param uri pointer to the keywords that will be used for this entry (can be modified) 1397 * @param uri pointer to the keywords that will be used for this entry (can be modified)
@@ -1415,9 +1415,9 @@ typedef int (*GNUNET_FS_FileInformationProcessor)(void *cls,
1415 1415
1416 1416
1417/** 1417/**
1418 * Create an entry for a file in a share-structure. 1418 * Create an entry for a file in a publish-structure.
1419 * 1419 *
1420 * @param filename name of the file or directory to share 1420 * @param filename name of the file or directory to publish
1421 * @param meta metadata for the file 1421 * @param meta metadata for the file
1422 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion, 1422 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
1423 * GNUNET_SYSERR for simulation 1423 * GNUNET_SYSERR for simulation
@@ -1426,7 +1426,7 @@ typedef int (*GNUNET_FS_FileInformationProcessor)(void *cls,
1426 * keep this file available? Use 0 for maximum anonymity and 1426 * keep this file available? Use 0 for maximum anonymity and
1427 * minimum reliability... 1427 * minimum reliability...
1428 * @param expirationTime when should this content expire? 1428 * @param expirationTime when should this content expire?
1429 * @return share structure entry for the file 1429 * @return publish structure entry for the file
1430 */ 1430 */
1431struct GNUNET_FS_FileInformation * 1431struct GNUNET_FS_FileInformation *
1432GNUNET_FS_file_information_create_from_file (void *client_info, 1432GNUNET_FS_file_information_create_from_file (void *client_info,
@@ -1439,7 +1439,7 @@ GNUNET_FS_file_information_create_from_file (void *client_info,
1439 1439
1440 1440
1441/** 1441/**
1442 * Create an entry for a file in a share-structure. 1442 * Create an entry for a file in a publish-structure.
1443 * 1443 *
1444 * @param length length of the file 1444 * @param length length of the file
1445 * @param data data for the file (should not be used afterwards by 1445 * @param data data for the file (should not be used afterwards by
@@ -1452,7 +1452,7 @@ GNUNET_FS_file_information_create_from_file (void *client_info,
1452 * keep this file available? Use 0 for maximum anonymity and 1452 * keep this file available? Use 0 for maximum anonymity and
1453 * minimum reliability... 1453 * minimum reliability...
1454 * @param expirationTime when should this content expire? 1454 * @param expirationTime when should this content expire?
1455 * @return share structure entry for the file 1455 * @return publish structure entry for the file
1456 */ 1456 */
1457struct GNUNET_FS_FileInformation * 1457struct GNUNET_FS_FileInformation *
1458GNUNET_FS_file_information_create_from_data (void *client_info, 1458GNUNET_FS_file_information_create_from_data (void *client_info,
@@ -1489,7 +1489,7 @@ typedef size_t (*GNUNET_FS_DataReader)(void *cls,
1489 1489
1490 1490
1491/** 1491/**
1492 * Create an entry for a file in a share-structure. 1492 * Create an entry for a file in a publish-structure.
1493 * 1493 *
1494 * @param length length of the file 1494 * @param length length of the file
1495 * @param reader function that can be used to obtain the data for the file 1495 * @param reader function that can be used to obtain the data for the file
@@ -1504,7 +1504,7 @@ typedef size_t (*GNUNET_FS_DataReader)(void *cls,
1504 * keep this file available? Use 0 for maximum anonymity and 1504 * keep this file available? Use 0 for maximum anonymity and
1505 * minimum reliability... 1505 * minimum reliability...
1506 * @param expirationTime when should this content expire? 1506 * @param expirationTime when should this content expire?
1507 * @return share structure entry for the file 1507 * @return publish structure entry for the file
1508 */ 1508 */
1509struct GNUNET_FS_FileInformation * 1509struct GNUNET_FS_FileInformation *
1510GNUNET_FS_file_information_create_from_reader (void *client_info, 1510GNUNET_FS_file_information_create_from_reader (void *client_info,
@@ -1555,7 +1555,7 @@ typedef int (*GNUNET_FS_DirectoryScanner)(void *cls,
1555/** 1555/**
1556 * Simple, useful default implementation of a directory scanner 1556 * Simple, useful default implementation of a directory scanner
1557 * (GNUNET_FS_DirectoryScanner). This implementation expects to get a 1557 * (GNUNET_FS_DirectoryScanner). This implementation expects to get a
1558 * UNIX filename, will share all files in the directory except hidden 1558 * UNIX filename, will publish all files in the directory except hidden
1559 * files (those starting with a "."). Metadata will be extracted 1559 * files (those starting with a "."). Metadata will be extracted
1560 * using GNU libextractor; the specific list of plugins should be 1560 * using GNU libextractor; the specific list of plugins should be
1561 * specified in "cls", passing NULL will disable (!) metadata 1561 * specified in "cls", passing NULL will disable (!) metadata
@@ -1578,7 +1578,7 @@ GNUNET_FS_directory_scanner_default (void *cls,
1578 1578
1579 1579
1580/** 1580/**
1581 * Create a share-structure from an existing file hierarchy, inferring 1581 * Create a publish-structure from an existing file hierarchy, inferring
1582 * and organizing keywords and metadata as much as possible. This 1582 * and organizing keywords and metadata as much as possible. This
1583 * function primarily performs the recursive build and re-organizes 1583 * function primarily performs the recursive build and re-organizes
1584 * keywords and metadata; for automatically getting metadata 1584 * keywords and metadata; for automatically getting metadata
@@ -1595,7 +1595,7 @@ GNUNET_FS_directory_scanner_default (void *cls,
1595 * keep this file available? Use 0 for maximum anonymity and 1595 * keep this file available? Use 0 for maximum anonymity and
1596 * minimum reliability... 1596 * minimum reliability...
1597 * @param expirationTime when should this content expire? 1597 * @param expirationTime when should this content expire?
1598 * @return share structure entry for the directory, NULL on error 1598 * @return publish structure entry for the directory, NULL on error
1599 */ 1599 */
1600struct GNUNET_FS_FileInformation * 1600struct GNUNET_FS_FileInformation *
1601GNUNET_FS_file_information_create_from_directory (void *client_info, 1601GNUNET_FS_file_information_create_from_directory (void *client_info,
@@ -1607,7 +1607,7 @@ GNUNET_FS_file_information_create_from_directory (void *client_info,
1607 1607
1608 1608
1609/** 1609/**
1610 * Create an entry for an empty directory in a share-structure. 1610 * Create an entry for an empty directory in a publish-structure.
1611 * This function should be used by applications for which the 1611 * This function should be used by applications for which the
1612 * use of "GNUNET_FS_file_information_create_from_directory" 1612 * use of "GNUNET_FS_file_information_create_from_directory"
1613 * is not appropriate. 1613 * is not appropriate.
@@ -1620,7 +1620,7 @@ GNUNET_FS_file_information_create_from_directory (void *client_info,
1620 * keep this file available? Use 0 for maximum anonymity and 1620 * keep this file available? Use 0 for maximum anonymity and
1621 * minimum reliability... 1621 * minimum reliability...
1622 * @param expirationTime when should this content expire? 1622 * @param expirationTime when should this content expire?
1623 * @return share structure entry for the directory , NULL on error 1623 * @return publish structure entry for the directory , NULL on error
1624 */ 1624 */
1625struct GNUNET_FS_FileInformation * 1625struct GNUNET_FS_FileInformation *
1626GNUNET_FS_file_information_create_empty_directory (void *client_info, 1626GNUNET_FS_file_information_create_empty_directory (void *client_info,
@@ -1632,9 +1632,9 @@ GNUNET_FS_file_information_create_empty_directory (void *client_info,
1632 1632
1633 1633
1634/** 1634/**
1635 * Add an entry to a directory in a share-structure. Clients 1635 * Add an entry to a directory in a publish-structure. Clients
1636 * should never modify share structures that were passed to 1636 * should never modify publish structures that were passed to
1637 * "GNUNET_FS_share_start" already. 1637 * "GNUNET_FS_publish_start" already.
1638 * 1638 *
1639 * @param dir the directory 1639 * @param dir the directory
1640 * @param end the entry to add; the entry must not have been 1640 * @param end the entry to add; the entry must not have been
@@ -1648,9 +1648,9 @@ GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir,
1648 1648
1649 1649
1650/** 1650/**
1651 * Inspect a file or directory in a share-structure. Clients 1651 * Inspect a file or directory in a publish-structure. Clients
1652 * should never modify share structures that were passed to 1652 * should never modify publish structures that were passed to
1653 * "GNUNET_FS_share_start" already. When called on a directory, 1653 * "GNUNET_FS_publish_start" already. When called on a directory,
1654 * this function will FIRST call "proc" with information about 1654 * this function will FIRST call "proc" with information about
1655 * the directory itself and then for each of the files in the 1655 * the directory itself and then for each of the files in the
1656 * directory (but not for files in subdirectories). When called 1656 * directory (but not for files in subdirectories). When called
@@ -1668,8 +1668,8 @@ GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir,
1668 1668
1669 1669
1670/** 1670/**
1671 * Destroy share-structure. Clients should never destroy share 1671 * Destroy publish-structure. Clients should never destroy publish
1672 * structures that were passed to "GNUNET_FS_share_start" already. 1672 * structures that were passed to "GNUNET_FS_publish_start" already.
1673 * 1673 *
1674 * @param fi structure to destroy 1674 * @param fi structure to destroy
1675 * @param cleaner function to call on each entry in the structure 1675 * @param cleaner function to call on each entry in the structure
@@ -1684,21 +1684,21 @@ GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi,
1684 1684
1685 1685
1686/** 1686/**
1687 * Share a file or directory. 1687 * Publish a file or directory.
1688 * 1688 *
1689 * @param h handle to the file sharing subsystem 1689 * @param h handle to the file sharing subsystem
1690 * @param ctx initial value to use for the '*ctx' 1690 * @param ctx initial value to use for the '*ctx'
1691 * in the callback (for the GNUNET_FS_STATUS_SHARE_START event). 1691 * in the callback (for the GNUNET_FS_STATUS_PUBLISH_START event).
1692 * @param fi information about the file or directory structure to share 1692 * @param fi information about the file or directory structure to publish
1693 * @param namespace namespace to share the file in, NULL for no namespace 1693 * @param namespace namespace to publish the file in, NULL for no namespace
1694 * @param nid identifier to use for the shared content in the namespace 1694 * @param nid identifier to use for the publishd content in the namespace
1695 * (can be NULL, must be NULL if namespace is NULL) 1695 * (can be NULL, must be NULL if namespace is NULL)
1696 * @param nuid update-identifier that will be used for future updates 1696 * @param nuid update-identifier that will be used for future updates
1697 * (can be NULL, must be NULL if namespace or nid is NULL) 1697 * (can be NULL, must be NULL if namespace or nid is NULL)
1698 * @return context that can be used to control the share operation 1698 * @return context that can be used to control the publish operation
1699 */ 1699 */
1700struct GNUNET_FS_ShareContext * 1700struct GNUNET_FS_PublishContext *
1701GNUNET_FS_share_start (struct GNUNET_FS_Handle *h, 1701GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h,
1702 void *ctx, 1702 void *ctx,
1703 const struct GNUNET_FS_FileInformation *fi, 1703 const struct GNUNET_FS_FileInformation *fi,
1704 struct GNUNET_FS_Namespace *namespace, 1704 struct GNUNET_FS_Namespace *namespace,
@@ -1708,13 +1708,13 @@ GNUNET_FS_share_start (struct GNUNET_FS_Handle *h,
1708 1708
1709/** 1709/**
1710 * Stop an upload. Will abort incomplete uploads (but 1710 * Stop an upload. Will abort incomplete uploads (but
1711 * not remove blocks that have already been shared) or 1711 * not remove blocks that have already been publishd) or
1712 * simply clean up the state for completed uploads. 1712 * simply clean up the state for completed uploads.
1713 * 1713 *
1714 * @param sc context for the upload to stop 1714 * @param sc context for the upload to stop
1715 */ 1715 */
1716void 1716void
1717GNUNET_FS_share_stop (struct GNUNET_FS_ShareContext *sc); 1717GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *sc);
1718 1718
1719 1719
1720/** 1720/**
@@ -1840,9 +1840,8 @@ typedef void (*GNUNET_FS_NamespaceInfoProcessor) (void *cls,
1840 * @param h handle to the file sharing subsystem 1840 * @param h handle to the file sharing subsystem
1841 * @param cb function to call on each known namespace 1841 * @param cb function to call on each known namespace
1842 * @param cb_cls closure for cb 1842 * @param cb_cls closure for cb
1843 * @return GNUNET_SYSERR on error, otherwise the number of pseudonyms in list
1844 */ 1843 */
1845int 1844void
1846GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h, 1845GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h,
1847 GNUNET_FS_NamespaceInfoProcessor cb, 1846 GNUNET_FS_NamespaceInfoProcessor cb,
1848 void *cb_cls); 1847 void *cb_cls);