use NULL value in load_path_suffix to NOT load any files
[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
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 pq/pq_result_helper.c
22  * @brief functions to extract result values
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_pq_lib.h"
28
29
30 /**
31  * Function called to clean up memory allocated
32  * by a #GNUNET_PQ_ResultConverter.
33  *
34  * @param cls closure
35  * @param rd result data to clean up
36  */
37 static void
38 clean_varsize_blob (void *cls,
39                     void *rd)
40 {
41   void **dst = rd;
42
43   (void) cls;
44   if (NULL != *dst)
45   {
46     GNUNET_free (*dst);
47     *dst = NULL;
48   }
49 }
50
51
52 /**
53  * Extract data from a Postgres database @a result at row @a row.
54  *
55  * @param cls closure
56  * @param result where to extract data from
57  * @param int row to extract data from
58  * @param fname name (or prefix) of the fields to extract from
59  * @param[in,out] dst_size where to store size of result, may be NULL
60  * @param[out] dst where to store the result
61  * @return
62  *   #GNUNET_YES if all results could be extracted
63  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
64  */
65 static int
66 extract_varsize_blob (void *cls,
67                       PGresult *result,
68                       int row,
69                       const char *fname,
70                       size_t *dst_size,
71                       void *dst)
72 {
73   size_t len;
74   const char *res;
75   void *idst;
76   int fnum;
77
78   (void) cls;
79   *dst_size = 0;
80   *((void **) dst) = NULL;
81
82   fnum = PQfnumber (result,
83                     fname);
84   if (fnum < 0)
85   {
86     GNUNET_break (0);
87     return GNUNET_SYSERR;
88   }
89   if (PQgetisnull (result,
90                    row,
91                    fnum))
92   {
93     /* Let's allow this for varsize */
94     return GNUNET_OK;
95   }
96   /* if a field is null, continue but
97    * remember that we now return a different result */
98   len = PQgetlength (result,
99                      row,
100                      fnum);
101   res = PQgetvalue (result,
102                     row,
103                     fnum);
104   GNUNET_assert (NULL != res);
105   *dst_size = len;
106   idst = GNUNET_malloc (len);
107   *((void **) dst) = idst;
108   GNUNET_memcpy (idst,
109                  res,
110                  len);
111   return GNUNET_OK;
112 }
113
114
115 /**
116  * Variable-size result expected.
117  *
118  * @param name name of the field in the table
119  * @param[out] dst where to store the result, allocated
120  * @param[out] sptr where to store the size of @a dst
121  * @return array entry for the result specification to use
122  */
123 struct GNUNET_PQ_ResultSpec
124 GNUNET_PQ_result_spec_variable_size (const char *name,
125                                      void **dst,
126                                      size_t *sptr)
127 {
128   struct GNUNET_PQ_ResultSpec res =
129   { &extract_varsize_blob,
130     &clean_varsize_blob, NULL,
131     (void *) (dst), 0, name, sptr };
132
133   return res;
134 }
135
136
137 /**
138  * Extract data from a Postgres database @a result at row @a row.
139  *
140  * @param cls closure
141  * @param result where to extract data from
142  * @param int row to extract data from
143  * @param fname name (or prefix) of the fields to extract from
144  * @param[in] dst_size desired size, never NULL
145  * @param[out] dst where to store the result
146  * @return
147  *   #GNUNET_YES if all results could be extracted
148  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
149  */
150 static int
151 extract_fixed_blob (void *cls,
152                     PGresult *result,
153                     int row,
154                     const char *fname,
155                     size_t *dst_size,
156                     void *dst)
157 {
158   size_t len;
159   const char *res;
160   int fnum;
161
162   (void) cls;
163   fnum = PQfnumber (result,
164                     fname);
165   if (fnum < 0)
166   {
167     GNUNET_break (0);
168     return GNUNET_SYSERR;
169   }
170   if (PQgetisnull (result,
171                    row,
172                    fnum))
173   {
174     GNUNET_break (0);
175     return GNUNET_SYSERR;
176   }
177
178   /* if a field is null, continue but
179    * remember that we now return a different result */
180   len = PQgetlength (result,
181                      row,
182                      fnum);
183   if (*dst_size != len)
184   {
185     GNUNET_break (0);
186     return GNUNET_SYSERR;
187   }
188   res = PQgetvalue (result,
189                     row,
190                     fnum);
191   GNUNET_assert (NULL != res);
192   GNUNET_memcpy (dst,
193                  res,
194                  len);
195   return GNUNET_OK;
196 }
197
198
199 /**
200  * Fixed-size result expected.
201  *
202  * @param name name of the field in the table
203  * @param[out] dst where to store the result
204  * @param dst_size number of bytes in @a dst
205  * @return array entry for the result specification to use
206  */
207 struct GNUNET_PQ_ResultSpec
208 GNUNET_PQ_result_spec_fixed_size (const char *name,
209                                   void *dst,
210                                   size_t dst_size)
211 {
212   struct GNUNET_PQ_ResultSpec res =
213   { &extract_fixed_blob,
214     NULL, NULL,
215     (dst), dst_size, name, NULL };
216
217   return res;
218 }
219
220
221 /**
222  * Extract data from a Postgres database @a result at row @a row.
223  *
224  * @param cls closure
225  * @param result where to extract data from
226  * @param int row to extract data from
227  * @param fname name (or prefix) of the fields to extract from
228  * @param[in,out] dst_size where to store size of result, may be NULL
229  * @param[out] dst where to store the result
230  * @return
231  *   #GNUNET_YES if all results could be extracted
232  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
233  */
234 static int
235 extract_rsa_public_key (void *cls,
236                         PGresult *result,
237                         int row,
238                         const char *fname,
239                         size_t *dst_size,
240                         void *dst)
241 {
242   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
243   size_t len;
244   const char *res;
245   int fnum;
246
247   (void) cls;
248   *pk = NULL;
249   fnum = PQfnumber (result,
250                     fname);
251   if (fnum < 0)
252   {
253     GNUNET_break (0);
254     return GNUNET_SYSERR;
255   }
256   if (PQgetisnull (result,
257                    row,
258                    fnum))
259   {
260     GNUNET_break (0);
261     return GNUNET_SYSERR;
262   }
263   /* if a field is null, continue but
264    * remember that we now return a different result */
265   len = PQgetlength (result,
266                      row,
267                      fnum);
268   res = PQgetvalue (result,
269                     row,
270                     fnum);
271   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
272                                              len);
273   if (NULL == *pk)
274   {
275     GNUNET_break (0);
276     return GNUNET_SYSERR;
277   }
278   return GNUNET_OK;
279 }
280
281
282 /**
283  * Function called to clean up memory allocated
284  * by a #GNUNET_PQ_ResultConverter.
285  *
286  * @param cls closure
287  * @param rd result data to clean up
288  */
289 static void
290 clean_rsa_public_key (void *cls,
291                       void *rd)
292 {
293   struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
294
295   (void) cls;
296   if (NULL != *pk)
297   {
298     GNUNET_CRYPTO_rsa_public_key_free (*pk);
299     *pk = NULL;
300   }
301 }
302
303
304 /**
305  * RSA public key expected.
306  *
307  * @param name name of the field in the table
308  * @param[out] rsa where to store the result
309  * @return array entry for the result specification to use
310  */
311 struct GNUNET_PQ_ResultSpec
312 GNUNET_PQ_result_spec_rsa_public_key (const char *name,
313                                       struct GNUNET_CRYPTO_RsaPublicKey **rsa)
314 {
315   struct GNUNET_PQ_ResultSpec res =
316   { &extract_rsa_public_key,
317     &clean_rsa_public_key,
318     NULL,
319     (void *) rsa, 0, name, NULL };
320
321   return res;
322 }
323
324
325 /**
326  * Extract data from a Postgres database @a result at row @a row.
327  *
328  * @param cls closure
329  * @param result where to extract data from
330  * @param int row to extract data from
331  * @param fname name (or prefix) of the fields to extract from
332  * @param[in,out] dst_size where to store size of result, may be NULL
333  * @param[out] dst where to store the result
334  * @return
335  *   #GNUNET_YES if all results could be extracted
336  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
337  */
338 static int
339 extract_rsa_signature (void *cls,
340                        PGresult *result,
341                        int row,
342                        const char *fname,
343                        size_t *dst_size,
344                        void *dst)
345 {
346   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
347   size_t len;
348   const char *res;
349   int fnum;
350
351   (void) cls;
352   *sig = NULL;
353   fnum = PQfnumber (result,
354                     fname);
355   if (fnum < 0)
356   {
357     GNUNET_break (0);
358     return GNUNET_SYSERR;
359   }
360   if (PQgetisnull (result,
361                    row,
362                    fnum))
363   {
364     GNUNET_break (0);
365     return GNUNET_SYSERR;
366   }
367   /* if a field is null, continue but
368    * remember that we now return a different result */
369   len = PQgetlength (result,
370                      row,
371                      fnum);
372   res = PQgetvalue (result,
373                     row,
374                     fnum);
375   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
376                                              len);
377   if (NULL == *sig)
378   {
379     GNUNET_break (0);
380     return GNUNET_SYSERR;
381   }
382   return GNUNET_OK;
383 }
384
385
386 /**
387  * Function called to clean up memory allocated
388  * by a #GNUNET_PQ_ResultConverter.
389  *
390  * @param cls closure
391  * @param rd result data to clean up
392  */
393 static void
394 clean_rsa_signature (void *cls,
395                      void *rd)
396 {
397   struct GNUNET_CRYPTO_RsaSignature **sig = rd;
398
399   (void) cls;
400   if (NULL != *sig)
401   {
402     GNUNET_CRYPTO_rsa_signature_free (*sig);
403     *sig = NULL;
404   }
405 }
406
407
408 /**
409  * RSA signature expected.
410  *
411  * @param name name of the field in the table
412  * @param[out] sig where to store the result;
413  * @return array entry for the result specification to use
414  */
415 struct GNUNET_PQ_ResultSpec
416 GNUNET_PQ_result_spec_rsa_signature (const char *name,
417                                      struct GNUNET_CRYPTO_RsaSignature **sig)
418 {
419   struct GNUNET_PQ_ResultSpec res =
420   { &extract_rsa_signature,
421     &clean_rsa_signature,
422     NULL,
423     (void *) sig, 0, (name), NULL };
424
425   return res;
426 }
427
428
429 /**
430  * Extract data from a Postgres database @a result at row @a row.
431  *
432  * @param cls closure
433  * @param result where to extract data from
434  * @param int row to extract data from
435  * @param fname name (or prefix) of the fields to extract from
436  * @param[in,out] dst_size where to store size of result, may be NULL
437  * @param[out] dst where to store the result
438  * @return
439  *   #GNUNET_YES if all results could be extracted
440  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
441  */
442 static int
443 extract_string (void *cls,
444                 PGresult *result,
445                 int row,
446                 const char *fname,
447                 size_t *dst_size,
448                 void *dst)
449 {
450   char **str = dst;
451   size_t len;
452   const char *res;
453   int fnum;
454
455   (void) cls;
456   *str = NULL;
457   fnum = PQfnumber (result,
458                     fname);
459   if (fnum < 0)
460   {
461     GNUNET_break (0);
462     return GNUNET_SYSERR;
463   }
464   if (PQgetisnull (result,
465                    row,
466                    fnum))
467   {
468     GNUNET_break (0);
469     return GNUNET_SYSERR;
470   }
471   /* if a field is null, continue but
472    * remember that we now return a different result */
473   len = PQgetlength (result,
474                      row,
475                      fnum);
476   res = PQgetvalue (result,
477                     row,
478                     fnum);
479   *str = GNUNET_strndup (res,
480                          len);
481   if (NULL == *str)
482   {
483     GNUNET_break (0);
484     return GNUNET_SYSERR;
485   }
486   return GNUNET_OK;
487 }
488
489
490 /**
491  * Function called to clean up memory allocated
492  * by a #GNUNET_PQ_ResultConverter.
493  *
494  * @param cls closure
495  * @param rd result data to clean up
496  */
497 static void
498 clean_string (void *cls,
499               void *rd)
500 {
501   char **str = rd;
502
503   (void) cls;
504   if (NULL != *str)
505   {
506     GNUNET_free (*str);
507     *str = NULL;
508   }
509 }
510
511
512 /**
513  * 0-terminated string expected.
514  *
515  * @param name name of the field in the table
516  * @param[out] dst where to store the result, allocated
517  * @return array entry for the result specification to use
518  */
519 struct GNUNET_PQ_ResultSpec
520 GNUNET_PQ_result_spec_string (const char *name,
521                               char **dst)
522 {
523   struct GNUNET_PQ_ResultSpec res =
524   { &extract_string,
525     &clean_string,
526     NULL,
527     (void *) dst, 0, (name), NULL };
528
529   return res;
530 }
531
532
533 /**
534  * Extract data from a Postgres database @a result at row @a row.
535  *
536  * @param cls closure
537  * @param result where to extract data from
538  * @param int row to extract data from
539  * @param fname name (or prefix) of the fields to extract from
540  * @param[in,out] dst_size where to store size of result, may be NULL
541  * @param[out] dst where to store the result
542  * @return
543  *   #GNUNET_YES if all results could be extracted
544  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
545  */
546 static int
547 extract_abs_time (void *cls,
548                   PGresult *result,
549                   int row,
550                   const char *fname,
551                   size_t *dst_size,
552                   void *dst)
553 {
554   struct GNUNET_TIME_Absolute *udst = dst;
555   const int64_t *res;
556   int fnum;
557
558   (void) cls;
559   fnum = PQfnumber (result,
560                     fname);
561   if (fnum < 0)
562   {
563     GNUNET_break (0);
564     return GNUNET_SYSERR;
565   }
566   if (PQgetisnull (result,
567                    row,
568                    fnum))
569   {
570     GNUNET_break (0);
571     return GNUNET_SYSERR;
572   }
573   GNUNET_assert (NULL != dst);
574   if (sizeof(struct GNUNET_TIME_Absolute) != *dst_size)
575   {
576     GNUNET_break (0);
577     return GNUNET_SYSERR;
578   }
579   if (sizeof(int64_t) !=
580       PQgetlength (result,
581                    row,
582                    fnum))
583   {
584     GNUNET_break (0);
585     return GNUNET_SYSERR;
586   }
587   res = (int64_t *) PQgetvalue (result,
588                                 row,
589                                 fnum);
590   if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
591     *udst = GNUNET_TIME_UNIT_FOREVER_ABS;
592   else
593     udst->abs_value_us = GNUNET_ntohll ((uint64_t) *res);
594   return GNUNET_OK;
595 }
596
597
598 /**
599  * Absolute time expected.
600  *
601  * @param name name of the field in the table
602  * @param[out] at where to store the result
603  * @return array entry for the result specification to use
604  */
605 struct GNUNET_PQ_ResultSpec
606 GNUNET_PQ_result_spec_absolute_time (const char *name,
607                                      struct GNUNET_TIME_Absolute *at)
608 {
609   struct GNUNET_PQ_ResultSpec res =
610   { &extract_abs_time,
611     NULL,
612     NULL,
613     (void *) at, sizeof(*at), (name), NULL };
614
615   return res;
616 }
617
618
619 /**
620  * Absolute time in network byte order expected.
621  *
622  * @param name name of the field in the table
623  * @param[out] at where to store the result
624  * @return array entry for the result specification to use
625  */
626 struct GNUNET_PQ_ResultSpec
627 GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
628                                          struct GNUNET_TIME_AbsoluteNBO *at)
629 {
630   struct GNUNET_PQ_ResultSpec res =
631     GNUNET_PQ_result_spec_auto_from_type (name, &at->abs_value_us__);
632
633   return res;
634 }
635
636
637 /**
638  * Extract data from a Postgres database @a result at row @a row.
639  *
640  * @param cls closure
641  * @param result where to extract data from
642  * @param int row to extract data from
643  * @param fname name (or prefix) of the fields to extract from
644  * @param[in,out] dst_size where to store size of result, may be NULL
645  * @param[out] dst where to store the result
646  * @return
647  *   #GNUNET_YES if all results could be extracted
648  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
649  */
650 static int
651 extract_uint16 (void *cls,
652                 PGresult *result,
653                 int row,
654                 const char *fname,
655                 size_t *dst_size,
656                 void *dst)
657 {
658   uint16_t *udst = dst;
659   const uint16_t *res;
660   int fnum;
661
662   (void) cls;
663   fnum = PQfnumber (result,
664                     fname);
665   if (fnum < 0)
666   {
667     GNUNET_break (0);
668     return GNUNET_SYSERR;
669   }
670   if (PQgetisnull (result,
671                    row,
672                    fnum))
673   {
674     GNUNET_break (0);
675     return GNUNET_SYSERR;
676   }
677   GNUNET_assert (NULL != dst);
678   if (sizeof(uint16_t) != *dst_size)
679   {
680     GNUNET_break (0);
681     return GNUNET_SYSERR;
682   }
683   if (sizeof(uint16_t) !=
684       PQgetlength (result,
685                    row,
686                    fnum))
687   {
688     GNUNET_break (0);
689     return GNUNET_SYSERR;
690   }
691   res = (uint16_t *) PQgetvalue (result,
692                                  row,
693                                  fnum);
694   *udst = ntohs (*res);
695   return GNUNET_OK;
696 }
697
698
699 /**
700  * uint16_t expected.
701  *
702  * @param name name of the field in the table
703  * @param[out] u16 where to store the result
704  * @return array entry for the result specification to use
705  */
706 struct GNUNET_PQ_ResultSpec
707 GNUNET_PQ_result_spec_uint16 (const char *name,
708                               uint16_t *u16)
709 {
710   struct GNUNET_PQ_ResultSpec res =
711   { &extract_uint16,
712     NULL,
713     NULL,
714     (void *) u16, sizeof(*u16), (name), NULL };
715
716   return res;
717 }
718
719
720 /**
721  * Extract data from a Postgres database @a result at row @a row.
722  *
723  * @param cls closure
724  * @param result where to extract data from
725  * @param int row to extract data from
726  * @param fname name (or prefix) of the fields to extract from
727  * @param[in,out] dst_size where to store size of result, may be NULL
728  * @param[out] dst where to store the result
729  * @return
730  *   #GNUNET_YES if all results could be extracted
731  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
732  */
733 static int
734 extract_uint32 (void *cls,
735                 PGresult *result,
736                 int row,
737                 const char *fname,
738                 size_t *dst_size,
739                 void *dst)
740 {
741   uint32_t *udst = dst;
742   const uint32_t *res;
743   int fnum;
744
745   (void) cls;
746   fnum = PQfnumber (result,
747                     fname);
748   if (fnum < 0)
749   {
750     GNUNET_break (0);
751     return GNUNET_SYSERR;
752   }
753   if (PQgetisnull (result,
754                    row,
755                    fnum))
756   {
757     GNUNET_break (0);
758     return GNUNET_SYSERR;
759   }
760   GNUNET_assert (NULL != dst);
761   if (sizeof(uint32_t) != *dst_size)
762   {
763     GNUNET_break (0);
764     return GNUNET_SYSERR;
765   }
766   if (sizeof(uint32_t) !=
767       PQgetlength (result,
768                    row,
769                    fnum))
770   {
771     GNUNET_break (0);
772     return GNUNET_SYSERR;
773   }
774   res = (uint32_t *) PQgetvalue (result,
775                                  row,
776                                  fnum);
777   *udst = ntohl (*res);
778   return GNUNET_OK;
779 }
780
781
782 /**
783  * uint32_t expected.
784  *
785  * @param name name of the field in the table
786  * @param[out] u32 where to store the result
787  * @return array entry for the result specification to use
788  */
789 struct GNUNET_PQ_ResultSpec
790 GNUNET_PQ_result_spec_uint32 (const char *name,
791                               uint32_t *u32)
792 {
793   struct GNUNET_PQ_ResultSpec res =
794   { &extract_uint32,
795     NULL,
796     NULL,
797     (void *) u32, sizeof(*u32), (name), NULL };
798
799   return res;
800 }
801
802
803 /**
804  * Extract data from a Postgres database @a result at row @a row.
805  *
806  * @param cls closure
807  * @param result where to extract data from
808  * @param int row to extract data from
809  * @param fname name (or prefix) of the fields to extract from
810  * @param[in,out] dst_size where to store size of result, may be NULL
811  * @param[out] dst where to store the result
812  * @return
813  *   #GNUNET_YES if all results could be extracted
814  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
815  */
816 static int
817 extract_uint64 (void *cls,
818                 PGresult *result,
819                 int row,
820                 const char *fname,
821                 size_t *dst_size,
822                 void *dst)
823 {
824   uint64_t *udst = dst;
825   const uint64_t *res;
826   int fnum;
827
828   (void) cls;
829   fnum = PQfnumber (result,
830                     fname);
831   if (fnum < 0)
832   {
833     GNUNET_break (0);
834     return GNUNET_SYSERR;
835   }
836   if (PQgetisnull (result,
837                    row,
838                    fnum))
839   {
840     GNUNET_break (0);
841     return GNUNET_SYSERR;
842   }
843   GNUNET_assert (NULL != dst);
844   if (sizeof(uint64_t) != *dst_size)
845   {
846     GNUNET_break (0);
847     return GNUNET_SYSERR;
848   }
849   if (sizeof(uint64_t) !=
850       PQgetlength (result,
851                    row,
852                    fnum))
853   {
854     GNUNET_break (0);
855     return GNUNET_SYSERR;
856   }
857   res = (uint64_t *) PQgetvalue (result,
858                                  row,
859                                  fnum);
860   *udst = GNUNET_ntohll (*res);
861   return GNUNET_OK;
862 }
863
864
865 /**
866  * uint64_t expected.
867  *
868  * @param name name of the field in the table
869  * @param[out] u64 where to store the result
870  * @return array entry for the result specification to use
871  */
872 struct GNUNET_PQ_ResultSpec
873 GNUNET_PQ_result_spec_uint64 (const char *name,
874                               uint64_t *u64)
875 {
876   struct GNUNET_PQ_ResultSpec res =
877   { &extract_uint64,
878     NULL,
879     NULL,
880     (void *) u64, sizeof(*u64), (name), NULL };
881
882   return res;
883 }
884
885
886 /* end of pq_result_helper.c */