aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_dirmetascan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/fs_dirmetascan.c')
-rw-r--r--src/fs/fs_dirmetascan.c217
1 files changed, 107 insertions, 110 deletions
diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c
index 115f99391..dd207e2c9 100644
--- a/src/fs/fs_dirmetascan.c
+++ b/src/fs/fs_dirmetascan.c
@@ -80,13 +80,12 @@ struct GNUNET_FS_DirScanner
80 /** 80 /**
81 * Task scheduled when we are done. 81 * Task scheduled when we are done.
82 */ 82 */
83 struct GNUNET_SCHEDULER_Task * stop_task; 83 struct GNUNET_SCHEDULER_Task *stop_task;
84 84
85 /** 85 /**
86 * Arguments for helper. 86 * Arguments for helper.
87 */ 87 */
88 char *args[4]; 88 char *args[4];
89
90}; 89};
91 90
92 91
@@ -151,11 +150,9 @@ advance (struct GNUNET_FS_ShareTreeItem *pos)
151 150
152 GNUNET_assert (NULL != pos); 151 GNUNET_assert (NULL != pos);
153 moved = 0; /* must not terminate, even on file, otherwise "normal" */ 152 moved = 0; /* must not terminate, even on file, otherwise "normal" */
154 while ( (pos->is_directory == GNUNET_YES) || 153 while ((pos->is_directory == GNUNET_YES) || (0 == moved))
155 (0 == moved) )
156 { 154 {
157 if ( (moved != -1) && 155 if ((moved != -1) && (NULL != pos->children_head))
158 (NULL != pos->children_head) )
159 { 156 {
160 pos = pos->children_head; 157 pos = pos->children_head;
161 moved = 1; /* can terminate if file */ 158 moved = 1; /* can terminate if file */
@@ -190,8 +187,8 @@ advance (struct GNUNET_FS_ShareTreeItem *pos)
190 */ 187 */
191static struct GNUNET_FS_ShareTreeItem * 188static struct GNUNET_FS_ShareTreeItem *
192expand_tree (struct GNUNET_FS_ShareTreeItem *parent, 189expand_tree (struct GNUNET_FS_ShareTreeItem *parent,
193 const char *filename, 190 const char *filename,
194 int is_directory) 191 int is_directory)
195{ 192{
196 struct GNUNET_FS_ShareTreeItem *chld; 193 struct GNUNET_FS_ShareTreeItem *chld;
197 size_t slen; 194 size_t slen;
@@ -200,20 +197,19 @@ expand_tree (struct GNUNET_FS_ShareTreeItem *parent,
200 chld->parent = parent; 197 chld->parent = parent;
201 chld->filename = GNUNET_strdup (filename); 198 chld->filename = GNUNET_strdup (filename);
202 GNUNET_asprintf (&chld->short_filename, 199 GNUNET_asprintf (&chld->short_filename,
203 "%s%s", 200 "%s%s",
204 GNUNET_STRINGS_get_short_name (filename), 201 GNUNET_STRINGS_get_short_name (filename),
205 is_directory == GNUNET_YES ? "/" : ""); 202 is_directory == GNUNET_YES ? "/" : "");
206 /* make sure we do not end with '//' */ 203 /* make sure we do not end with '//' */
207 slen = strlen (chld->short_filename); 204 slen = strlen (chld->short_filename);
208 if ( (slen >= 2) && 205 if ((slen >= 2) && (chld->short_filename[slen - 1] == '/') &&
209 (chld->short_filename[slen-1] == '/') && 206 (chld->short_filename[slen - 2] == '/'))
210 (chld->short_filename[slen-2] == '/') ) 207 chld->short_filename[slen - 1] = '\0';
211 chld->short_filename[slen-1] = '\0';
212 chld->is_directory = is_directory; 208 chld->is_directory = is_directory;
213 if (NULL != parent) 209 if (NULL != parent)
214 GNUNET_CONTAINER_DLL_insert (parent->children_head, 210 GNUNET_CONTAINER_DLL_insert (parent->children_head,
215 parent->children_tail, 211 parent->children_tail,
216 chld); 212 chld);
217 return chld; 213 return chld;
218} 214}
219 215
@@ -235,8 +231,9 @@ finish_scan (void *cls)
235 ds->helper = NULL; 231 ds->helper = NULL;
236 } 232 }
237 ds->progress_callback (ds->progress_callback_cls, 233 ds->progress_callback (ds->progress_callback_cls,
238 NULL, GNUNET_SYSERR, 234 NULL,
239 GNUNET_FS_DIRSCANNER_FINISHED); 235 GNUNET_SYSERR,
236 GNUNET_FS_DIRSCANNER_FINISHED);
240} 237}
241 238
242 239
@@ -251,8 +248,7 @@ finish_scan (void *cls)
251 * #GNUNET_SYSERR to stop further processing with error 248 * #GNUNET_SYSERR to stop further processing with error
252 */ 249 */
253static int 250static int
254process_helper_msgs (void *cls, 251process_helper_msgs (void *cls, const struct GNUNET_MessageHeader *msg)
255 const struct GNUNET_MessageHeader *msg)
256{ 252{
257 struct GNUNET_FS_DirScanner *ds = cls; 253 struct GNUNET_FS_DirScanner *ds = cls;
258 const char *filename; 254 const char *filename;
@@ -265,34 +261,31 @@ process_helper_msgs (void *cls,
265 (unsigned int) ntohs (msg->type)); 261 (unsigned int) ntohs (msg->type));
266#endif 262#endif
267 left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader); 263 left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader);
268 filename = (const char*) &msg[1]; 264 filename = (const char *) &msg[1];
269 switch (ntohs (msg->type)) 265 switch (ntohs (msg->type))
270 { 266 {
271 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE: 267 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE:
272 if (filename[left-1] != '\0') 268 if (filename[left - 1] != '\0')
273 { 269 {
274 GNUNET_break (0); 270 GNUNET_break (0);
275 break; 271 break;
276 } 272 }
277 ds->progress_callback (ds->progress_callback_cls, 273 ds->progress_callback (ds->progress_callback_cls,
278 filename, GNUNET_NO, 274 filename,
279 GNUNET_FS_DIRSCANNER_FILE_START); 275 GNUNET_NO,
276 GNUNET_FS_DIRSCANNER_FILE_START);
280 if (NULL == ds->toplevel) 277 if (NULL == ds->toplevel)
281 { 278 {
282 ds->toplevel = expand_tree (ds->pos, 279 ds->toplevel = expand_tree (ds->pos, filename, GNUNET_NO);
283 filename,
284 GNUNET_NO);
285 } 280 }
286 else 281 else
287 { 282 {
288 GNUNET_assert (NULL != ds->pos); 283 GNUNET_assert (NULL != ds->pos);
289 (void) expand_tree (ds->pos, 284 (void) expand_tree (ds->pos, filename, GNUNET_NO);
290 filename,
291 GNUNET_NO);
292 } 285 }
293 return GNUNET_OK; 286 return GNUNET_OK;
294 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY: 287 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY:
295 if (filename[left-1] != '\0') 288 if (filename[left - 1] != '\0')
296 { 289 {
297 GNUNET_break (0); 290 GNUNET_break (0);
298 break; 291 break;
@@ -301,29 +294,29 @@ process_helper_msgs (void *cls,
301 { 294 {
302 if (NULL == ds->pos) 295 if (NULL == ds->pos)
303 { 296 {
304 GNUNET_break (0); 297 GNUNET_break (0);
305 break; 298 break;
306 } 299 }
307 ds->pos = ds->pos->parent; 300 ds->pos = ds->pos->parent;
308 return GNUNET_OK; 301 return GNUNET_OK;
309 } 302 }
310 ds->progress_callback (ds->progress_callback_cls, 303 ds->progress_callback (ds->progress_callback_cls,
311 filename, GNUNET_YES, 304 filename,
312 GNUNET_FS_DIRSCANNER_FILE_START); 305 GNUNET_YES,
313 ds->pos = expand_tree (ds->pos, 306 GNUNET_FS_DIRSCANNER_FILE_START);
314 filename, 307 ds->pos = expand_tree (ds->pos, filename, GNUNET_YES);
315 GNUNET_YES);
316 if (NULL == ds->toplevel) 308 if (NULL == ds->toplevel)
317 ds->toplevel = ds->pos; 309 ds->toplevel = ds->pos;
318 return GNUNET_OK; 310 return GNUNET_OK;
319 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR: 311 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR:
320 break; 312 break;
321 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE: 313 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE:
322 if ('\0' != filename[left-1]) 314 if ('\0' != filename[left - 1])
323 break; 315 break;
324 ds->progress_callback (ds->progress_callback_cls, 316 ds->progress_callback (ds->progress_callback_cls,
325 filename, GNUNET_SYSERR, 317 filename,
326 GNUNET_FS_DIRSCANNER_FILE_IGNORED); 318 GNUNET_SYSERR,
319 GNUNET_FS_DIRSCANNER_FILE_IGNORED);
327 return GNUNET_OK; 320 return GNUNET_OK;
328 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE: 321 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE:
329 if (0 != left) 322 if (0 != left)
@@ -334,65 +327,66 @@ process_helper_msgs (void *cls,
334 if (NULL == ds->toplevel) 327 if (NULL == ds->toplevel)
335 break; 328 break;
336 ds->progress_callback (ds->progress_callback_cls, 329 ds->progress_callback (ds->progress_callback_cls,
337 NULL, GNUNET_SYSERR, 330 NULL,
338 GNUNET_FS_DIRSCANNER_ALL_COUNTED); 331 GNUNET_SYSERR,
332 GNUNET_FS_DIRSCANNER_ALL_COUNTED);
339 ds->pos = ds->toplevel; 333 ds->pos = ds->toplevel;
340 if (GNUNET_YES == ds->pos->is_directory) 334 if (GNUNET_YES == ds->pos->is_directory)
341 ds->pos = advance (ds->pos); 335 ds->pos = advance (ds->pos);
342 return GNUNET_OK; 336 return GNUNET_OK;
343 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA: 337 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA: {
344 { 338 size_t nlen;
345 size_t nlen; 339 const char *end;
346 const char *end;
347 340
348 if (NULL == ds->pos) 341 if (NULL == ds->pos)
349 { 342 {
350 GNUNET_break (0); 343 GNUNET_break (0);
351 break; 344 break;
352 } 345 }
353 end = memchr (filename, 0, left); 346 end = memchr (filename, 0, left);
354 if (NULL == end) 347 if (NULL == end)
355 { 348 {
356 GNUNET_break (0); 349 GNUNET_break (0);
357 break; 350 break;
358 } 351 }
359 end++; 352 end++;
360 nlen = end - filename; 353 nlen = end - filename;
361 left -= nlen; 354 left -= nlen;
362 if (0 != strcmp (filename, 355 if (0 != strcmp (filename, ds->pos->filename))
363 ds->pos->filename)) 356 {
364 { 357 GNUNET_break (0);
365 GNUNET_break (0); 358 break;
366 break; 359 }
367 } 360 ds->progress_callback (ds->progress_callback_cls,
368 ds->progress_callback (ds->progress_callback_cls, 361 filename,
369 filename, 362 GNUNET_YES,
370 GNUNET_YES, 363 GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED);
371 GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED); 364 if (0 < left)
372 if (0 < left) 365 {
366 ds->pos->meta = GNUNET_CONTAINER_meta_data_deserialize (end, left);
367 if (NULL == ds->pos->meta)
373 { 368 {
374 ds->pos->meta = GNUNET_CONTAINER_meta_data_deserialize (end, 369 GNUNET_break (0);
375 left); 370 break;
376 if (NULL == ds->pos->meta)
377 {
378 GNUNET_break (0);
379 break;
380 }
381 /* having full filenames is too dangerous; always make sure we clean them up */
382 GNUNET_CONTAINER_meta_data_delete (ds->pos->meta,
383 EXTRACTOR_METATYPE_FILENAME,
384 NULL, 0);
385 /* instead, put in our 'safer' original filename */
386 GNUNET_CONTAINER_meta_data_insert (ds->pos->meta, "<libgnunetfs>",
387 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
388 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
389 ds->pos->short_filename,
390 strlen (ds->pos->short_filename) + 1);
391 } 371 }
392 ds->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (ds->pos->meta); 372 /* having full filenames is too dangerous; always make sure we clean them up */
393 ds->pos = advance (ds->pos); 373 GNUNET_CONTAINER_meta_data_delete (ds->pos->meta,
394 return GNUNET_OK; 374 EXTRACTOR_METATYPE_FILENAME,
375 NULL,
376 0);
377 /* instead, put in our 'safer' original filename */
378 GNUNET_CONTAINER_meta_data_insert (ds->pos->meta,
379 "<libgnunetfs>",
380 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
381 EXTRACTOR_METAFORMAT_UTF8,
382 "text/plain",
383 ds->pos->short_filename,
384 strlen (ds->pos->short_filename) + 1);
395 } 385 }
386 ds->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (ds->pos->meta);
387 ds->pos = advance (ds->pos);
388 return GNUNET_OK;
389 }
396 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED: 390 case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED:
397 if (NULL != ds->pos) 391 if (NULL != ds->pos)
398 { 392 {
@@ -406,16 +400,16 @@ process_helper_msgs (void *cls,
406 } 400 }
407 if (NULL == ds->toplevel) 401 if (NULL == ds->toplevel)
408 break; 402 break;
409 ds->stop_task = GNUNET_SCHEDULER_add_now (&finish_scan, 403 ds->stop_task = GNUNET_SCHEDULER_add_now (&finish_scan, ds);
410 ds);
411 return GNUNET_OK; 404 return GNUNET_OK;
412 default: 405 default:
413 GNUNET_break (0); 406 GNUNET_break (0);
414 break; 407 break;
415 } 408 }
416 ds->progress_callback (ds->progress_callback_cls, 409 ds->progress_callback (ds->progress_callback_cls,
417 NULL, GNUNET_SYSERR, 410 NULL,
418 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); 411 GNUNET_SYSERR,
412 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR);
419 return GNUNET_OK; 413 return GNUNET_OK;
420} 414}
421 415
@@ -434,8 +428,9 @@ helper_died_cb (void *cls)
434 if (NULL != ds->stop_task) 428 if (NULL != ds->stop_task)
435 return; /* normal death, was finished */ 429 return; /* normal death, was finished */
436 ds->progress_callback (ds->progress_callback_cls, 430 ds->progress_callback (ds->progress_callback_cls,
437 NULL, GNUNET_SYSERR, 431 NULL,
438 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); 432 GNUNET_SYSERR,
433 GNUNET_FS_DIRSCANNER_INTERNAL_ERROR);
439} 434}
440 435
441 436
@@ -452,22 +447,23 @@ helper_died_cb (void *cls)
452 */ 447 */
453struct GNUNET_FS_DirScanner * 448struct GNUNET_FS_DirScanner *
454GNUNET_FS_directory_scan_start (const char *filename, 449GNUNET_FS_directory_scan_start (const char *filename,
455 int disable_extractor, const char *ex, 450 int disable_extractor,
456 GNUNET_FS_DirScannerProgressCallback cb, 451 const char *ex,
457 void *cb_cls) 452 GNUNET_FS_DirScannerProgressCallback cb,
453 void *cb_cls)
458{ 454{
459 struct stat sbuf; 455 struct stat sbuf;
460 char *filename_expanded; 456 char *filename_expanded;
461 struct GNUNET_FS_DirScanner *ds; 457 struct GNUNET_FS_DirScanner *ds;
462 458
463 if (0 != STAT (filename, &sbuf)) 459 if (0 != stat (filename, &sbuf))
464 return NULL; 460 return NULL;
465 filename_expanded = GNUNET_STRINGS_filename_expand (filename); 461 filename_expanded = GNUNET_STRINGS_filename_expand (filename);
466 if (NULL == filename_expanded) 462 if (NULL == filename_expanded)
467 return NULL; 463 return NULL;
468 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
469 "Starting to scan directory `%s'\n", 465 "Starting to scan directory `%s'\n",
470 filename_expanded); 466 filename_expanded);
471 ds = GNUNET_new (struct GNUNET_FS_DirScanner); 467 ds = GNUNET_new (struct GNUNET_FS_DirScanner);
472 ds->progress_callback = cb; 468 ds->progress_callback = cb;
473 ds->progress_callback_cls = cb_cls; 469 ds->progress_callback_cls = cb_cls;
@@ -481,12 +477,13 @@ GNUNET_FS_directory_scan_start (const char *filename,
481 ds->args[2] = ds->ex_arg; 477 ds->args[2] = ds->ex_arg;
482 ds->args[3] = NULL; 478 ds->args[3] = NULL;
483 ds->helper = GNUNET_HELPER_start (GNUNET_NO, 479 ds->helper = GNUNET_HELPER_start (GNUNET_NO,
484 "gnunet-helper-fs-publish", 480 "gnunet-helper-fs-publish",
485 ds->args, 481 ds->args,
486 &process_helper_msgs, 482 &process_helper_msgs,
487 &helper_died_cb, ds); 483 &helper_died_cb,
484 ds);
488 if (NULL == ds->helper) 485 if (NULL == ds->helper)
489 { 486 {
490 GNUNET_free (filename_expanded); 487 GNUNET_free (filename_expanded);
491 GNUNET_free (ds); 488 GNUNET_free (ds);
492 return NULL; 489 return NULL;