diff options
-rw-r--r-- | TODO | 4 | ||||
-rw-r--r-- | src/fs/Makefile.am | 7 | ||||
-rw-r--r-- | src/fs/fs.c | 65 | ||||
-rw-r--r-- | src/fs/fs.h | 12 | ||||
-rw-r--r-- | src/fs/fs_directory.c | 7 | ||||
-rw-r--r-- | src/fs/fs_download.c | 923 | ||||
-rw-r--r-- | src/fs/fs_file_information.c | 269 | ||||
-rw-r--r-- | src/fs/fs_namespace.c | 729 | ||||
-rw-r--r-- | src/fs/fs_publish.c | 459 | ||||
-rw-r--r-- | src/fs/fs_search.c | 572 | ||||
-rw-r--r-- | src/fs/fs_test.c | 259 | ||||
-rw-r--r-- | src/fs/fs_unindex.c | 394 | ||||
-rw-r--r-- | src/fs/fs_uri.c | 133 | ||||
-rw-r--r-- | src/fs/test_fs_collection.c | 100 | ||||
-rw-r--r-- | src/fs/test_fs_collection_data.conf | 9 | ||||
-rw-r--r-- | src/fs/test_fs_directory.c | 7 | ||||
-rw-r--r-- | src/fs/test_fs_download.c | 324 | ||||
-rw-r--r-- | src/fs/test_fs_download_recursive.c | 380 | ||||
-rw-r--r-- | src/fs/test_fs_getopt.c | 7 | ||||
-rw-r--r-- | src/fs/test_fs_search_persistence.c | 213 | ||||
-rw-r--r-- | src/fs/test_fs_search_ranking.c | 250 | ||||
-rw-r--r-- | src/fs/test_fs_start_stop.c | 89 | ||||
-rw-r--r-- | src/fs/test_fs_uri.c | 46 | ||||
-rw-r--r-- | src/fs/test_namespace.c | 136 | ||||
-rw-r--r-- | src/include/gnunet_fs_service.h | 107 |
25 files changed, 5347 insertions, 154 deletions
@@ -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 | |||
13 | lib_LTLIBRARIES = libgnunetfs.la | 13 | lib_LTLIBRARIES = libgnunetfs.la |
14 | 14 | ||
15 | libgnunetfs_la_SOURCES = \ | 15 | libgnunetfs_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 | ||
21 | libgnunetfs_la_LIBADD = \ | 25 | libgnunetfs_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 | ||
78 | EXTRA_DIST = \ | 82 | EXTRA_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 | */ | ||
42 | struct GNUNET_FS_Handle * | ||
43 | GNUNET_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 | */ | ||
60 | void | ||
61 | GNUNET_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 | */ | ||
137 | struct 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 | |||
235 | void | ||
236 | GNUNET_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 | */ | ||
42 | struct 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 | */ | ||
86 | struct 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 | |||
201 | static int | ||
202 | content_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 | */ | ||
212 | static void | ||
213 | free_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 | */ | ||
253 | static int | ||
254 | read_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 | */ | ||
274 | static int | ||
275 | write_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 | */ | ||
300 | static void | ||
301 | add_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 | |||
314 | static void | ||
315 | signal_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 | */ | ||
329 | static void | ||
330 | delete_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 | */ | ||
344 | static unsigned int | ||
345 | get_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 | */ | ||
390 | static void | ||
391 | notify_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 | */ | ||
419 | static 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 | */ | ||
436 | static int | ||
437 | check_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 | */ | ||
476 | static void | ||
477 | iblock_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 | */ | ||
536 | static int | ||
537 | decrypt_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 | */ | ||
562 | static int | ||
563 | content_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 | */ | ||
626 | static char * | ||
627 | get_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 | */ | ||
698 | struct GNUNET_ECRS_DownloadContext * | ||
699 | GNUNET_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 | |||
826 | int | ||
827 | GNUNET_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 | */ | ||
858 | int | ||
859 | GNUNET_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 | */ | ||
903 | int | ||
904 | GNUNET_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 | */ | ||
45 | struct GNUNET_FS_FileInformation * | ||
46 | GNUNET_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 | */ | ||
73 | struct GNUNET_FS_FileInformation * | ||
74 | GNUNET_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 | */ | ||
105 | struct GNUNET_FS_FileInformation * | ||
106 | GNUNET_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 | */ | ||
140 | int | ||
141 | GNUNET_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 | */ | ||
170 | struct GNUNET_FS_FileInformation * | ||
171 | GNUNET_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 | */ | ||
198 | struct GNUNET_FS_FileInformation * | ||
199 | GNUNET_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 | */ | ||
221 | int | ||
222 | GNUNET_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 | */ | ||
243 | void | ||
244 | GNUNET_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 | */ | ||
261 | void | ||
262 | GNUNET_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 | */ | ||
46 | struct GNUNET_FS_Uri * | ||
47 | GNUNET_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 | */ | ||
68 | struct GNUNET_FS_Namespace * | ||
69 | GNUNET_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 | */ | ||
87 | int | ||
88 | GNUNET_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 | */ | ||
104 | void | ||
105 | GNUNET_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 | |||
152 | static char * | ||
153 | getPseudonymFileName (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 | */ | ||
190 | int | ||
191 | GNUNET_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 | */ | ||
209 | int | ||
210 | GNUNET_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 | */ | ||
237 | static int | ||
238 | write_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 | */ | ||
284 | struct GNUNET_ECRS_URI * | ||
285 | GNUNET_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 | |||
464 | static struct GNUNET_RSA_PrivateKey * | ||
465 | read_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 | */ | ||
518 | struct GNUNET_ECRS_URI * | ||
519 | GNUNET_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 | |||
625 | struct 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 | |||
634 | static int | ||
635 | processFile_ (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 | */ | ||
707 | int | ||
708 | GNUNET_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 | */ | ||
46 | static int | ||
47 | pushBlock (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 | */ | ||
113 | int | ||
114 | GNUNET_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; | ||
447 | FAILURE: | ||
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 | */ | ||
40 | struct 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 | */ | ||
63 | struct 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 | |||
101 | static int | ||
102 | receive_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 | */ | ||
109 | static void | ||
110 | add_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 | */ | ||
141 | static void | ||
142 | add_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 | */ | ||
223 | static int | ||
224 | process_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 | */ | ||
301 | static int | ||
302 | receive_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 | */ | ||
475 | struct GNUNET_ECRS_SearchContext * | ||
476 | GNUNET_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 | */ | ||
522 | void | ||
523 | GNUNET_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 | */ | ||
547 | int | ||
548 | GNUNET_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 | |||
35 | static char * | ||
36 | makeName (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 | |||
50 | static volatile enum GNUNET_FSUI_EventType lastEvent; | ||
51 | |||
52 | static struct GNUNET_MetaData *search_meta; | ||
53 | |||
54 | static struct GNUNET_ECRS_URI *search_uri; | ||
55 | |||
56 | static struct GNUNET_FSUI_Context *ctx; | ||
57 | |||
58 | static void * | ||
59 | eventCallback (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 | |||
103 | int | ||
104 | main (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 */ | ||
233 | FAILURE: | ||
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 | */ | ||
55 | static int | ||
56 | pushBlock (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 | */ | ||
108 | static int | ||
109 | undoSymlinking (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 | */ | ||
167 | int | ||
168 | GNUNET_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; | ||
384 | FAILURE: | ||
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; |
603 | ERR: | 651 | ERR: |
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; } | 31 | static struct GNUNET_CONFIGURATION_Handle *cfg; |
32 | 32 | ||
33 | int | 33 | static void* progress_cb (void *cls, |
34 | main (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 | |
41 | static void | ||
42 | task (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 */ | 90 | int |
95 | FAILURE: | 91 | main (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] | ||
2 | SERVICEHOME = /tmp/gnunet-test-fs-uri/ | ||
3 | DEFAULTCONFIG = /etc/gnunetd.conf | ||
4 | |||
5 | [gnunetd] | ||
6 | HOSTKEY = $SERVICEHOME/.hostkey | ||
7 | |||
8 | [TESTING] | ||
9 | WEAKRANDOM = 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 | |||
35 | static volatile int suspendRestart = 0; | ||
36 | |||
37 | static struct GNUNET_GE_Context *ectx; | ||
38 | |||
39 | static char * | ||
40 | makeName (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 | |||
58 | static volatile enum GNUNET_FSUI_EventType lastEvent; | ||
59 | static volatile enum GNUNET_FSUI_EventType waitForEvent; | ||
60 | static volatile int download_done; | ||
61 | static struct GNUNET_FSUI_Context *ctx; | ||
62 | static struct GNUNET_ECRS_URI *upURI; | ||
63 | static struct GNUNET_FSUI_DownloadList *download; | ||
64 | |||
65 | static void * | ||
66 | eventCallback (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 | |||
155 | int | ||
156 | main (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 */ | ||
292 | FAILURE: | ||
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 | |||
40 | static struct GNUNET_GE_Context *ectx; | ||
41 | |||
42 | volatile int download_done; | ||
43 | |||
44 | static char * | ||
45 | makeName (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 | |||
60 | static int | ||
61 | makeHierarchyHelper (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 | |||
124 | static char * | ||
125 | makeHierarchy (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 | |||
134 | static int | ||
135 | checkHierarchy (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 | |||
153 | static volatile enum GNUNET_FSUI_EventType lastEvent; | ||
154 | static volatile enum GNUNET_FSUI_EventType waitForEvent; | ||
155 | static struct GNUNET_FSUI_Context *ctx; | ||
156 | static struct GNUNET_ECRS_URI *upURI; | ||
157 | static struct GNUNET_FSUI_DownloadList *download; | ||
158 | |||
159 | static void * | ||
160 | eventCallback (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 | |||
255 | int | ||
256 | main (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 | } | ||
349 | FAILURE: | ||
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 @@ | |||
28 | int | 28 | int |
29 | main (int argc, char *argv[]) | 29 | main (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 | |||
37 | static struct GNUNET_GE_Context *ectx; | ||
38 | |||
39 | static struct GNUNET_FSUI_Context *ctx; | ||
40 | static struct GNUNET_FSUI_SearchList *search; | ||
41 | static int have_error; | ||
42 | |||
43 | static void * | ||
44 | eventCallback (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 | |||
123 | int | ||
124 | main (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 */ | ||
198 | FAILURE: | ||
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 | |||
35 | static char * | ||
36 | makeName (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 | |||
49 | static struct GNUNET_FSUI_SearchList *search; | ||
50 | |||
51 | static volatile enum GNUNET_FSUI_EventType lastEvent; | ||
52 | |||
53 | static volatile struct GNUNET_ECRS_URI *uri; | ||
54 | |||
55 | static volatile int availability; | ||
56 | |||
57 | static volatile unsigned int rank; | ||
58 | |||
59 | static volatile enum GNUNET_FSUI_EventType waitForEvent; | ||
60 | |||
61 | static void * | ||
62 | eventCallback (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 | |||
125 | int | ||
126 | main (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 */ | ||
231 | FAILURE: | ||
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 | |||
34 | static struct GNUNET_FSUI_Context *ctx; | ||
35 | |||
36 | static void * | ||
37 | eventCallback (void *cls, const GNUNET_FSUI_Event * event) | ||
38 | { | ||
39 | return NULL; | ||
40 | } | ||
41 | |||
42 | #define START_DAEMON 1 | ||
43 | |||
44 | int | ||
45 | main (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); | ||
78 | FAILURE: | ||
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 | |||
37 | static struct GNUNET_GC_Configuration *cfg; | ||
38 | |||
39 | static int match; | ||
40 | |||
41 | static int | ||
42 | spcb (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 | |||
57 | static int | ||
58 | tt (void *unused) | ||
59 | { | ||
60 | if (match == 1) | ||
61 | return GNUNET_SYSERR; | ||
62 | return GNUNET_OK; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | testNamespace () | ||
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 | |||
106 | int | ||
107 | main (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 | |||
441 | enum GNUNET_FS_Status | 441 | enum 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 | */ |
643 | struct GNUNET_FS_ShareContext; | 643 | struct 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 | */ |
1351 | typedef int (*GNUNET_FS_ProgressCallback) | 1351 | typedef 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 | */ |
1431 | struct GNUNET_FS_FileInformation * | 1431 | struct GNUNET_FS_FileInformation * |
1432 | GNUNET_FS_file_information_create_from_file (void *client_info, | 1432 | GNUNET_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 | */ |
1457 | struct GNUNET_FS_FileInformation * | 1457 | struct GNUNET_FS_FileInformation * |
1458 | GNUNET_FS_file_information_create_from_data (void *client_info, | 1458 | GNUNET_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 | */ |
1509 | struct GNUNET_FS_FileInformation * | 1509 | struct GNUNET_FS_FileInformation * |
1510 | GNUNET_FS_file_information_create_from_reader (void *client_info, | 1510 | GNUNET_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 | */ |
1600 | struct GNUNET_FS_FileInformation * | 1600 | struct GNUNET_FS_FileInformation * |
1601 | GNUNET_FS_file_information_create_from_directory (void *client_info, | 1601 | GNUNET_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 | */ |
1625 | struct GNUNET_FS_FileInformation * | 1625 | struct GNUNET_FS_FileInformation * |
1626 | GNUNET_FS_file_information_create_empty_directory (void *client_info, | 1626 | GNUNET_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 | */ |
1700 | struct GNUNET_FS_ShareContext * | 1700 | struct GNUNET_FS_PublishContext * |
1701 | GNUNET_FS_share_start (struct GNUNET_FS_Handle *h, | 1701 | GNUNET_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 | */ |
1716 | void | 1716 | void |
1717 | GNUNET_FS_share_stop (struct GNUNET_FS_ShareContext *sc); | 1717 | GNUNET_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 | */ |
1845 | int | 1844 | void |
1846 | GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h, | 1845 | GNUNET_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); |