aboutsummaryrefslogtreecommitdiff
path: root/src/plugin/namestore/plugin_namestore_flat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugin/namestore/plugin_namestore_flat.c')
-rw-r--r--src/plugin/namestore/plugin_namestore_flat.c816
1 files changed, 816 insertions, 0 deletions
diff --git a/src/plugin/namestore/plugin_namestore_flat.c b/src/plugin/namestore/plugin_namestore_flat.c
new file mode 100644
index 000000000..20019e1db
--- /dev/null
+++ b/src/plugin/namestore/plugin_namestore_flat.c
@@ -0,0 +1,816 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2015, 2018, 2019 GNUnet e.V.
4 *
5 * GNUnet is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License,
8 * or (at your 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 * Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file namestore/plugin_namestore_flat.c
22 * @brief file-based namestore backend
23 * @author Martin Schanzenbach
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_namestore_plugin.h"
29#include "gnunet_gnsrecord_lib.h"
30
31/**
32 * Context for all functions in this plugin.
33 */
34struct Plugin
35{
36 const struct GNUNET_CONFIGURATION_Handle *cfg;
37
38 /**
39 * Database filename.
40 */
41 char *fn;
42
43 /**
44 * HashMap
45 */
46 struct GNUNET_CONTAINER_MultiHashMap *hm;
47};
48
49
50struct FlatFileEntry
51{
52 /**
53 * Entry zone
54 */
55 struct GNUNET_CRYPTO_PrivateKey private_key;
56
57 /**
58 * Record count.
59 */
60 uint32_t record_count;
61
62 /**
63 * Rvalue
64 */
65 uint64_t rvalue;
66
67 /**
68 * Record data
69 */
70 struct GNUNET_GNSRECORD_Data *record_data;
71
72 /**
73 * Label
74 */
75 char *label;
76};
77
78
79/**
80 * Hash contactenation of @a pkey and @a label into @a h
81 *
82 * @param pkey a key
83 * @param label a label
84 * @param[out] h initialized hash
85 */
86static void
87hash_pkey_and_label (const struct GNUNET_CRYPTO_PrivateKey *pkey,
88 const char *label,
89 struct GNUNET_HashCode *h)
90{
91 char *key;
92 size_t label_len;
93 size_t key_len;
94
95 label_len = strlen (label);
96 key_len = label_len + sizeof(struct GNUNET_CRYPTO_PrivateKey);
97 key = GNUNET_malloc (key_len);
98 GNUNET_memcpy (key,
99 label,
100 label_len);
101 GNUNET_memcpy (key + label_len,
102 pkey,
103 sizeof(struct GNUNET_CRYPTO_PrivateKey));
104 GNUNET_CRYPTO_hash (key,
105 key_len,
106 h);
107 GNUNET_free (key);
108}
109
110
111/**
112 * Initialize the database connections and associated
113 * data structures (create tables and indices
114 * as needed as well).
115 *
116 * @param plugin the plugin context (state for this module)
117 * @return #GNUNET_OK on success
118 */
119static int
120database_setup (struct Plugin *plugin)
121{
122 char *flatdbfile;
123 char *record_data;
124 char *zone_private_key;
125 char *record_data_b64;
126 char *buffer;
127 char *line;
128 char *label;
129 char *rvalue;
130 char *record_count;
131 size_t record_data_size;
132 uint64_t size;
133 struct GNUNET_HashCode hkey;
134 struct GNUNET_DISK_FileHandle *fh;
135 struct FlatFileEntry *entry;
136 struct GNUNET_DISK_MapHandle *mh;
137
138 if (GNUNET_OK !=
139 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
140 "namestore-flat",
141 "FILENAME",
142 &flatdbfile))
143 {
144 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
145 "namestore-flat",
146 "FILENAME");
147 return GNUNET_SYSERR;
148 }
149 if (GNUNET_OK !=
150 GNUNET_DISK_file_test (flatdbfile))
151 {
152 if (GNUNET_OK !=
153 GNUNET_DISK_directory_create_for_file (flatdbfile))
154 {
155 GNUNET_break (0);
156 GNUNET_free (flatdbfile);
157 return GNUNET_SYSERR;
158 }
159 }
160 /* flatdbfile should be UTF-8-encoded. If it isn't, it's a bug */
161 plugin->fn = flatdbfile;
162
163 /* Load data from file into hashmap */
164 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
165 GNUNET_NO);
166 fh = GNUNET_DISK_file_open (flatdbfile,
167 GNUNET_DISK_OPEN_CREATE
168 | GNUNET_DISK_OPEN_READWRITE,
169 GNUNET_DISK_PERM_USER_WRITE
170 | GNUNET_DISK_PERM_USER_READ);
171 if (NULL == fh)
172 {
173 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
174 _ ("Unable to initialize file: %s.\n"),
175 flatdbfile);
176 return GNUNET_SYSERR;
177 }
178 if (GNUNET_SYSERR ==
179 GNUNET_DISK_file_size (flatdbfile,
180 &size,
181 GNUNET_YES,
182 GNUNET_YES))
183 {
184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
185 _ ("Unable to get filesize: %s.\n"),
186 flatdbfile);
187 GNUNET_DISK_file_close (fh);
188 return GNUNET_SYSERR;
189 }
190 if (size > SIZE_MAX)
191 {
192 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
193 _ ("File too big to map: %llu bytes.\n"),
194 (unsigned long long) size);
195 GNUNET_DISK_file_close (fh);
196 return GNUNET_SYSERR;
197 }
198 if (0 == size)
199 {
200 GNUNET_DISK_file_close (fh);
201 return GNUNET_OK;
202 }
203 buffer = GNUNET_DISK_file_map (fh,
204 &mh,
205 GNUNET_DISK_MAP_TYPE_READ,
206 size);
207 if (NULL == buffer)
208 {
209 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
210 "mmap");
211 GNUNET_DISK_file_close (fh);
212 return GNUNET_SYSERR;
213 }
214 if ('\0' != buffer[size - 1])
215 {
216 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
217 _ ("Namestore database file `%s' malformed\n"),
218 flatdbfile);
219 GNUNET_DISK_file_unmap (mh);
220 GNUNET_DISK_file_close (fh);
221 return GNUNET_SYSERR;
222 }
223
224 line = strtok (buffer, "\n");
225 while (NULL != line)
226 {
227 zone_private_key = strtok (line, ",");
228 if (NULL == zone_private_key)
229 break;
230 rvalue = strtok (NULL, ",");
231 if (NULL == rvalue)
232 break;
233 record_count = strtok (NULL, ",");
234 if (NULL == record_count)
235 break;
236 record_data_b64 = strtok (NULL, ",");
237 if (NULL == record_data_b64)
238 break;
239 label = strtok (NULL, ",");
240 if (NULL == label)
241 break;
242 line = strtok (NULL, "\n");
243 entry = GNUNET_new (struct FlatFileEntry);
244 {
245 unsigned long long ll;
246
247 if (1 != sscanf (rvalue,
248 "%llu",
249 &ll))
250 {
251 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
252 "Error parsing entry\n");
253 GNUNET_free (entry);
254 break;
255 }
256 entry->rvalue = (uint64_t) ll;
257 }
258 {
259 unsigned int ui;
260
261 if (1 != sscanf (record_count,
262 "%u",
263 &ui))
264 {
265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
266 "Error parsing entry\n");
267 GNUNET_free (entry);
268 break;
269 }
270 entry->record_count = (uint32_t) ui;
271 }
272 entry->label = GNUNET_strdup (label);
273 record_data_size
274 = GNUNET_STRINGS_base64_decode (record_data_b64,
275 strlen (record_data_b64),
276 (void **) &record_data);
277 entry->record_data =
278 GNUNET_new_array (entry->record_count,
279 struct GNUNET_GNSRECORD_Data);
280 if (GNUNET_OK !=
281 GNUNET_GNSRECORD_records_deserialize (record_data_size,
282 record_data,
283 entry->record_count,
284 entry->record_data))
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
287 "Unable to deserialize record %s\n",
288 label);
289 GNUNET_free (entry->label);
290 GNUNET_free (entry);
291 GNUNET_free (record_data);
292 break;
293 }
294 GNUNET_free (record_data);
295
296 {
297 struct GNUNET_CRYPTO_PrivateKey *private_key;
298
299 GNUNET_STRINGS_base64_decode (zone_private_key,
300 strlen (zone_private_key),
301 (void **) &private_key);
302 entry->private_key = *private_key;
303 GNUNET_free (private_key);
304 }
305
306 hash_pkey_and_label (&entry->private_key,
307 label,
308 &hkey);
309 if (GNUNET_OK !=
310 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
311 &hkey,
312 entry,
313 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
314 {
315 GNUNET_free (entry);
316 GNUNET_break (0);
317 }
318 }
319 GNUNET_DISK_file_unmap (mh);
320 GNUNET_DISK_file_close (fh);
321 return GNUNET_OK;
322}
323
324
325/**
326 * Store values in hashmap in file and free data
327 *
328 * @param plugin the plugin context
329 * @param key key in the map
330 * @param value a `struct FlatFileEntry`
331 */
332static int
333store_and_free_entries (void *cls,
334 const struct GNUNET_HashCode *key,
335 void *value)
336{
337 struct GNUNET_DISK_FileHandle *fh = cls;
338 struct FlatFileEntry *entry = value;
339 char *line;
340 char *zone_private_key;
341 char *record_data_b64;
342 ssize_t data_size;
343
344 (void) key;
345 GNUNET_STRINGS_base64_encode (&entry->private_key,
346 sizeof(struct GNUNET_CRYPTO_PrivateKey),
347 &zone_private_key);
348 data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
349 entry->record_data);
350 if (data_size < 0)
351 {
352 GNUNET_break (0);
353 GNUNET_free (zone_private_key);
354 return GNUNET_SYSERR;
355 }
356 if (data_size >= UINT16_MAX)
357 {
358 GNUNET_break (0);
359 GNUNET_free (zone_private_key);
360 return GNUNET_SYSERR;
361 }
362 {
363 char data[data_size];
364 ssize_t ret;
365
366 ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
367 entry->record_data,
368 data_size,
369 data);
370 if ((ret < 0) ||
371 (data_size != ret))
372 {
373 GNUNET_break (0);
374 GNUNET_free (zone_private_key);
375 return GNUNET_SYSERR;
376 }
377 GNUNET_STRINGS_base64_encode (data,
378 data_size,
379 &record_data_b64);
380 }
381 GNUNET_asprintf (&line,
382 "%s,%llu,%u,%s,%s\n",
383 zone_private_key,
384 (unsigned long long) entry->rvalue,
385 (unsigned int) entry->record_count,
386 record_data_b64,
387 entry->label);
388 GNUNET_free (record_data_b64);
389 GNUNET_free (zone_private_key);
390
391 GNUNET_DISK_file_write (fh,
392 line,
393 strlen (line));
394
395 GNUNET_free (line);
396 GNUNET_free (entry->label);
397 GNUNET_free (entry->record_data);
398 GNUNET_free (entry);
399 return GNUNET_YES;
400}
401
402
403/**
404 * Shutdown database connection and associate data
405 * structures.
406 * @param plugin the plugin context (state for this module)
407 */
408static void
409database_shutdown (struct Plugin *plugin)
410{
411 struct GNUNET_DISK_FileHandle *fh;
412
413 fh = GNUNET_DISK_file_open (plugin->fn,
414 GNUNET_DISK_OPEN_CREATE
415 | GNUNET_DISK_OPEN_TRUNCATE
416 | GNUNET_DISK_OPEN_READWRITE,
417 GNUNET_DISK_PERM_USER_WRITE
418 | GNUNET_DISK_PERM_USER_READ);
419 if (NULL == fh)
420 {
421 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
422 _ ("Unable to initialize file: %s.\n"),
423 plugin->fn);
424 return;
425 }
426
427 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
428 &store_and_free_entries,
429 fh);
430 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
431 /* append 0-terminator */
432 GNUNET_DISK_file_write (fh,
433 "",
434 1);
435 GNUNET_DISK_file_close (fh);
436}
437
438
439/**
440 * Store a record in the datastore. Removes any existing record in the
441 * same zone with the same name.
442 *
443 * @param cls closure (internal context for the plugin)
444 * @param zone_key private key of the zone
445 * @param label name that is being mapped (at most 255 characters long)
446 * @param rd_count number of entries in @a rd array
447 * @param rd array of records with data to store
448 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
449 */
450static int
451namestore_flat_store_records (void *cls,
452 const struct
453 GNUNET_CRYPTO_PrivateKey *zone_key,
454 const char *label,
455 unsigned int rd_count,
456 const struct GNUNET_GNSRECORD_Data *rd)
457{
458 struct Plugin *plugin = cls;
459 uint64_t rvalue;
460 struct GNUNET_HashCode hkey;
461 struct FlatFileEntry *entry;
462
463 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
464 UINT64_MAX);
465 hash_pkey_and_label (zone_key,
466 label,
467 &hkey);
468 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
469 &hkey);
470 if (0 == rd_count)
471 {
472 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
473 "sqlite",
474 "Record deleted\n");
475 return GNUNET_OK;
476 }
477 entry = GNUNET_new (struct FlatFileEntry);
478 GNUNET_asprintf (&entry->label,
479 label,
480 strlen (label));
481 GNUNET_memcpy (&entry->private_key,
482 zone_key,
483 sizeof(struct GNUNET_CRYPTO_PrivateKey));
484 entry->rvalue = rvalue;
485 entry->record_count = rd_count;
486 entry->record_data = GNUNET_new_array (rd_count,
487 struct GNUNET_GNSRECORD_Data);
488 for (unsigned int i = 0; i < rd_count; i++)
489 {
490 entry->record_data[i].expiration_time = rd[i].expiration_time;
491 entry->record_data[i].record_type = rd[i].record_type;
492 entry->record_data[i].flags = rd[i].flags;
493 entry->record_data[i].data_size = rd[i].data_size;
494 entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
495 GNUNET_memcpy ((char *) entry->record_data[i].data,
496 rd[i].data,
497 rd[i].data_size);
498 }
499 return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
500 &hkey,
501 entry,
502 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
503}
504
505
506/**
507 * Lookup records in the datastore for which we are the authority.
508 *
509 * @param cls closure (internal context for the plugin)
510 * @param zone private key of the zone
511 * @param label name of the record in the zone
512 * @param iter function to call with the result
513 * @param iter_cls closure for @a iter
514 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
515 */
516static int
517namestore_flat_lookup_records (void *cls,
518 const struct GNUNET_CRYPTO_PrivateKey *zone,
519 const char *label,
520 GNUNET_NAMESTORE_RecordIterator iter,
521 void *iter_cls)
522{
523 struct Plugin *plugin = cls;
524 struct FlatFileEntry *entry;
525 struct GNUNET_HashCode hkey;
526
527 if (NULL == zone)
528 {
529 GNUNET_break (0);
530 return GNUNET_SYSERR;
531 }
532 hash_pkey_and_label (zone,
533 label,
534 &hkey);
535 entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
536 &hkey);
537
538 if (NULL == entry)
539 return GNUNET_NO;
540 if (NULL != iter)
541 iter (iter_cls,
542 1, /* zero is illegal */
543 &entry->private_key,
544 entry->label,
545 entry->record_count,
546 entry->record_data);
547 return GNUNET_YES;
548}
549
550
551/**
552 * Closure for #iterate_zones.
553 */
554struct IterateContext
555{
556 /**
557 * How many more records should we skip before returning results?
558 */
559 uint64_t offset;
560
561 /**
562 * How many more records should we return?
563 */
564 uint64_t limit;
565
566 /**
567 * What is the position of the current entry, counting
568 * starts from 1.
569 */
570 uint64_t pos;
571
572 /**
573 * Target zone.
574 */
575 const struct GNUNET_CRYPTO_PrivateKey *zone;
576
577 /**
578 * Function to call on each record.
579 */
580 GNUNET_NAMESTORE_RecordIterator iter;
581
582 /**
583 * Closure for @e iter.
584 */
585 void *iter_cls;
586};
587
588
589/**
590 * Helper function for #namestore_flat_iterate_records().
591 *
592 * @param cls a `struct IterateContext`
593 * @param key unused
594 * @param value a `struct FlatFileEntry`
595 * @return #GNUNET_YES to continue the iteration
596 */
597static int
598iterate_zones (void *cls,
599 const struct GNUNET_HashCode *key,
600 void *value)
601{
602 struct IterateContext *ic = cls;
603 struct FlatFileEntry *entry = value;
604
605 (void) key;
606 if (0 == ic->limit)
607 return GNUNET_NO;
608 if ((NULL != ic->zone) &&
609 (0 != GNUNET_memcmp (&entry->private_key,
610 ic->zone)))
611 return GNUNET_YES;
612 ic->pos++;
613 if (ic->offset > 0)
614 {
615 ic->offset--;
616 return GNUNET_YES;
617 }
618 ic->iter (ic->iter_cls,
619 ic->pos,
620 (NULL == ic->zone)
621 ? &entry->private_key
622 : ic->zone,
623 entry->label,
624 entry->record_count,
625 entry->record_data);
626 ic->limit--;
627 if (0 == ic->limit)
628 return GNUNET_NO;
629 return GNUNET_YES;
630}
631
632
633/**
634 * Iterate over the results for a particular key and zone in the
635 * datastore. Will return at most one result to the iterator.
636 *
637 * @param cls closure (internal context for the plugin)
638 * @param zone hash of public key of the zone, NULL to iterate over all zones
639 * @param serial serial number to exclude in the list of all matching records
640 * @param limit maximum number of results to return to @a iter
641 * @param iter function to call with the result
642 * @param iter_cls closure for @a iter
643 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
644 */
645static int
646namestore_flat_iterate_records (void *cls,
647 const struct
648 GNUNET_CRYPTO_PrivateKey *zone,
649 uint64_t serial,
650 uint64_t limit,
651 GNUNET_NAMESTORE_RecordIterator iter,
652 void *iter_cls)
653{
654 struct Plugin *plugin = cls;
655 struct IterateContext ic;
656
657 ic.offset = serial;
658 ic.pos = 0;
659 ic.limit = limit;
660 ic.iter = iter;
661 ic.iter_cls = iter_cls;
662 ic.zone = zone;
663 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
664 &iterate_zones,
665 &ic);
666 return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
667}
668
669
670/**
671 * Closure for #zone_to_name.
672 */
673struct ZoneToNameContext
674{
675 const struct GNUNET_CRYPTO_PrivateKey *zone;
676 const struct GNUNET_CRYPTO_PublicKey *value_zone;
677 GNUNET_NAMESTORE_RecordIterator iter;
678 void *iter_cls;
679
680 int result_found;
681};
682
683
684static int
685zone_to_name (void *cls,
686 const struct GNUNET_HashCode *key,
687 void *value)
688{
689 struct ZoneToNameContext *ztn = cls;
690 struct FlatFileEntry *entry = value;
691
692 (void) key;
693 if (0 != GNUNET_memcmp (&entry->private_key,
694 ztn->zone))
695 return GNUNET_YES;
696
697 for (unsigned int i = 0; i < entry->record_count; i++)
698 {
699 if (GNUNET_NO ==
700 GNUNET_GNSRECORD_is_zonekey_type (entry->record_data[i].record_type))
701 continue;
702 if (ztn->value_zone->type != entry->record_data[i].record_type)
703 continue;
704 if (0 == memcmp (ztn->value_zone,
705 entry->record_data[i].data,
706 entry->record_data[i].data_size))
707 {
708 ztn->iter (ztn->iter_cls,
709 i + 1, /* zero is illegal! */
710 &entry->private_key,
711 entry->label,
712 entry->record_count,
713 entry->record_data);
714 ztn->result_found = GNUNET_YES;
715 }
716 }
717 return GNUNET_YES;
718}
719
720
721/**
722 * Look for an existing PKEY delegation record for a given public key.
723 * Returns at most one result to the iterator.
724 *
725 * @param cls closure (internal context for the plugin)
726 * @param zone private key of the zone to look up in, never NULL
727 * @param value_zone public key of the target zone (value), never NULL
728 * @param iter function to call with the result
729 * @param iter_cls closure for @a iter
730 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
731 */
732static int
733namestore_flat_zone_to_name (void *cls,
734 const struct GNUNET_CRYPTO_PrivateKey *zone,
735 const struct
736 GNUNET_CRYPTO_PublicKey *value_zone,
737 GNUNET_NAMESTORE_RecordIterator iter,
738 void *iter_cls)
739{
740 struct Plugin *plugin = cls;
741 struct ZoneToNameContext ztn = {
742 .iter = iter,
743 .iter_cls = iter_cls,
744 .zone = zone,
745 .value_zone = value_zone,
746 .result_found = GNUNET_NO
747 };
748
749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
750 "Performing reverse lookup for `%s'\n",
751 GNUNET_GNSRECORD_z2s (value_zone));
752 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
753 &zone_to_name,
754 &ztn);
755 return ztn.result_found;
756}
757
758
759/**
760 * Entry point for the plugin.
761 *
762 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
763 * @return NULL on error, otherwise the plugin context
764 */
765void *
766libgnunet_plugin_namestore_flat_init (void *cls)
767{
768 static struct Plugin plugin;
769 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
770 struct GNUNET_NAMESTORE_PluginFunctions *api;
771
772 if (NULL != plugin.cfg)
773 return NULL; /* can only initialize once! */
774 memset (&plugin,
775 0,
776 sizeof(struct Plugin));
777 plugin.cfg = cfg;
778 if (GNUNET_OK != database_setup (&plugin))
779 {
780 database_shutdown (&plugin);
781 return NULL;
782 }
783 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
784 api->cls = &plugin;
785 api->store_records = &namestore_flat_store_records;
786 api->iterate_records = &namestore_flat_iterate_records;
787 api->zone_to_name = &namestore_flat_zone_to_name;
788 api->lookup_records = &namestore_flat_lookup_records;
789 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
790 _ ("Flat file database running\n"));
791 return api;
792}
793
794
795/**
796 * Exit point from the plugin.
797 *
798 * @param cls the plugin context (as returned by "init")
799 * @return always NULL
800 */
801void *
802libgnunet_plugin_namestore_flat_done (void *cls)
803{
804 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
805 struct Plugin *plugin = api->cls;
806
807 database_shutdown (plugin);
808 plugin->cfg = NULL;
809 GNUNET_free (api);
810 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
811 "Flat file plugin is finished\n");
812 return NULL;
813}
814
815
816/* end of plugin_namestore_flat.c */