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