aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2009-08-25 10:59:00 +0000
committerChristian Grothoff <christian@grothoff.org>2009-08-25 10:59:00 +0000
commit9cbff87bf9b68c08242b1a6a79221311dc157fc0 (patch)
tree6dacb93610d32de7f16e71765874fe2fb6e3a704
parent3d0444f9e6d64d6bc6b109cb743b9e08abcada0e (diff)
downloadgnunet-9cbff87bf9b68c08242b1a6a79221311dc157fc0.tar.gz
gnunet-9cbff87bf9b68c08242b1a6a79221311dc157fc0.zip
hxing
-rw-r--r--BUGS1
-rw-r--r--TODO11
-rw-r--r--src/fs/fs.c37
-rw-r--r--src/fs/fs.h39
-rw-r--r--src/fs/fs_file_information.c44
-rw-r--r--src/include/gnunet_bio_lib.h26
-rw-r--r--src/include/gnunet_fs_service.h36
-rw-r--r--src/util/bio.c633
8 files changed, 454 insertions, 373 deletions
diff --git a/BUGS b/BUGS
index a6339547e..6271eb2f1 100644
--- a/BUGS
+++ b/BUGS
@@ -6,6 +6,7 @@ sane end-user should care about this codebase yet anyway.
6* UTIL: 6* UTIL:
7 - crypto_hash: use libgcrypt (supports SHA-512 since 2003) 7 - crypto_hash: use libgcrypt (supports SHA-512 since 2003)
8 - container_bloomfilter: improve efficiency (see FIXME) 8 - container_bloomfilter: improve efficiency (see FIXME)
9 - no tests for BIO
9 - Windows: use events instead of pipes to signal select()s [Nils] 10 - Windows: use events instead of pipes to signal select()s [Nils]
10 - only connect() sockets that are ready (select()) [Nils] 11 - only connect() sockets that are ready (select()) [Nils]
11 [On W32, we need to select after calling socket before 12 [On W32, we need to select after calling socket before
diff --git a/TODO b/TODO
index 94fc5d4e5..889bdcea5 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
1Implementable right now (but not necessarily important), with caveats 1Implementable right now (but not necessarily important), with caveats
2(unavailable components that will limit what can be implemented right 2(unavailable components that will limit what can be implemented right
3away), in order in which they will likely be done: 3away), in order in which they will likely be done:
4* Buffered IO library (extend gnunet_disk_lib.h?)
5* TESTING 4* TESTING
6* FS (DHT not available) 5* FS (DHT not available)
7* SETUP 6* SETUP
@@ -42,16 +41,16 @@ PHASE #2: (Goal: recover basic file-sharing functionality)
42 - implement FS library 41 - implement FS library
43 + URI API -- DONE (but do more testing) 42 + URI API -- DONE (but do more testing)
44 + getopt API -- DONE (but do more testing) 43 + getopt API -- DONE (but do more testing)
45 + persistence mechanism 44 + persistence mechanism (design done)
46 + sharing API 45 + sharing API
47 ~ file-information 46 ~ file-information (almost done, needs testing)
48 ~ insert 47 ~ insert
49 ~ download
50 ~ search 48 ~ search
51 ~ unindex 49 ~ download
50 ~ unindex & list indexed!!!
52 ~ namespaces 51 ~ namespaces
53 ~ collection 52 ~ collection
54 + directory API 53 + directory API (builder API unclear)
55 - design network structs (P2P) 54 - design network structs (P2P)
56 - datastore request queueing mechanism 55 - datastore request queueing mechanism
57 - implement FS service (needs DHT) 56 - implement FS service (needs DHT)
diff --git a/src/fs/fs.c b/src/fs/fs.c
index 0522b7941..157f4ef22 100644
--- a/src/fs/fs.c
+++ b/src/fs/fs.c
@@ -29,7 +29,6 @@
29#include "fs.h" 29#include "fs.h"
30 30
31 31
32
33/** 32/**
34 * Setup a connection to the file-sharing service. 33 * Setup a connection to the file-sharing service.
35 * 34 *
@@ -46,7 +45,35 @@ GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched,
46 GNUNET_FS_ProgressCallback upcb, 45 GNUNET_FS_ProgressCallback upcb,
47 void *upcb_cls) 46 void *upcb_cls)
48{ 47{
49 return NULL; 48 struct GNUNET_FS_Handle *ret;
49 struct GNUNET_CLIENT_Connection *client;
50
51 client = GNUNET_CLIENT_connect (sched,
52 "fs",
53 cfg);
54 if (NULL == client)
55 return NULL;
56 ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Handle));
57 ret->sched = sched;
58 ret->cfg = cfg;
59 ret->client_name = GNUNET_strdup (client_name);
60 ret->upcb = upcb;
61 ret->upcb_cls = upcb_cls;
62 ret->client = client;
63 // FIXME: setup receive-loop with client
64 // FIXME: deserialize state; use client-name to find master-directory!
65 // Deserialize-Upload:
66 // * read FNs for upload FIs, deserialize each
67 // Deserialize Search:
68 // * read search queries
69 // * for each query, read file with search results
70 // * for each search result with active download, deserialize download
71 // * for each directory search result, check for active downloads of contents
72 // Deserialize Download:
73 // * always part of search???
74 // Deserialize Unindex:
75 // * read FNs for unindex with progress offset
76 return ret;
50} 77}
51 78
52 79
@@ -60,6 +87,12 @@ GNUNET_FS_start (struct GNUNET_SCHEDULER_Handle *sched,
60void 87void
61GNUNET_FS_stop (struct GNUNET_FS_Handle *h) 88GNUNET_FS_stop (struct GNUNET_FS_Handle *h)
62{ 89{
90 // FIXME: serialize state!? (or is it always serialized???)
91 // FIXME: terminate receive-loop with client
92 GNUNET_CLIENT_disconnect (h->client);
93 GNUNET_free (h->client_name);
94 GNUNET_free (h);
63} 95}
64 96
97
65/* end of fs.c */ 98/* end of fs.c */
diff --git a/src/fs/fs.h b/src/fs/fs.h
index 0c82d5831..1a8a6b0f7 100644
--- a/src/fs/fs.h
+++ b/src/fs/fs.h
@@ -279,4 +279,43 @@ struct GNUNET_FS_FileInformation
279}; 279};
280 280
281 281
282/**
283 * Master context for most FS operations.
284 */
285struct GNUNET_FS_Handle
286{
287 /**
288 * Scheduler.
289 */
290 struct GNUNET_SCHEDULER_Handle *sched;
291
292 /**
293 * Configuration to use.
294 */
295 const struct GNUNET_CONFIGURATION_Handle *cfg;
296
297 /**
298 * Name of our client.
299 */
300 char *client_name;
301
302 /**
303 * Function to call with updates on our progress.
304 */
305 GNUNET_FS_ProgressCallback upcb;
306
307 /**
308 * Closure for upcb.
309 */
310 void *upcb_cls;
311
312 /**
313 * Connection to the FS service.
314 */
315 struct GNUNET_CLIENT_Connection *client;
316
317
318};
319
320
282#endif 321#endif
diff --git a/src/fs/fs_file_information.c b/src/fs/fs_file_information.c
index 9b806184b..540b518dc 100644
--- a/src/fs/fs_file_information.c
+++ b/src/fs/fs_file_information.c
@@ -24,7 +24,6 @@
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * TODO: 26 * TODO:
27 * - publishing progress update API (increment offset, serialize)
28 * - serialization/deserialization (& deserialization API) 27 * - serialization/deserialization (& deserialization API)
29 * - metadata filename clean up code 28 * - metadata filename clean up code
30 * - metadata/ksk generation for directories from contained files 29 * - metadata/ksk generation for directories from contained files
@@ -36,15 +35,15 @@
36 35
37 36
38/** 37/**
39 * Create a temporary file disk to store the current 38 * Create a temporary file on disk to store the current
40 * state of "fi" in. 39 * state of "fi" in.
41 */ 40 */
42static void 41void
43fi_sync (struct GNUNET_FS_FileInformation * fi) 42GNUNET_FS_file_information_sync (struct GNUNET_FS_FileInformation * fi)
44{ 43{
45 if (NULL == fi->serialization) 44 if (NULL == fi->serialization)
46 { 45 {
47 fi->serialization = NULL; // FIXME 46 fi->serialization = NULL; // FIXME -- need cfg!
48 } 47 }
49 // FIXME... 48 // FIXME...
50} 49}
@@ -57,8 +56,8 @@ fi_sync (struct GNUNET_FS_FileInformation * fi)
57 * @param filename name of the file to use 56 * @param filename name of the file to use
58 * @return NULL on error 57 * @return NULL on error
59 */ 58 */
60static struct GNUNET_FS_FileInformation * 59struct GNUNET_FS_FileInformation *
61fi_load (const char *filename) 60GNUNET_FS_file_information_recover (const char *name)
62{ 61{
63 struct GNUNET_FS_FileInformation *ret; 62 struct GNUNET_FS_FileInformation *ret;
64 // FIXME! 63 // FIXME!
@@ -67,6 +66,25 @@ fi_load (const char *filename)
67 66
68 67
69/** 68/**
69 * Obtain the name under which this file information
70 * structure is stored on disk. Only works for top-level
71 * file information structures.
72 *
73 * @param s structure to get the filename for
74 * @return NULL on error, otherwise filename that
75 * can be passed to "GNUNET_FS_file_information_recover"
76 * to read this fi-struct from disk.
77 */
78const char *
79GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s)
80{
81 if (NULL != s->dir)
82 return NULL;
83 return s->serialization;
84}
85
86
87/**
70 * Closure for "data_reader_file". 88 * Closure for "data_reader_file".
71 */ 89 */
72struct FileInfo 90struct FileInfo
@@ -320,7 +338,7 @@ GNUNET_FS_file_information_create_from_reader (void *client_info,
320 ret->data.file.do_index = do_index; 338 ret->data.file.do_index = do_index;
321 ret->anonymity = anonymity; 339 ret->anonymity = anonymity;
322 ret->priority = priority; 340 ret->priority = priority;
323 fi_sync (ret); 341 GNUNET_FS_file_information_sync (ret);
324 return ret; 342 return ret;
325} 343}
326 344
@@ -609,10 +627,10 @@ GNUNET_FS_file_information_create_from_directory (void *client_info,
609 while (dc.entries != NULL) 627 while (dc.entries != NULL)
610 { 628 {
611 dc.entries->dir = ret; 629 dc.entries->dir = ret;
612 fi_sync (dc.entries); 630 GNUNET_FS_file_information_sync (dc.entries);
613 dc.entries = dc.entries->next; 631 dc.entries = dc.entries->next;
614 } 632 }
615 fi_sync (ret); 633 GNUNET_FS_file_information_sync (ret);
616 return ret; 634 return ret;
617} 635}
618 636
@@ -651,7 +669,7 @@ GNUNET_FS_file_information_create_empty_directory (void *client_info,
651 ret->is_directory = GNUNET_YES; 669 ret->is_directory = GNUNET_YES;
652 ret->anonymity = anonymity; 670 ret->anonymity = anonymity;
653 ret->priority = priority; 671 ret->priority = priority;
654 fi_sync (ret); 672 GNUNET_FS_file_information_sync (ret);
655 return ret; 673 return ret;
656} 674}
657 675
@@ -683,8 +701,8 @@ GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir,
683 dir->data.dir.entries = ent; 701 dir->data.dir.entries = ent;
684 dir->data.dir.dir_size = 0; 702 dir->data.dir.dir_size = 0;
685 dir->publish_offset = 0; 703 dir->publish_offset = 0;
686 fi_sync (ent); 704 GNUNET_FS_file_information_sync (ent);
687 fi_sync (dir); 705 GNUNET_FS_file_information_sync (dir);
688 return GNUNET_OK; 706 return GNUNET_OK;
689} 707}
690 708
diff --git a/src/include/gnunet_bio_lib.h b/src/include/gnunet_bio_lib.h
index 02b04570e..2765b4695 100644
--- a/src/include/gnunet_bio_lib.h
+++ b/src/include/gnunet_bio_lib.h
@@ -71,12 +71,12 @@ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h,
71 * @param what describes what is being read (for error message creation) 71 * @param what describes what is being read (for error message creation)
72 * @param result the buffer to write the result to 72 * @param result the buffer to write the result to
73 * @param len the number of bytes to read 73 * @param len the number of bytes to read
74 * @return len on success, GNUNET_SYSERR on failure 74 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
75 */ 75 */
76ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, 76int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
77 const char *what, 77 const char *what,
78 void *result, 78 void *result,
79 size_t len); 79 size_t len);
80 80
81/** 81/**
82 * Read 0-terminated string from a file. 82 * Read 0-terminated string from a file.
@@ -85,11 +85,13 @@ ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
85 * @param what describes what is being read (for error message creation) 85 * @param what describes what is being read (for error message creation)
86 * @param result the buffer to store a pointer to the (allocated) string to 86 * @param result the buffer to store a pointer to the (allocated) string to
87 * (note that *result could be set to NULL as well) 87 * (note that *result could be set to NULL as well)
88 * @param maxLen maximum allowed length for the string
88 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 89 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
89 */ 90 */
90int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, 91int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
91 const char *what, 92 const char *what,
92 char **result); 93 char **result,
94 size_t maxLen);
93 95
94 96
95/** 97/**
@@ -198,9 +200,9 @@ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h);
198 * @param n number of bytes to write 200 * @param n number of bytes to write
199 * @return GNUNET_OK on success, GNUNET_SYSERR on error 201 * @return GNUNET_OK on success, GNUNET_SYSERR on error
200 */ 202 */
201ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, 203int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
202 const void *buffer, 204 const void *buffer,
203 size_t n); 205 size_t n);
204 206
205 207
206/** 208/**
@@ -244,7 +246,7 @@ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
244 * @param h hande to open file 246 * @param h hande to open file
245 * @param f double to write (must be a variable) 247 * @param f double to write (must be a variable)
246 */ 248 */
247#define GNUNET_BIO_write_float(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double))) 249#define GNUNET_BIO_write_double(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double)))
248 250
249 251
250/** 252/**
@@ -254,7 +256,7 @@ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
254 * @param i address of 32-bit integer to write 256 * @param i address of 32-bit integer to write
255 * @return GNUNET_OK on success, GNUNET_SYSERR on error 257 * @return GNUNET_OK on success, GNUNET_SYSERR on error
256 */ 258 */
257int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, 259int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h,
258 int32_t i); 260 int32_t i);
259 261
260 262
@@ -265,7 +267,7 @@ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h,
265 * @param i address of 64-bit integer to write 267 * @param i address of 64-bit integer to write
266 * @return GNUNET_OK on success, GNUNET_SYSERR on error 268 * @return GNUNET_OK on success, GNUNET_SYSERR on error
267 */ 269 */
268int GNUNET_BIO_write_int64 (struct GNUNET_BIO_ReadHandle *h, 270int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h,
269 int64_t i); 271 int64_t i);
270 272
271 273
diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h
index 45cd1e77e..7c6fc0549 100644
--- a/src/include/gnunet_fs_service.h
+++ b/src/include/gnunet_fs_service.h
@@ -1415,6 +1415,42 @@ typedef int (*GNUNET_FS_FileInformationProcessor)(void *cls,
1415 1415
1416 1416
1417/** 1417/**
1418 * Recover file information structure from disk.
1419 *
1420 * @param name filename for the structure on disk
1421 * @return NULL on error
1422 */
1423struct GNUNET_FS_FileInformation *
1424GNUNET_FS_file_information_recover (const char *name);
1425
1426
1427/**
1428 * Obtain the name under which this file information
1429 * structure is stored on disk. Only works for top-level
1430 * file information structures.
1431 *
1432 * @param s structure to get the filename for
1433 * @return NULL on error, otherwise filename that
1434 * can be passed to "GNUNET_FS_file_information_recover"
1435 * to read this fi-struct from disk.
1436 */
1437const char *
1438GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s);
1439
1440
1441/**
1442 * Synchronize this file-information struct with its mirror
1443 * on disk. Note that all internal FS-operations that change
1444 * file information data should already call "sync" internally,
1445 * so this function is likely not useful for clients.
1446 *
1447 * @param s the struct to sync
1448 */
1449void
1450GNUNET_FS_file_information_sync (struct GNUNET_FS_FileInformation *s);
1451
1452
1453/**
1418 * Create an entry for a file in a publish-structure. 1454 * Create an entry for a file in a publish-structure.
1419 * 1455 *
1420 * @param filename name of the file or directory to publish 1456 * @param filename name of the file or directory to publish
diff --git a/src/util/bio.c b/src/util/bio.c
index 060b6f94b..8c3daed15 100644
--- a/src/util/bio.c
+++ b/src/util/bio.c
@@ -17,8 +17,6 @@
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19*/ 19*/
20
21
22/** 20/**
23 * @file util/bio.c 21 * @file util/bio.c
24 * @brief functions for buffering IO 22 * @brief functions for buffering IO
@@ -26,13 +24,23 @@
26 */ 24 */
27#include "platform.h" 25#include "platform.h"
28#include "gnunet_bio_lib.h" 26#include "gnunet_bio_lib.h"
27#include "gnunet_disk_lib.h"
28
29#define BIO_BUFFER_SIZE 65536
29 30
31#define MAX_META_DATA (1024 * 1024)
30 32
31/** 33/**
32 * Handle for buffered reading. 34 * Handle for buffered reading.
33 */ 35 */
34struct GNUNET_BIO_ReadHandle 36struct GNUNET_BIO_ReadHandle
35{ 37{
38 struct GNUNET_DISK_FileHandle *fd;
39 char *emsg;
40 char *buffer;
41 size_t have;
42 size_t size;
43 off_t pos;
36}; 44};
37 45
38 46
@@ -42,9 +50,20 @@ struct GNUNET_BIO_ReadHandle
42 * @param fn file name to be opened 50 * @param fn file name to be opened
43 * @return IO handle on success, NULL on error 51 * @return IO handle on success, NULL on error
44 */ 52 */
45struct GNUNET_BIO_ReadHandle *GNUNET_BIO_read_open (const char *fn) 53struct GNUNET_BIO_ReadHandle *
54GNUNET_BIO_read_open (const char *fn)
46{ 55{
47 return NULL; 56 struct GNUNET_DISK_FileHandle *fd;
57 struct GNUNET_BIO_ReadHandle *h;
58
59 fd = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ);
60 if (NULL == fd)
61 return NULL;
62 h = GNUNET_malloc (sizeof(struct GNUNET_BIO_ReadHandle) + BIO_BUFFER_SIZE);
63 h->buffer = (char*) &h[1];
64 h->size = BIO_BUFFER_SIZE;
65 h->fd = fd;
66 return h;
48} 67}
49 68
50 69
@@ -59,7 +78,10 @@ struct GNUNET_BIO_ReadHandle *GNUNET_BIO_read_open (const char *fn)
59int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, 78int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h,
60 char **emsg) 79 char **emsg)
61{ 80{
62 return GNUNET_SYSERR; 81 *emsg = h->emsg;
82 GNUNET_DISK_file_close (h->fd);
83 GNUNET_free (h);
84 return (NULL == *emsg) ? GNUNET_OK : GNUNET_SYSERR;
63} 85}
64 86
65 87
@@ -70,13 +92,61 @@ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h,
70 * @param what describes what is being read (for error message creation) 92 * @param what describes what is being read (for error message creation)
71 * @param result the buffer to write the result to 93 * @param result the buffer to write the result to
72 * @param len the number of bytes to read 94 * @param len the number of bytes to read
73 * @return len on success, GNUNET_SYSERR on failure 95 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
74 */ 96 */
75ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, 97int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
76 const char *what, 98 const char *what,
77 void *result, 99 void *result,
78 size_t len) 100 size_t len)
79{ 101{
102 char *dst = result;
103 size_t min;
104 size_t pos;
105 ssize_t ret;
106
107 if (h->emsg != NULL)
108 return GNUNET_SYSERR;
109 pos = 0;
110 do
111 {
112 /* first, use buffer */
113 min = h->have - h->pos;
114 if (min > 0)
115 {
116 if (min > len - pos)
117 min = len - pos;
118 memcpy (&dst[pos], &h->buffer[h->pos], min);
119 h->pos += min;
120 pos += min;
121 }
122 if (pos == len)
123 return GNUNET_OK; /* done! */
124 GNUNET_assert (h->have == h->pos);
125 /* fill buffer */
126 ret = GNUNET_DISK_file_read (h->fd,
127 h->buffer,
128 h->size);
129 if (ret == -1)
130 {
131 GNUNET_asprintf (&h->emsg,
132 _("Error reading `%s': %s"),
133 what,
134 STRERROR (errno));
135 return GNUNET_SYSERR;
136 }
137 if (ret == 0)
138 {
139 GNUNET_asprintf (&h->emsg,
140 _("Error reading `%s': %s"),
141 what,
142 _("End of file"));
143 return GNUNET_SYSERR;
144 }
145 h->pos = 0;
146 h->have = ret;
147 }
148 while (pos < len); /* should always be true */
149 return GNUNET_OK;
80} 150}
81 151
82 152
@@ -87,12 +157,42 @@ ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
87 * @param what describes what is being read (for error message creation) 157 * @param what describes what is being read (for error message creation)
88 * @param result the buffer to store a pointer to the (allocated) string to 158 * @param result the buffer to store a pointer to the (allocated) string to
89 * (note that *result could be set to NULL as well) 159 * (note that *result could be set to NULL as well)
160 * @param maxLen maximum allowed length for the string
90 * @return GNUNET_OK on success, GNUNET_SYSERR on failure 161 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
91 */ 162 */
92int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, 163int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
93 const char *what, 164 const char *what,
94 char **result) 165 char **result,
166 size_t maxLen)
95{ 167{
168 char *buf;
169 uint32_t big;
170
171 if (! GNUNET_BIO_read_int32 (h, &big))
172 return GNUNET_SYSERR;
173 if (big == 0)
174 {
175 *result = NULL;
176 return GNUNET_OK;
177 }
178 if (big > maxLen)
179 {
180 GNUNET_asprintf (&h->emsg,
181 _("String `%s' longer than allowed (%u > %u)"),
182 what,
183 big,
184 maxLen);
185 return GNUNET_SYSERR;
186 }
187 buf = GNUNET_malloc (big);
188 buf[--big] = '\0';
189 if (big != GNUNET_BIO_read (h, what, buf, big))
190 {
191 GNUNET_free (buf);
192 return GNUNET_SYSERR;
193 }
194 *result = buf;
195 return GNUNET_OK;
96} 196}
97 197
98 198
@@ -108,6 +208,42 @@ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
108 const char *what, 208 const char *what,
109 struct GNUNET_CONTAINER_MetaData **result) 209 struct GNUNET_CONTAINER_MetaData **result)
110{ 210{
211 uint32_t size;
212 char *buf;
213 struct GNUNET_CONTAINER_MetaData *meta;
214
215 if (GNUNET_BIO_read_int32__ (h,
216 what,
217 (int32_t*) &size) != GNUNET_OK)
218 return GNUNET_SYSERR;
219 if (size > MAX_META_DATA)
220 {
221 GNUNET_asprintf (&h->emsg,
222 _("Serialized metadata `%s' larger than allowed (%u > %u)"),
223 what,
224 size,
225 MAX_META_DATA);
226 return GNUNET_SYSERR;
227 }
228 buf = GNUNET_malloc (size);
229 if (size !=
230 GNUNET_BIO_read (h, what, buf, size))
231 {
232 GNUNET_free (buf);
233 return GNUNET_SYSERR;
234 }
235 meta = GNUNET_CONTAINER_meta_data_deserialize (buf, size);
236 if (meta == NULL)
237 {
238 GNUNET_free (buf);
239 GNUNET_asprintf (&h->emsg,
240 _("Metadata `%s' failed to deserialize"),
241 what);
242 return GNUNET_SYSERR;
243 }
244 GNUNET_free (buf);
245 *result = meta;
246 return GNUNET_OK;
111} 247}
112 248
113 249
@@ -121,7 +257,19 @@ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
121 */ 257 */
122int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, 258int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h,
123 const char *what, 259 const char *what,
124 int32_t *i); 260 int32_t *i)
261{
262 int32_t big;
263
264 if (sizeof (int32_t) !=
265 GNUNET_BIO_read (h,
266 what,
267 &big,
268 sizeof (int32_t)))
269 return GNUNET_SYSERR;
270 *i = ntohl (big);
271 return GNUNET_OK;
272}
125 273
126 274
127/** 275/**
@@ -134,13 +282,30 @@ int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h,
134 */ 282 */
135int GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, 283int GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h,
136 const char *what, 284 const char *what,
137 int64_t *i); 285 int64_t *i)
286{
287 int64_t big;
288
289 if (sizeof (int64_t) !=
290 GNUNET_BIO_read (h,
291 what,
292 &big,
293 sizeof (int64_t)))
294 return GNUNET_SYSERR;
295 *i = GNUNET_ntohll (big);
296 return GNUNET_OK;
297}
298
138 299
139/** 300/**
140 * Handle for buffered writing. 301 * Handle for buffered writing.
141 */ 302 */
142struct GNUNET_BIO_WriteHandle 303struct GNUNET_BIO_WriteHandle
143{ 304{
305 struct GNUNET_DISK_FileHandle *fd;
306 char *buffer;
307 size_t have;
308 size_t size;
144}; 309};
145 310
146 311
@@ -152,7 +317,19 @@ struct GNUNET_BIO_WriteHandle
152 */ 317 */
153struct GNUNET_BIO_WriteHandle *GNUNET_BIO_write_open (const char *fn) 318struct GNUNET_BIO_WriteHandle *GNUNET_BIO_write_open (const char *fn)
154{ 319{
155 return NULL; 320 struct GNUNET_DISK_FileHandle *fd;
321 struct GNUNET_BIO_WriteHandle *h;
322
323 fd = GNUNET_DISK_file_open (fn,
324 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE,
325 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
326 if (NULL == fd)
327 return NULL;
328 h = GNUNET_malloc (sizeof(struct GNUNET_BIO_WriteHandle) + BIO_BUFFER_SIZE);
329 h->buffer = (char*) &h[1];
330 h->size = BIO_BUFFER_SIZE;
331 h->fd = fd;
332 return h;
156} 333}
157 334
158 335
@@ -162,7 +339,22 @@ struct GNUNET_BIO_WriteHandle *GNUNET_BIO_write_open (const char *fn)
162 * @param h file handle 339 * @param h file handle
163 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise 340 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
164 */ 341 */
165int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h); 342int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h)
343{
344 int ret;
345
346 if (NULL == h->fd)
347 {
348 ret = GNUNET_SYSERR;
349 }
350 else
351 {
352 GNUNET_DISK_file_close (h->fd);
353 ret = GNUNET_OK;
354 }
355 GNUNET_free (h);
356 return ret;
357}
166 358
167 359
168/** 360/**
@@ -173,9 +365,42 @@ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h);
173 * @param n number of bytes to write 365 * @param n number of bytes to write
174 * @return GNUNET_OK on success, GNUNET_SYSERR on error 366 * @return GNUNET_OK on success, GNUNET_SYSERR on error
175 */ 367 */
176ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, 368int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
177 const void *buffer, 369 const void *buffer,
178 size_t n); 370 size_t n)
371{
372 const char *src = buffer;
373 size_t min;
374 size_t pos;
375 ssize_t ret;
376
377 if (NULL == h->fd)
378 return GNUNET_SYSERR;
379 pos = 0;
380 do
381 {
382 /* first, just use buffer */
383 min = h->size - h->have;
384 if (min > n - pos)
385 min = n - pos;
386 memcpy (&h->buffer[h->have], &src[pos], min);
387 pos += min;
388 h->have += min;
389 if (pos == n)
390 return GNUNET_OK; /* done */
391 GNUNET_assert (h->have == h->size);
392 ret = GNUNET_DISK_file_write (h->fd, h->buffer, h->size);
393 if (ret != h->size)
394 {
395 GNUNET_DISK_file_close (h->fd);
396 h->fd = NULL;
397 return GNUNET_SYSERR; /* error */
398 }
399 h->have = 0;
400 }
401 while (pos < n); /* should always be true */
402 return GNUNET_OK;
403}
179 404
180 405
181/** 406/**
@@ -186,9 +411,18 @@ ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
186 * @return GNUNET_OK on success, GNUNET_SYSERR on error 411 * @return GNUNET_OK on success, GNUNET_SYSERR on error
187 */ 412 */
188int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, 413int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
189 const char *s); 414 const char *s)
190 415{
416 uint32_t slen;
191 417
418 slen = (uint32_t) ((s == NULL) ? 0 : strlen(s) + 1);
419 if (GNUNET_OK !=
420 GNUNET_BIO_write_int32 (h, slen))
421 return GNUNET_SYSERR;
422 if (0 != slen)
423 return GNUNET_BIO_write (h, s, slen - 1);
424 return GNUNET_OK;
425}
192 426
193 427
194/** 428/**
@@ -199,27 +433,34 @@ int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
199 * @return GNUNET_OK on success, GNUNET_SYSERR on error 433 * @return GNUNET_OK on success, GNUNET_SYSERR on error
200 */ 434 */
201int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, 435int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
202 const struct GNUNET_CONTAINER_MetaData *m); 436 const struct GNUNET_CONTAINER_MetaData *m)
203 437{
204 438 unsigned int size;
205 439 char *buf;
206/**
207 * Write a float.
208 *
209 * @param h hande to open file
210 * @param f float to write (must be a variable)
211 */
212#define GNUNET_BIO_write_float(h, f) (sizeof(float) == GNUNET_BIO_write (h, &f, sizeof(float)))
213
214
215 440
216/** 441 size = GNUNET_CONTAINER_meta_data_get_serialized_size (m,
217 * Write a double. 442 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL
218 * 443 |
219 * @param h hande to open file 444 GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS);
220 * @param f double to write (must be a variable) 445 if (size > MAX_META_DATA)
221 */ 446 size = MAX_META_DATA;
222#define GNUNET_BIO_write_float(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double))) 447 buf = GNUNET_malloc (size);
448 GNUNET_CONTAINER_meta_data_serialize (m,
449 buf,
450 size,
451 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART |
452 GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS);
453 if ( (GNUNET_OK !=
454 GNUNET_BIO_write_int32 (h, size)) ||
455 (GNUNET_OK !=
456 GNUNET_BIO_write (h, buf, size)) )
457 {
458 GNUNET_free (buf);
459 return GNUNET_SYSERR;
460 }
461 GNUNET_free (buf);
462 return GNUNET_OK;
463}
223 464
224 465
225/** 466/**
@@ -229,8 +470,13 @@ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
229 * @param i address of 32-bit integer to write 470 * @param i address of 32-bit integer to write
230 * @return GNUNET_OK on success, GNUNET_SYSERR on error 471 * @return GNUNET_OK on success, GNUNET_SYSERR on error
231 */ 472 */
232int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, 473int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h,
233 int32_t i); 474 int32_t i)
475{
476 int32_t big;
477 big = htonl (i);
478 return GNUNET_BIO_write (h, &big, sizeof (int32_t));
479}
234 480
235 481
236/** 482/**
@@ -240,306 +486,13 @@ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h,
240 * @param i address of 64-bit integer to write 486 * @param i address of 64-bit integer to write
241 * @return GNUNET_OK on success, GNUNET_SYSERR on error 487 * @return GNUNET_OK on success, GNUNET_SYSERR on error
242 */ 488 */
243int GNUNET_BIO_write_int64 (struct GNUNET_BIO_ReadHandle *h, 489int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h,
244 int64_t i); 490 int64_t i)
245
246
247
248
249
250typedef struct
251{ 491{
252 int fd; 492 int64_t big;
253 unsigned int have; 493 big = GNUNET_htonll (i);
254 unsigned int size; 494 return GNUNET_BIO_write (h, &big, sizeof (int64_t));
255 char *buffer;
256} WriteBuffer;
257
258static void
259write_buffered (WriteBuffer * wb, const void *s, unsigned int size)
260{
261 const char *src = s;
262 unsigned int min;
263 unsigned int pos;
264 int ret;
265
266 if (wb->fd == -1)
267 return;
268 pos = 0;
269 do
270 {
271 /* first, just use buffer */
272 min = wb->size - wb->have;
273 if (min > size - pos)
274 min = size - pos;
275 memcpy (&wb->buffer[wb->have], &src[pos], min);
276 pos += min;
277 wb->have += min;
278 if (pos == size)
279 return; /* done */
280 GNUNET_GE_ASSERT (NULL, wb->have == wb->size);
281 ret = WRITE (wb->fd, wb->buffer, wb->size);
282 if (ret != wb->size)
283 {
284 CLOSE (wb->fd);
285 wb->fd = -1;
286 return; /* error */
287 }
288 wb->have = 0;
289 }
290 while (pos < size); /* should always be true */
291} 495}
292 496
293 497
294static void
295WRITEINT (WriteBuffer * wb, int val)
296{
297 int big;
298 big = htonl (val);
299 write_buffered (wb, &big, sizeof (int));
300}
301
302static void
303WRITELONG (WriteBuffer * wb, long long val)
304{
305 long long big;
306 big = GNUNET_htonll (val);
307 write_buffered (wb, &big, sizeof (long long));
308}
309
310static void
311writeURI (WriteBuffer * wb, const struct GNUNET_ECRS_URI *uri)
312{
313 char *buf;
314 unsigned int size;
315
316 buf = GNUNET_ECRS_uri_to_string (uri);
317 size = strlen (buf);
318 WRITEINT (wb, size);
319 write_buffered (wb, buf, size);
320 GNUNET_free (buf);
321}
322
323static void
324WRITESTRING (WriteBuffer * wb, const char *name)
325{
326 GNUNET_GE_BREAK (NULL, name != NULL);
327 WRITEINT (wb, strlen (name));
328 write_buffered (wb, name, strlen (name));
329}
330
331static void
332writeMetaData (struct GNUNET_GE_Context *ectx,
333 WriteBuffer * wb, const struct GNUNET_MetaData *meta)
334{
335 unsigned int size;
336 char *buf;
337
338 size = GNUNET_meta_data_get_serialized_size (meta,
339 GNUNET_SERIALIZE_FULL
340 |
341 GNUNET_SERIALIZE_NO_COMPRESS);
342 if (size > 1024 * 1024)
343 size = 1024 * 1024;
344 buf = GNUNET_malloc (size);
345 GNUNET_meta_data_serialize (ectx,
346 meta,
347 buf,
348 size,
349 GNUNET_SERIALIZE_PART |
350 GNUNET_SERIALIZE_NO_COMPRESS);
351 WRITEINT (wb, size);
352 write_buffered (wb, buf, size);
353 GNUNET_free (buf);
354}
355
356
357static void
358writeFileInfo (struct GNUNET_GE_Context *ectx, WriteBuffer * wb,
359 const GNUNET_ECRS_FileInfo * fi)
360{
361 writeMetaData (ectx, wb, fi->meta);
362 writeURI (wb, fi->uri);
363}
364
365
366
367
368typedef struct
369{
370 int fd;
371 unsigned int have;
372 unsigned int size;
373 unsigned int pos;
374 char *buffer;
375} ReadBuffer;
376
377static int
378read_buffered (ReadBuffer * rb, void *d, unsigned int size)
379{
380 char *dst = d;
381 unsigned int min;
382 unsigned int pos;
383 int ret;
384
385 if (rb->fd == -1)
386 return -1;
387 pos = 0;
388 do
389 {
390 /* first, use buffer */
391 min = rb->have - rb->pos;
392 if (min > 0)
393 {
394 if (min > size - pos)
395 min = size - pos;
396 memcpy (&dst[pos], &rb->buffer[rb->pos], min);
397 rb->pos += min;
398 pos += min;
399 }
400 if (pos == size)
401 return pos; /* done! */
402 GNUNET_GE_ASSERT (NULL, rb->have == rb->pos);
403 /* fill buffer */
404 ret = READ (rb->fd, rb->buffer, rb->size);
405 if (ret == -1)
406 {
407 CLOSE (rb->fd);
408 rb->fd = -1;
409 return -1;
410 }
411 if (ret == 0)
412 return 0;
413 rb->pos = 0;
414 rb->have = ret;
415 }
416 while (pos < size); /* should always be true */
417 return pos;
418}
419
420
421static int
422read_int (ReadBuffer * rb, int *val)
423{
424 int big;
425
426 if (sizeof (int) != read_buffered (rb, &big, sizeof (int)))
427 return GNUNET_SYSERR;
428 *val = ntohl (big);
429 return GNUNET_OK;
430}
431
432static unsigned int
433read_uint (ReadBuffer * rb, unsigned int *val)
434{
435 unsigned int big;
436
437 if (sizeof (unsigned int) !=
438 read_buffered (rb, &big, sizeof (unsigned int)))
439 return GNUNET_SYSERR;
440 *val = ntohl (big);
441 return GNUNET_OK;
442}
443
444#define READINT(a) if (GNUNET_OK != read_int(rb, (int*) &a)) return GNUNET_SYSERR;
445
446static int
447read_long (ReadBuffer * rb, long long *val)
448{
449 long long big;
450
451 if (sizeof (long long) != read_buffered (rb, &big, sizeof (long long)))
452 return GNUNET_SYSERR;
453 *val = GNUNET_ntohll (big);
454 return GNUNET_OK;
455}
456
457#define READLONG(a) if (GNUNET_OK != read_long(rb, (long long*) &a)) return GNUNET_SYSERR;
458
459static struct GNUNET_ECRS_URI *
460read_uri (struct GNUNET_GE_Context *ectx, ReadBuffer * rb)
461{
462 char *buf;
463 struct GNUNET_ECRS_URI *ret;
464 unsigned int size;
465
466 if (GNUNET_OK != read_uint (rb, &size))
467 return NULL;
468 buf = GNUNET_malloc (size + 1);
469 buf[size] = '\0';
470 if (size != read_buffered (rb, buf, size))
471 {
472 GNUNET_free (buf);
473 return NULL;
474 }
475 ret = GNUNET_ECRS_string_to_uri (ectx, buf);
476 GNUNET_GE_BREAK (ectx, ret != NULL);
477 GNUNET_free (buf);
478 return ret;
479}
480
481#define READURI(u) if (NULL == (u = read_uri(ectx, rb))) return GNUNET_SYSERR;
482
483static char *
484read_string (ReadBuffer * rb, unsigned int maxLen)
485{
486 char *buf;
487 unsigned int big;
488
489 if (GNUNET_OK != read_uint (rb, &big))
490 return NULL;
491 if (big > maxLen)
492 return NULL;
493 buf = GNUNET_malloc (big + 1);
494 buf[big] = '\0';
495 if (big != read_buffered (rb, buf, big))
496 {
497 GNUNET_free (buf);
498 return NULL;
499 }
500 return buf;
501}
502
503#define READSTRING(c, max) if (NULL == (c = read_string(rb, max))) return GNUNET_SYSERR;
504
505/**
506 * Read file info from file.
507 *
508 * @return GNUNET_OK on success, GNUNET_SYSERR on error
509 */
510static struct GNUNET_MetaData *
511read_meta (struct GNUNET_GE_Context *ectx, ReadBuffer * rb)
512{
513 unsigned int size;
514 char *buf;
515 struct GNUNET_MetaData *meta;
516
517 if (read_uint (rb, &size) != GNUNET_OK)
518 {
519 GNUNET_GE_BREAK (ectx, 0);
520 return NULL;
521 }
522 if (size > 1024 * 1024)
523 {
524 GNUNET_GE_BREAK (ectx, 0);
525 return NULL;
526 }
527 buf = GNUNET_malloc (size);
528 if (size != read_buffered (rb, buf, size))
529 {
530 GNUNET_free (buf);
531 GNUNET_GE_BREAK (ectx, 0);
532 return NULL;
533 }
534 meta = GNUNET_meta_data_deserialize (ectx, buf, size);
535 if (meta == NULL)
536 {
537 GNUNET_free (buf);
538 GNUNET_GE_BREAK (ectx, 0);
539 return NULL;
540 }
541 GNUNET_free (buf);
542 return meta;
543}
544
545/* end of bio.c */ 498/* end of bio.c */