remove CYGWIN codeblocks, drop vendored Windows openvpn, drop win32 specific 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 == *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 */