Merge branch 'master' of git+ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / sq / sq_result_helper.c
1
2 /*
3   This file is part of GNUnet
4   Copyright (C) 2017 GNUnet e.V.
5
6   GNUnet is free software; you can redistribute it and/or modify it under the
7   terms of the GNU General Public License as published by the Free Software
8   Foundation; either version 3, or (at your option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
11   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License along with
15   GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
16 */
17 /**
18  * @file sq/sq_result_helper.c
19  * @brief helper functions for queries
20  * @author Christian Grothoff
21  */
22 #include "platform.h"
23 #include "gnunet_sq_lib.h"
24
25
26 /**
27  * Extract variable-sized binary data from a Postgres database @a result at row @a row.
28  *
29  * @param cls closure
30  * @param result where to extract data from
31  * @param column column to extract data from
32  * @param[in,out] dst_size where to store size of result, may be NULL
33  * @param[out] dst where to store the result (actually a `void **`)
34  * @return
35  *   #GNUNET_YES if all results could be extracted
36  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
37  */
38 static int
39 extract_var_blob (void *cls,
40                   sqlite3_stmt *result,
41                   unsigned int column,
42                   size_t *dst_size,
43                   void *dst)
44 {
45   int have;
46   const void *ret;
47   void **rdst = (void **) dst;
48
49   if (SQLITE_BLOB !=
50       sqlite3_column_type (result,
51                            column))
52   {
53     GNUNET_break (0);
54     return GNUNET_SYSERR;
55   }
56   /* sqlite manual says to invoke 'sqlite3_column_blob()'
57      before calling sqlite3_column_bytes() */
58   ret = sqlite3_column_blob (result,
59                              column);
60   have = sqlite3_column_bytes (result,
61                                column);
62   if (have < 0)
63   {
64     GNUNET_break (0);
65     return GNUNET_SYSERR;
66   }
67   *dst_size = have;
68   if (0 == have)
69   {
70     *rdst = NULL;
71     return GNUNET_OK;
72   }
73   *rdst = GNUNET_malloc (have);
74   GNUNET_memcpy (*rdst,
75                  ret,
76                  have);
77   return GNUNET_OK;
78 }
79
80
81 /**
82  * Cleanup memory allocated by #extract_var_blob().
83  *
84  * @param cls pointer to pointer of allocation
85  */
86 static void
87 clean_var_blob (void *cls)
88 {
89   void **dptr = (void **) cls;
90
91   if (NULL != *dptr)
92   {
93     GNUNET_free (*dptr);
94     *dptr = NULL;
95   }
96 }
97
98
99 /**
100  * Variable-size result expected.
101  *
102  * @param[out] dst where to store the result, allocated
103  * @param[out] sptr where to store the size of @a dst
104  * @return array entry for the result specification to use
105  */
106 struct GNUNET_SQ_ResultSpec
107 GNUNET_SQ_result_spec_variable_size (void **dst,
108                                      size_t *sptr)
109 {
110   struct GNUNET_SQ_ResultSpec rs = {
111     .conv = &extract_var_blob,
112     .cleaner = &clean_var_blob,
113     .dst = dst,
114     .cls = dst,
115     .result_size = sptr,
116     .num_params = 1
117   };
118
119   return rs;
120 }
121
122
123 /**
124  * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
125  *
126  * @param cls closure
127  * @param result where to extract data from
128  * @param column column to extract data from
129  * @param[in,out] dst_size where to store size of result, may be NULL
130  * @param[out] dst where to store the result
131  * @return
132  *   #GNUNET_YES if all results could be extracted
133  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
134  */
135 static int
136 extract_fixed_blob (void *cls,
137                     sqlite3_stmt *result,
138                     unsigned int column,
139                     size_t *dst_size,
140                     void *dst)
141 {
142   int have;
143   const void *ret;
144
145   if (SQLITE_BLOB !=
146       sqlite3_column_type (result,
147                            column))
148   {
149     GNUNET_break (0);
150     return GNUNET_SYSERR;
151   }
152   /* sqlite manual says to invoke 'sqlite3_column_blob()'
153      before calling sqlite3_column_bytes() */
154   ret = sqlite3_column_blob (result,
155                              column);
156   have = sqlite3_column_bytes (result,
157                                column);
158   if (*dst_size != have)
159   {
160     GNUNET_break (0);
161     return GNUNET_SYSERR;
162   }
163   GNUNET_memcpy (dst,
164                  ret,
165                  have);
166   return GNUNET_OK;
167 }
168
169
170 /**
171  * Fixed-size result expected.
172  *
173  * @param[out] dst where to store the result
174  * @param dst_size number of bytes in @a dst
175  * @return array entry for the result specification to use
176  */
177 struct GNUNET_SQ_ResultSpec
178 GNUNET_SQ_result_spec_fixed_size (void *dst,
179                                   size_t dst_size)
180 {
181   struct GNUNET_SQ_ResultSpec rs = {
182     .conv = &extract_fixed_blob,
183     .dst = dst,
184     .dst_size = dst_size,
185     .num_params = 1
186   };
187
188   return rs;
189 }
190
191
192 /**
193  * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
194  *
195  * @param cls closure
196  * @param result where to extract data from
197  * @param column column to extract data from
198  * @param[in,out] dst_size where to store size of result, may be NULL
199  * @param[out] dst where to store the result
200  * @return
201  *   #GNUNET_YES if all results could be extracted
202  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
203  */
204 static int
205 extract_utf8_string (void *cls,
206                      sqlite3_stmt *result,
207                      unsigned int column,
208                      size_t *dst_size,
209                      void *dst)
210 {
211   const char *text;
212   char **rdst = dst;
213
214   if (SQLITE_TEXT !=
215       sqlite3_column_type (result,
216                            column))
217   {
218     GNUNET_break (0);
219     return GNUNET_SYSERR;
220   }
221   /* sqlite manual guarantees that 'sqlite3_column_text()'
222      is 0-terminated */
223   text = (const char *) sqlite3_column_text (result,
224                                              column);
225   if (NULL == text)
226   {
227     GNUNET_break (0);
228     return GNUNET_SYSERR;
229   }
230   *dst_size = strlen (text) + 1;
231   *rdst = GNUNET_strdup (text);
232   return GNUNET_OK;
233 }
234
235
236 /**
237  * Cleanup memory allocated by #extract_var_blob().
238  *
239  * @param cls pointer to pointer of allocation
240  */
241 static void
242 clean_utf8_string (void *cls)
243 {
244   char **dptr = (char **) cls;
245
246   if (NULL != *dptr)
247   {
248     GNUNET_free (*dptr);
249     *dptr = NULL;
250   }
251 }
252
253
254 /**
255  * 0-terminated string expected.
256  *
257  * @param[out] dst where to store the result, allocated
258  * @return array entry for the result specification to use
259  */
260 struct GNUNET_SQ_ResultSpec
261 GNUNET_SQ_result_spec_string (char **dst)
262 {
263   struct GNUNET_SQ_ResultSpec rs = {
264     .conv = &extract_utf8_string,
265     .cleaner = &clean_utf8_string,
266     .cls = dst,
267     .dst = dst,
268     .num_params = 1
269   };
270
271   return rs;
272 }
273
274
275 /**
276  * Extract data from a Postgres database @a result at row @a row.
277  *
278  * @param cls closure
279  * @param result where to extract data from
280  * @param column column to extract data from
281  * @param[in,out] dst_size where to store size of result, may be NULL
282  * @param[out] dst where to store the result
283  * @return
284  *   #GNUNET_YES if all results could be extracted
285  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
286  */
287 static int
288 extract_rsa_pub (void *cls,
289                  sqlite3_stmt *result,
290                  unsigned int column,
291                  size_t *dst_size,
292                  void *dst)
293 {
294   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
295   int have;
296   const void *ret;
297
298   if (SQLITE_BLOB !=
299       sqlite3_column_type (result,
300                            column))
301   {
302     GNUNET_break (0);
303     return GNUNET_SYSERR;
304   }
305   /* sqlite manual says to invoke 'sqlite3_column_blob()'
306      before calling sqlite3_column_bytes() */
307   ret = sqlite3_column_blob (result,
308                              column);
309   have = sqlite3_column_bytes (result,
310                                column);
311   if (have < 0)
312   {
313     GNUNET_break (0);
314     return GNUNET_SYSERR;
315   }
316
317   *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret,
318                                              have);
319   if (NULL == *pk)
320   {
321     GNUNET_break (0);
322     return GNUNET_SYSERR;
323   }
324   return GNUNET_OK;
325 }
326
327
328 /**
329  * Function called to clean up memory allocated
330  * by a #GNUNET_PQ_ResultConverter.
331  *
332  * @param cls closure
333  */
334 static void
335 clean_rsa_pub (void *cls)
336 {
337   struct GNUNET_CRYPTO_RsaPublicKey **pk = cls;
338
339   if (NULL != *pk)
340   {
341     GNUNET_CRYPTO_rsa_public_key_free (*pk);
342     *pk = NULL;
343   }
344 }
345
346
347 /**
348  * RSA public key expected.
349  *
350  * @param[out] rsa where to store the result
351  * @return array entry for the result specification to use
352  */
353 struct GNUNET_SQ_ResultSpec
354 GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
355 {
356   struct GNUNET_SQ_ResultSpec rs = {
357     .conv = &extract_rsa_pub,
358     .cleaner = &clean_rsa_pub,
359     .dst = rsa,
360     .cls = rsa,
361     .num_params = 1
362   };
363
364   return rs;
365 }
366
367
368 /**
369  * Extract data from a Postgres database @a result at row @a row.
370  *
371  * @param cls closure
372  * @param result where to extract data from
373  * @param column column to extract data from
374  * @param[in,out] dst_size where to store size of result, may be NULL
375  * @param[out] dst where to store the result
376  * @return
377  *   #GNUNET_YES if all results could be extracted
378  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
379  */
380 static int
381 extract_rsa_sig (void *cls,
382                  sqlite3_stmt *result,
383                  unsigned int column,
384                  size_t *dst_size,
385                  void *dst)
386 {
387   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
388   int have;
389   const void *ret;
390
391   if (SQLITE_BLOB !=
392       sqlite3_column_type (result,
393                            column))
394   {
395     GNUNET_break (0);
396     return GNUNET_SYSERR;
397   }
398   /* sqlite manual says to invoke 'sqlite3_column_blob()'
399      before calling sqlite3_column_bytes() */
400   ret = sqlite3_column_blob (result,
401                              column);
402   have = sqlite3_column_bytes (result,
403                                column);
404   if (have < 0)
405   {
406     GNUNET_break (0);
407     return GNUNET_SYSERR;
408   }
409
410   *sig = GNUNET_CRYPTO_rsa_signature_decode (ret,
411                                              have);
412   if (NULL == *sig)
413   {
414     GNUNET_break (0);
415     return GNUNET_SYSERR;
416   }
417   return GNUNET_OK;
418 }
419
420
421 /**
422  * Function called to clean up memory allocated
423  * by a #GNUNET_PQ_ResultConverter.
424  *
425  * @param cls result data to clean up
426  */
427 static void
428 clean_rsa_sig (void *cls)
429 {
430   struct GNUNET_CRYPTO_RsaSignature **sig = cls;
431
432   if (NULL != *sig)
433   {
434     GNUNET_CRYPTO_rsa_signature_free (*sig);
435     *sig = NULL;
436   }
437 }
438
439
440 /**
441  * RSA signature expected.
442  *
443  * @param[out] sig where to store the result;
444  * @return array entry for the result specification to use
445  */
446 struct GNUNET_SQ_ResultSpec
447 GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
448 {
449   struct GNUNET_SQ_ResultSpec rs = {
450     .conv = &extract_rsa_sig,
451     .cleaner = &clean_rsa_sig,
452     .dst = sig,
453     .cls = sig,
454     .num_params = 1
455   };
456
457   return rs;
458 }
459
460
461 /**
462  * Absolute time expected.
463  *
464  * @param[out] at where to store the result
465  * @return array entry for the result specification to use
466  */
467 struct GNUNET_SQ_ResultSpec
468 GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
469 {
470   return GNUNET_SQ_result_spec_uint64 (&at->abs_value_us);
471 }
472
473
474 /**
475  * Extract absolute time value in NBO from a Postgres database @a result at row @a row.
476  *
477  * @param cls closure
478  * @param result where to extract data from
479  * @param column column to extract data from
480  * @param[in,out] dst_size where to store size of result, may be NULL
481  * @param[out] dst where to store the result
482  * @return
483  *   #GNUNET_YES if all results could be extracted
484  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
485  */
486 static int
487 extract_abs_time_nbo (void *cls,
488                       sqlite3_stmt *result,
489                       unsigned int column,
490                       size_t *dst_size,
491                       void *dst)
492 {
493   struct GNUNET_TIME_AbsoluteNBO *u = dst;
494   struct GNUNET_TIME_Absolute t;
495
496   GNUNET_assert (sizeof (uint64_t) == *dst_size);
497   if (SQLITE_INTEGER !=
498       sqlite3_column_type (result,
499                            column))
500   {
501     GNUNET_break (0);
502     return GNUNET_SYSERR;
503   }
504   t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
505                                                     column);
506   *u = GNUNET_TIME_absolute_hton (t);
507   return GNUNET_OK;
508 }
509
510
511 /**
512  * Absolute time expected.
513  *
514  * @param[out] at where to store the result
515  * @return array entry for the result specification to use
516  */
517 struct GNUNET_SQ_ResultSpec
518 GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
519 {
520   struct GNUNET_SQ_ResultSpec rs = {
521     .conv = &extract_abs_time_nbo,
522     .dst = at,
523     .dst_size = sizeof (struct GNUNET_TIME_AbsoluteNBO),
524     .num_params = 1
525   };
526
527   return rs;
528 }
529
530
531 /**
532  * Extract 16-bit integer from a Postgres database @a result at row @a row.
533  *
534  * @param cls closure
535  * @param result where to extract data from
536  * @param column column to extract data from
537  * @param[in,out] dst_size where to store size of result, may be NULL
538  * @param[out] dst where to store the result
539  * @return
540  *   #GNUNET_YES if all results could be extracted
541  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
542  */
543 static int
544 extract_uint16 (void *cls,
545                 sqlite3_stmt *result,
546                 unsigned int column,
547                 size_t *dst_size,
548                 void *dst)
549 {
550   uint64_t v;
551   uint32_t *u = dst;
552
553   GNUNET_assert (sizeof (uint16_t) == *dst_size);
554   if (SQLITE_INTEGER !=
555       sqlite3_column_type (result,
556                            column))
557   {
558     GNUNET_break (0);
559     return GNUNET_SYSERR;
560   }
561   v = (uint64_t) sqlite3_column_int64 (result,
562                                        column);
563   if (v > UINT16_MAX)
564   {
565     GNUNET_break (0);
566     return GNUNET_SYSERR;
567   }
568   *u = (uint16_t) v;
569   return GNUNET_OK;
570 }
571
572
573 /**
574  * uint16_t expected.
575  *
576  * @param[out] u16 where to store the result
577  * @return array entry for the result specification to use
578  */
579 struct GNUNET_SQ_ResultSpec
580 GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
581 {
582   struct GNUNET_SQ_ResultSpec rs = {
583     .conv = &extract_uint16,
584     .dst = u16,
585     .dst_size = sizeof (uint16_t),
586     .num_params = 1
587   };
588
589   return rs;
590 }
591
592
593 /**
594  * Extract 32-bit integer from a Postgres database @a result at row @a row.
595  *
596  * @param cls closure
597  * @param result where to extract data from
598  * @param column column to extract data from
599  * @param[in,out] dst_size where to store size of result, may be NULL
600  * @param[out] dst where to store the result
601  * @return
602  *   #GNUNET_YES if all results could be extracted
603  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
604  */
605 static int
606 extract_uint32 (void *cls,
607                 sqlite3_stmt *result,
608                 unsigned int column,
609                 size_t *dst_size,
610                 void *dst)
611 {
612   uint64_t v;
613   uint32_t *u = dst;
614
615   GNUNET_assert (sizeof (uint32_t) == *dst_size);
616   if (SQLITE_INTEGER !=
617       sqlite3_column_type (result,
618                            column))
619   {
620     GNUNET_break (0);
621     return GNUNET_SYSERR;
622   }
623   v = (uint64_t) sqlite3_column_int64 (result,
624                                        column);
625   if (v > UINT32_MAX)
626   {
627     GNUNET_break (0);
628     return GNUNET_SYSERR;
629   }
630   *u = (uint32_t) v;
631   return GNUNET_OK;
632 }
633
634
635 /**
636  * uint32_t expected.
637  *
638  * @param[out] u32 where to store the result
639  * @return array entry for the result specification to use
640  */
641 struct GNUNET_SQ_ResultSpec
642 GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
643 {
644   struct GNUNET_SQ_ResultSpec rs = {
645     .conv = &extract_uint32,
646     .dst = u32,
647     .dst_size = sizeof (uint32_t),
648     .num_params = 1
649   };
650
651   return rs;
652 }
653
654
655 /**
656  * Extract 64-bit integer from a Postgres database @a result at row @a row.
657  *
658  * @param cls closure
659  * @param result where to extract data from
660  * @param column column to extract data from
661  * @param[in,out] dst_size where to store size of result, may be NULL
662  * @param[out] dst where to store the result
663  * @return
664  *   #GNUNET_YES if all results could be extracted
665  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
666  */
667 static int
668 extract_uint64 (void *cls,
669                 sqlite3_stmt *result,
670                 unsigned int column,
671                 size_t *dst_size,
672                 void *dst)
673 {
674   uint64_t *u = dst;
675
676   GNUNET_assert (sizeof (uint64_t) == *dst_size);
677   if (SQLITE_INTEGER !=
678       sqlite3_column_type (result,
679                            column))
680   {
681     GNUNET_break (0);
682     return GNUNET_SYSERR;
683   }
684   *u = (uint64_t) sqlite3_column_int64 (result,
685                                         column);
686   return GNUNET_OK;
687 }
688
689
690 /**
691  * uint64_t expected.
692  *
693  * @param[out] u64 where to store the result
694  * @return array entry for the result specification to use
695  */
696 struct GNUNET_SQ_ResultSpec
697 GNUNET_SQ_result_spec_uint64 (uint64_t *u64)
698 {
699   struct GNUNET_SQ_ResultSpec rs = {
700     .conv = &extract_uint64,
701     .dst = u64,
702     .dst_size = sizeof (uint64_t),
703     .num_params = 1
704   };
705
706   return rs;
707 }
708
709
710 /* end of sq_result_helper.c */