aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-04-30 13:16:03 +0000
committerChristian Grothoff <christian@grothoff.org>2010-04-30 13:16:03 +0000
commitd59ea5663203392637e84dea69feb9671ca2a3de (patch)
tree2898909b01cc22b9b031bb76b99d6cd262ab3ee3
parent4f2b474c1a9e51d71abe8d692fedddcb1d1e0ede (diff)
downloadgnunet-d59ea5663203392637e84dea69feb9671ca2a3de.tar.gz
gnunet-d59ea5663203392637e84dea69feb9671ca2a3de.zip
finishing initial coding of fs-publish serialization/deserialization
-rw-r--r--src/fs/fs.c197
-rw-r--r--src/fs/fs.h48
-rw-r--r--src/fs/fs_file_information.c106
3 files changed, 233 insertions, 118 deletions
diff --git a/src/fs/fs.c b/src/fs/fs.c
index 837f59a10..e7a52d235 100644
--- a/src/fs/fs.c
+++ b/src/fs/fs.c
@@ -20,7 +20,7 @@
20 20
21/** 21/**
22 * @file fs/fs.c 22 * @file fs/fs.c
23 * @brief main FS functions 23 * @brief main FS functions (master initialization, serialization, deserialization, shared code)
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 */ 25 */
26 26
@@ -214,6 +214,116 @@ GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh)
214} 214}
215 215
216 216
217
218
219/**
220 * Closure for "data_reader_file".
221 */
222struct FileInfo
223{
224 /**
225 * Name of the file to read.
226 */
227 char *filename;
228
229 /**
230 * File descriptor, NULL if it has not yet been opened.
231 */
232 struct GNUNET_DISK_FileHandle *fd;
233};
234
235
236/**
237 * Function that provides data by reading from a file.
238 *
239 * @param cls closure (points to the file information)
240 * @param offset offset to read from; it is possible
241 * that the caller might need to go backwards
242 * a bit at times
243 * @param max maximum number of bytes that should be
244 * copied to buf; readers are not allowed
245 * to provide less data unless there is an error;
246 * a value of "0" will be used at the end to allow
247 * the reader to clean up its internal state
248 * @param buf where the reader should write the data
249 * @param emsg location for the reader to store an error message
250 * @return number of bytes written, usually "max", 0 on error
251 */
252size_t
253GNUNET_FS_data_reader_file_(void *cls,
254 uint64_t offset,
255 size_t max,
256 void *buf,
257 char **emsg)
258{
259 struct FileInfo *fi = cls;
260 ssize_t ret;
261
262 if (max == 0)
263 {
264 if (fi->fd != NULL)
265 GNUNET_DISK_file_close (fi->fd);
266 GNUNET_free (fi->filename);
267 GNUNET_free (fi);
268 return 0;
269 }
270 if (fi->fd == NULL)
271 {
272 fi->fd = GNUNET_DISK_file_open (fi->filename,
273 GNUNET_DISK_OPEN_READ,
274 GNUNET_DISK_PERM_NONE);
275 if (fi->fd == NULL)
276 {
277 GNUNET_asprintf (emsg,
278 _("Could not open file `%s': %s"),
279 fi->filename,
280 STRERROR (errno));
281 return 0;
282 }
283 }
284 GNUNET_DISK_file_seek (fi->fd, offset, GNUNET_DISK_SEEK_SET);
285 ret = GNUNET_DISK_file_read (fi->fd, buf, max);
286 if (ret == -1)
287 {
288 GNUNET_asprintf (emsg,
289 _("Could not read file `%s': %s"),
290 fi->filename,
291 STRERROR (errno));
292 return 0;
293 }
294 if (ret != max)
295 {
296 GNUNET_asprintf (emsg,
297 _("Short read reading from file `%s'!"),
298 fi->filename);
299 return 0;
300 }
301 return max;
302}
303
304
305/**
306 * Create the closure for the 'GNUNET_FS_data_reader_file_' callback.
307 *
308 * @param filename file to read
309 * @return closure to use, NULL on error
310 */
311void *
312GNUNET_FS_make_file_reader_context_ (const char *filename)
313{
314 struct FileInfo *fi;
315
316 fi = GNUNET_malloc (sizeof(struct FileInfo));
317 fi->filename = GNUNET_STRINGS_filename_expand (filename);
318 if (fi->filename == NULL)
319 {
320 GNUNET_free (fi);
321 return NULL;
322 }
323 return fi;
324}
325
326
217/** 327/**
218 * Return the full filename where we would store state information 328 * Return the full filename where we would store state information
219 * (for serialization/deserialization). 329 * (for serialization/deserialization).
@@ -422,6 +532,8 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
422 files (!?) */ 532 files (!?) */
423 break; 533 break;
424 case 1: /* file-index, no hash */ 534 case 1: /* file-index, no hash */
535 if (NULL == ret->filename)
536 goto cleanup;
425 if (GNUNET_OK != 537 if (GNUNET_OK !=
426 GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) 538 GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size))
427 goto cleanup; 539 goto cleanup;
@@ -429,11 +541,12 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
429 ret->data.file.do_index = GNUNET_YES; 541 ret->data.file.do_index = GNUNET_YES;
430 ret->data.file.have_hash = GNUNET_NO; 542 ret->data.file.have_hash = GNUNET_NO;
431 ret->data.file.index_start_confirmed = GNUNET_NO; 543 ret->data.file.index_start_confirmed = GNUNET_NO;
432 /* FIXME: what's our approach for dealing with the 544 ret->data.file.reader = &GNUNET_FS_data_reader_file_;
433 'reader' and 'reader_cls' fields? 545 ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename);
434 (should be easy for indexing since we must have a file) */
435 break; 546 break;
436 case 2: /* file-index-with-hash */ 547 case 2: /* file-index-with-hash */
548 if (NULL == ret->filename)
549 goto cleanup;
437 if ( (GNUNET_OK != 550 if ( (GNUNET_OK !=
438 GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) || 551 GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) ||
439 (GNUNET_OK != 552 (GNUNET_OK !=
@@ -443,23 +556,24 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
443 ret->data.file.do_index = GNUNET_YES; 556 ret->data.file.do_index = GNUNET_YES;
444 ret->data.file.have_hash = GNUNET_YES; 557 ret->data.file.have_hash = GNUNET_YES;
445 ret->data.file.index_start_confirmed = GNUNET_NO; 558 ret->data.file.index_start_confirmed = GNUNET_NO;
446 /* FIXME: what's our approach for dealing with the 559 ret->data.file.reader = &GNUNET_FS_data_reader_file_;
447 'reader' and 'reader_cls' fields? 560 ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename);
448 (should be easy for indexing since we must have a file) */
449 break; 561 break;
450 case 3: /* file-index-with-hash-confirmed */ 562 case 3: /* file-index-with-hash-confirmed */
563 if (NULL == ret->filename)
564 goto cleanup;
451 if ( (GNUNET_OK != 565 if ( (GNUNET_OK !=
452 GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) || 566 GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) ||
453 (GNUNET_OK != 567 (GNUNET_OK !=
454 GNUNET_BIO_read (rh, "fileid", &ret->data.file.file_id, sizeof (GNUNET_HashCode))) ) 568 GNUNET_BIO_read (rh, "fileid", &ret->data.file.file_id, sizeof (GNUNET_HashCode))) )
455 goto cleanup; 569 goto cleanup;
570
456 ret->is_directory = GNUNET_NO; 571 ret->is_directory = GNUNET_NO;
457 ret->data.file.do_index = GNUNET_YES; 572 ret->data.file.do_index = GNUNET_YES;
458 ret->data.file.have_hash = GNUNET_YES; 573 ret->data.file.have_hash = GNUNET_YES;
459 ret->data.file.index_start_confirmed = GNUNET_YES; 574 ret->data.file.index_start_confirmed = GNUNET_YES;
460 /* FIXME: what's our approach for dealing with the 575 ret->data.file.reader = &GNUNET_FS_data_reader_file_;
461 'reader' and 'reader_cls' fields? 576 ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename);
462 (should be easy for indexing since we must have a file) */
463 break; 577 break;
464 case 4: /* directory */ 578 case 4: /* directory */
465 if ( (GNUNET_OK != 579 if ( (GNUNET_OK !=
@@ -507,7 +621,6 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
507 GNUNET_free_non_null (filename); 621 GNUNET_free_non_null (filename);
508 GNUNET_FS_file_information_destroy (ret, NULL, NULL); 622 GNUNET_FS_file_information_destroy (ret, NULL, NULL);
509 return NULL; 623 return NULL;
510
511} 624}
512 625
513 626
@@ -581,7 +694,8 @@ get_serialization_short_name (const char *fullname)
581 694
582 695
583/** 696/**
584 * Create a new random name for serialization. 697 * Create a new random name for serialization. Also checks if persistence
698 * is enabled and returns NULL if not.
585 * 699 *
586 * @param h master context 700 * @param h master context
587 * @param ext component of the path 701 * @param ext component of the path
@@ -595,7 +709,8 @@ make_serialization_file_name (struct GNUNET_FS_Handle *h,
595 char *dn; 709 char *dn;
596 char *ret; 710 char *ret;
597 711
598 /* FIXME: check if persistence option was set! */ 712 if (0 == (h->flags & GNUNET_FS_FLAGS_PERSISTENCE))
713 return NULL; /* persistence not requested */
599 dn = get_serialization_file_name (h, ext, ""); 714 dn = get_serialization_file_name (h, ext, "");
600 fn = GNUNET_DISK_mktemp (dn); 715 fn = GNUNET_DISK_mktemp (dn);
601 GNUNET_free (dn); 716 GNUNET_free (dn);
@@ -608,6 +723,44 @@ make_serialization_file_name (struct GNUNET_FS_Handle *h,
608 723
609 724
610/** 725/**
726 * Copy all of the data from the reader to the write handle.
727 *
728 * @param wh write handle
729 * @param fi file with reader
730 * @return GNUNET_OK on success
731 */
732static int
733copy_from_reader (struct GNUNET_BIO_WriteHandle *wh,
734 struct GNUNET_FS_FileInformation * fi)
735{
736 char buf[32 * 1024];
737 uint64_t off;
738 size_t ret;
739 char *emsg;
740
741 emsg = NULL;
742 off = 0;
743 while (off < fi->data.file.file_size)
744 {
745 ret = fi->data.file.reader (fi->data.file.reader_cls,
746 off, sizeof (buf),
747 buf,
748 &emsg);
749 if (ret == 0)
750 {
751 GNUNET_free (emsg);
752 return GNUNET_SYSERR;
753 }
754 if (GNUNET_OK !=
755 GNUNET_BIO_write (wh, buf, ret))
756 return GNUNET_SYSERR;
757 off += ret;
758 }
759 return GNUNET_OK;
760}
761
762
763/**
611 * Create a temporary file on disk to store the current 764 * Create a temporary file on disk to store the current
612 * state of "fi" in. 765 * state of "fi" in.
613 * 766 *
@@ -622,7 +775,6 @@ GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation * fi)
622 char *ksks; 775 char *ksks;
623 char *chks; 776 char *chks;
624 777
625 /* FIXME: check if persistence option was set! */
626 if (NULL == fi->serialization) 778 if (NULL == fi->serialization)
627 fi->serialization = make_serialization_file_name (fi->h, "publish-fi"); 779 fi->serialization = make_serialization_file_name (fi->h, "publish-fi");
628 if (NULL == fi->serialization) 780 if (NULL == fi->serialization)
@@ -684,27 +836,28 @@ GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation * fi)
684 if (GNUNET_OK != 836 if (GNUNET_OK !=
685 GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) 837 GNUNET_BIO_write_int64 (wh, fi->data.file.file_size))
686 goto cleanup; 838 goto cleanup;
687 /* FIXME: what's our approach for dealing with the 839 if ( (GNUNET_NO == fi->is_published) &&
688 'reader' and 'reader_cls' fields? I guess the only 840 (NULL == fi->filename) )
689 good way would be to dump "small" files into 841 if (GNUNET_OK !=
690 'rh' and to not support serialization of "large" 842 copy_from_reader (wh, fi))
691 files (!?) */ 843 goto cleanup;
692 break; 844 break;
693 case 1: /* file-index, no hash */ 845 case 1: /* file-index, no hash */
846 if (NULL == fi->filename)
847 goto cleanup;
694 if (GNUNET_OK != 848 if (GNUNET_OK !=
695 GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) 849 GNUNET_BIO_write_int64 (wh, fi->data.file.file_size))
696 goto cleanup; 850 goto cleanup;
697 break; 851 break;
698 case 2: /* file-index-with-hash */ 852 case 2: /* file-index-with-hash */
699 case 3: /* file-index-with-hash-confirmed */ 853 case 3: /* file-index-with-hash-confirmed */
854 if (NULL == fi->filename)
855 goto cleanup;
700 if ( (GNUNET_OK != 856 if ( (GNUNET_OK !=
701 GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) || 857 GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) ||
702 (GNUNET_OK != 858 (GNUNET_OK !=
703 GNUNET_BIO_write (wh, &fi->data.file.file_id, sizeof (GNUNET_HashCode))) ) 859 GNUNET_BIO_write (wh, &fi->data.file.file_id, sizeof (GNUNET_HashCode))) )
704 goto cleanup; 860 goto cleanup;
705 /* FIXME: what's our approach for dealing with the
706 'reader' and 'reader_cls' fields?
707 (should be easy for indexing since we must have a file) */
708 break; 861 break;
709 case 4: /* directory */ 862 case 4: /* directory */
710 if ( (GNUNET_OK != 863 if ( (GNUNET_OK !=
diff --git a/src/fs/fs.h b/src/fs/fs.h
index fa36b8f02..953e1e51b 100644
--- a/src/fs/fs.h
+++ b/src/fs/fs.h
@@ -431,11 +431,6 @@ struct GNUNET_FS_FileInformation
431 } data; 431 } data;
432 432
433 /** 433 /**
434 * Is this struct for a file or directory?
435 */
436 int is_directory;
437
438 /**
439 * Desired anonymity level. 434 * Desired anonymity level.
440 */ 435 */
441 uint32_t anonymity; 436 uint32_t anonymity;
@@ -445,6 +440,16 @@ struct GNUNET_FS_FileInformation
445 */ 440 */
446 uint32_t priority; 441 uint32_t priority;
447 442
443 /**
444 * Is this struct for a file or directory?
445 */
446 int is_directory;
447
448 /**
449 * Are we done publishing this file?
450 */
451 int is_published;
452
448}; 453};
449 454
450 455
@@ -563,6 +568,39 @@ void
563GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh); 568GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qh);
564 569
565 570
571/**
572 * Function that provides data by reading from a file.
573 *
574 * @param cls closure (points to the file information)
575 * @param offset offset to read from; it is possible
576 * that the caller might need to go backwards
577 * a bit at times
578 * @param max maximum number of bytes that should be
579 * copied to buf; readers are not allowed
580 * to provide less data unless there is an error;
581 * a value of "0" will be used at the end to allow
582 * the reader to clean up its internal state
583 * @param buf where the reader should write the data
584 * @param emsg location for the reader to store an error message
585 * @return number of bytes written, usually "max", 0 on error
586 */
587size_t
588GNUNET_FS_data_reader_file_(void *cls,
589 uint64_t offset,
590 size_t max,
591 void *buf,
592 char **emsg);
593
594
595/**
596 * Create the closure for the 'GNUNET_FS_data_reader_file_' callback.
597 *
598 * @param filename file to read
599 * @return closure to use
600 */
601void *
602GNUNET_FS_make_file_reader_context_ (const char *filename);
603
566 604
567/** 605/**
568 * Notification of FS that a search probe has made progress. 606 * Notification of FS that a search probe has made progress.
diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c
index 2d0194741..df5593f75 100644
--- a/src/fs/fs_file_information.c
+++ b/src/fs/fs_file_information.c
@@ -55,92 +55,6 @@ GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s)
55 55
56 56
57/** 57/**
58 * Closure for "data_reader_file".
59 */
60struct FileInfo
61{
62 /**
63 * Name of the file to read.
64 */
65 char *filename;
66
67 /**
68 * File descriptor, NULL if it has not yet been opened.
69 */
70 struct GNUNET_DISK_FileHandle *fd;
71};
72
73
74/**
75 * Function that provides data by reading from a file.
76 *
77 * @param cls closure (points to the file information)
78 * @param offset offset to read from; it is possible
79 * that the caller might need to go backwards
80 * a bit at times
81 * @param max maximum number of bytes that should be
82 * copied to buf; readers are not allowed
83 * to provide less data unless there is an error;
84 * a value of "0" will be used at the end to allow
85 * the reader to clean up its internal state
86 * @param buf where the reader should write the data
87 * @param emsg location for the reader to store an error message
88 * @return number of bytes written, usually "max", 0 on error
89 */
90static size_t
91data_reader_file(void *cls,
92 uint64_t offset,
93 size_t max,
94 void *buf,
95 char **emsg)
96{
97 struct FileInfo *fi = cls;
98 ssize_t ret;
99
100 if (max == 0)
101 {
102 if (fi->fd != NULL)
103 GNUNET_DISK_file_close (fi->fd);
104 GNUNET_free (fi->filename);
105 GNUNET_free (fi);
106 return 0;
107 }
108 if (fi->fd == NULL)
109 {
110 fi->fd = GNUNET_DISK_file_open (fi->filename,
111 GNUNET_DISK_OPEN_READ,
112 GNUNET_DISK_PERM_NONE);
113 if (fi->fd == NULL)
114 {
115 GNUNET_asprintf (emsg,
116 _("Could not open file `%s': %s"),
117 fi->filename,
118 STRERROR (errno));
119 return 0;
120 }
121 }
122 GNUNET_DISK_file_seek (fi->fd, offset, GNUNET_DISK_SEEK_SET);
123 ret = GNUNET_DISK_file_read (fi->fd, buf, max);
124 if (ret == -1)
125 {
126 GNUNET_asprintf (emsg,
127 _("Could not read file `%s': %s"),
128 fi->filename,
129 STRERROR (errno));
130 return 0;
131 }
132 if (ret != max)
133 {
134 GNUNET_asprintf (emsg,
135 _("Short read reading from file `%s'!"),
136 fi->filename);
137 return 0;
138 }
139 return max;
140}
141
142
143/**
144 * Create an entry for a file in a publish-structure. 58 * Create an entry for a file in a publish-structure.
145 * 59 *
146 * @param h handle to the file sharing subsystem 60 * @param h handle to the file sharing subsystem
@@ -182,17 +96,16 @@ GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h,
182 filename); 96 filename);
183 return NULL; 97 return NULL;
184 } 98 }
185 fi = GNUNET_malloc (sizeof(struct FileInfo)); 99 fi = GNUNET_FS_make_file_reader_context_ (filename);
186 fi->filename = GNUNET_STRINGS_filename_expand (filename); 100 if (fi == NULL)
187 if (fi->filename == NULL)
188 { 101 {
189 GNUNET_free (fi); 102 GNUNET_break (0);
190 return NULL; 103 return NULL;
191 } 104 }
192 ret = GNUNET_FS_file_information_create_from_reader (h, 105 ret = GNUNET_FS_file_information_create_from_reader (h,
193 client_info, 106 client_info,
194 sbuf.st_size, 107 sbuf.st_size,
195 &data_reader_file, 108 &GNUNET_FS_data_reader_file_,
196 fi, 109 fi,
197 keywords, 110 keywords,
198 meta, 111 meta,
@@ -284,6 +197,11 @@ GNUNET_FS_file_information_create_from_data (struct GNUNET_FS_Handle *h,
284 uint32_t priority, 197 uint32_t priority,
285 struct GNUNET_TIME_Absolute expirationTime) 198 struct GNUNET_TIME_Absolute expirationTime)
286{ 199{
200 if (GNUNET_YES == do_index)
201 {
202 GNUNET_break (0);
203 return NULL;
204 }
287 return GNUNET_FS_file_information_create_from_reader (h, 205 return GNUNET_FS_file_information_create_from_reader (h,
288 client_info, 206 client_info,
289 length, 207 length,
@@ -333,6 +251,12 @@ GNUNET_FS_file_information_create_from_reader (struct GNUNET_FS_Handle *h,
333{ 251{
334 struct GNUNET_FS_FileInformation *ret; 252 struct GNUNET_FS_FileInformation *ret;
335 253
254 if ( (GNUNET_YES == do_index) &&
255 (reader != &GNUNET_FS_data_reader_file_) )
256 {
257 GNUNET_break (0);
258 return NULL;
259 }
336 ret = GNUNET_malloc (sizeof (struct GNUNET_FS_FileInformation)); 260 ret = GNUNET_malloc (sizeof (struct GNUNET_FS_FileInformation));
337 ret->h = h; 261 ret->h = h;
338 ret->client_info = client_info; 262 ret->client_info = client_info;