GNUnet  0.11.x
pq_result_helper.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2014, 2015, 2016, 2020 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  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_pq_lib.h"
28 
29 
32  bool *is_null)
33 {
34  struct GNUNET_PQ_ResultSpec rsr;
35 
36  rsr = rs;
37  rsr.is_nullable = true;
38  rsr.is_null = is_null;
39  return rsr;
40 }
41 
42 
50 static void
52  void *rd)
53 {
54  void **dst = rd;
55 
56  (void) cls;
57  if (NULL != *dst)
58  {
59  GNUNET_free (*dst);
60  *dst = NULL;
61  }
62 }
63 
64 
78 static int
80  PGresult *result,
81  int row,
82  const char *fname,
83  size_t *dst_size,
84  void *dst)
85 {
86  size_t len;
87  const char *res;
88  void *idst;
89  int fnum;
90 
91  (void) cls;
92  *dst_size = 0;
93  *((void **) dst) = NULL;
94 
95  fnum = PQfnumber (result,
96  fname);
97  if (fnum < 0)
98  {
99  GNUNET_break (0);
100  return GNUNET_SYSERR;
101  }
102  if (PQgetisnull (result,
103  row,
104  fnum))
105  {
106  /* Let's allow this for varsize */
107  return GNUNET_OK;
108  }
109  /* if a field is null, continue but
110  * remember that we now return a different result */
111  len = PQgetlength (result,
112  row,
113  fnum);
114  res = PQgetvalue (result,
115  row,
116  fnum);
117  GNUNET_assert (NULL != res);
118  *dst_size = len;
119  idst = GNUNET_malloc (len);
120  *((void **) dst) = idst;
121  GNUNET_memcpy (idst,
122  res,
123  len);
124  return GNUNET_OK;
125 }
126 
127 
130  void **dst,
131  size_t *sptr)
132 {
133  struct GNUNET_PQ_ResultSpec res =
135  &clean_varsize_blob, NULL,
136  (void *) (dst), 0, name, sptr };
137 
138  return res;
139 }
140 
141 
155 static int
157  PGresult *result,
158  int row,
159  const char *fname,
160  size_t *dst_size,
161  void *dst)
162 {
163  size_t len;
164  const char *res;
165  int fnum;
166 
167  (void) cls;
168  fnum = PQfnumber (result,
169  fname);
170  if (fnum < 0)
171  {
172  GNUNET_break (0);
173  return GNUNET_SYSERR;
174  }
175  if (PQgetisnull (result,
176  row,
177  fnum))
178  {
179  GNUNET_break (0);
180  return GNUNET_SYSERR;
181  }
182 
183  /* if a field is null, continue but
184  * remember that we now return a different result */
185  len = PQgetlength (result,
186  row,
187  fnum);
188  if (*dst_size != len)
189  {
190  GNUNET_break (0);
191  return GNUNET_SYSERR;
192  }
193  res = PQgetvalue (result,
194  row,
195  fnum);
196  GNUNET_assert (NULL != res);
197  GNUNET_memcpy (dst,
198  res,
199  len);
200  return GNUNET_OK;
201 }
202 
203 
206  void *dst,
207  size_t dst_size)
208 {
209  struct GNUNET_PQ_ResultSpec res =
211  NULL, NULL,
212  (dst), dst_size, name, NULL };
213 
214  return res;
215 }
216 
217 
231 static int
233  PGresult *result,
234  int row,
235  const char *fname,
236  size_t *dst_size,
237  void *dst)
238 {
239  struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
240  size_t len;
241  const char *res;
242  int fnum;
243 
244  (void) cls;
245  *pk = NULL;
246  fnum = PQfnumber (result,
247  fname);
248  if (fnum < 0)
249  {
250  GNUNET_break (0);
251  return GNUNET_SYSERR;
252  }
253  if (PQgetisnull (result,
254  row,
255  fnum))
256  {
257  GNUNET_break (0);
258  return GNUNET_SYSERR;
259  }
260  /* if a field is null, continue but
261  * remember that we now return a different result */
262  len = PQgetlength (result,
263  row,
264  fnum);
265  res = PQgetvalue (result,
266  row,
267  fnum);
269  len);
270  if (NULL == *pk)
271  {
272  GNUNET_break (0);
273  return GNUNET_SYSERR;
274  }
275  return GNUNET_OK;
276 }
277 
278 
286 static void
288  void *rd)
289 {
290  struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
291 
292  (void) cls;
293  if (NULL != *pk)
294  {
296  *pk = NULL;
297  }
298 }
299 
300 
303  struct GNUNET_CRYPTO_RsaPublicKey **rsa)
304 {
305  struct GNUNET_PQ_ResultSpec res =
308  NULL,
309  (void *) rsa, 0, name, NULL };
310 
311  return res;
312 }
313 
314 
328 static int
330  PGresult *result,
331  int row,
332  const char *fname,
333  size_t *dst_size,
334  void *dst)
335 {
336  struct GNUNET_CRYPTO_RsaSignature **sig = dst;
337  size_t len;
338  const void *res;
339  int fnum;
340 
341  (void) cls;
342  *sig = NULL;
343  fnum = PQfnumber (result,
344  fname);
345  if (fnum < 0)
346  {
347  GNUNET_break (0);
348  return GNUNET_SYSERR;
349  }
350  if (PQgetisnull (result,
351  row,
352  fnum))
353  {
354  GNUNET_break (0);
355  return GNUNET_SYSERR;
356  }
357  /* if a field is null, continue but
358  * remember that we now return a different result */
359  len = PQgetlength (result,
360  row,
361  fnum);
362  res = PQgetvalue (result,
363  row,
364  fnum);
366  len);
367  if (NULL == *sig)
368  {
369  GNUNET_break (0);
370  return GNUNET_SYSERR;
371  }
372  return GNUNET_OK;
373 }
374 
375 
383 static void
385  void *rd)
386 {
387  struct GNUNET_CRYPTO_RsaSignature **sig = rd;
388 
389  (void) cls;
390  if (NULL != *sig)
391  {
393  *sig = NULL;
394  }
395 }
396 
397 
400  struct GNUNET_CRYPTO_RsaSignature **sig)
401 {
402  struct GNUNET_PQ_ResultSpec res =
405  NULL,
406  (void *) sig, 0, (name), NULL };
407 
408  return res;
409 }
410 
411 
425 static int
427  PGresult *result,
428  int row,
429  const char *fname,
430  size_t *dst_size,
431  void *dst)
432 {
433  char **str = dst;
434  size_t len;
435  const char *res;
436  int fnum;
437 
438  (void) cls;
439  *str = NULL;
440  fnum = PQfnumber (result,
441  fname);
442  if (fnum < 0)
443  {
444  GNUNET_break (0);
445  return GNUNET_SYSERR;
446  }
447  if (PQgetisnull (result,
448  row,
449  fnum))
450  {
451  GNUNET_break (0);
452  return GNUNET_SYSERR;
453  }
454  /* if a field is null, continue but
455  * remember that we now return a different result */
456  len = PQgetlength (result,
457  row,
458  fnum);
459  res = PQgetvalue (result,
460  row,
461  fnum);
462  *str = GNUNET_strndup (res,
463  len);
464  if (NULL == *str)
465  {
466  GNUNET_break (0);
467  return GNUNET_SYSERR;
468  }
469  return GNUNET_OK;
470 }
471 
472 
480 static void
482  void *rd)
483 {
484  char **str = rd;
485 
486  (void) cls;
487  if (NULL != *str)
488  {
489  GNUNET_free (*str);
490  *str = NULL;
491  }
492 }
493 
494 
497  char **dst)
498 {
499  struct GNUNET_PQ_ResultSpec res =
500  { &extract_string,
501  &clean_string,
502  NULL,
503  (void *) dst, 0, (name), NULL };
504 
505  return res;
506 }
507 
508 
522 static int
524  PGresult *result,
525  int row,
526  const char *fname,
527  size_t *dst_size,
528  void *dst)
529 {
530  struct GNUNET_TIME_Relative *udst = dst;
531  const int64_t *res;
532  int fnum;
533 
534  (void) cls;
535  fnum = PQfnumber (result,
536  fname);
537  if (fnum < 0)
538  {
539  GNUNET_break (0);
540  return GNUNET_SYSERR;
541  }
542  if (PQgetisnull (result,
543  row,
544  fnum))
545  {
546  GNUNET_break (0);
547  return GNUNET_SYSERR;
548  }
549  GNUNET_assert (NULL != dst);
550  if (sizeof(struct GNUNET_TIME_Relative) != *dst_size)
551  {
552  GNUNET_break (0);
553  return GNUNET_SYSERR;
554  }
555  if (sizeof(int64_t) !=
556  PQgetlength (result,
557  row,
558  fnum))
559  {
560  GNUNET_break (0);
561  return GNUNET_SYSERR;
562  }
563  res = (int64_t *) PQgetvalue (result,
564  row,
565  fnum);
566  if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
568  else
569  udst->rel_value_us = GNUNET_ntohll ((uint64_t) *res);
570  return GNUNET_OK;
571 }
572 
573 
576  struct GNUNET_TIME_Relative *rt)
577 {
578  struct GNUNET_PQ_ResultSpec res = {
580  NULL,
581  NULL,
582  (void *) rt,
583  sizeof(*rt),
584  name,
585  NULL
586  };
587 
588  return res;
589 }
590 
591 
605 static int
607  PGresult *result,
608  int row,
609  const char *fname,
610  size_t *dst_size,
611  void *dst)
612 {
613  struct GNUNET_TIME_Absolute *udst = dst;
614  const int64_t *res;
615  int fnum;
616 
617  (void) cls;
618  fnum = PQfnumber (result,
619  fname);
620  if (fnum < 0)
621  {
622  GNUNET_break (0);
623  return GNUNET_SYSERR;
624  }
625  if (PQgetisnull (result,
626  row,
627  fnum))
628  {
629  GNUNET_break (0);
630  return GNUNET_SYSERR;
631  }
632  GNUNET_assert (NULL != dst);
633  if (sizeof(struct GNUNET_TIME_Absolute) != *dst_size)
634  {
635  GNUNET_break (0);
636  return GNUNET_SYSERR;
637  }
638  if (sizeof(int64_t) !=
639  PQgetlength (result,
640  row,
641  fnum))
642  {
643  GNUNET_break (0);
644  return GNUNET_SYSERR;
645  }
646  res = (int64_t *) PQgetvalue (result,
647  row,
648  fnum);
649  if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
651  else
652  udst->abs_value_us = GNUNET_ntohll ((uint64_t) *res);
653  return GNUNET_OK;
654 }
655 
656 
659  struct GNUNET_TIME_Absolute *at)
660 {
661  struct GNUNET_PQ_ResultSpec res =
662  { &extract_abs_time,
663  NULL,
664  NULL,
665  (void *) at, sizeof(*at), (name), NULL };
666 
667  return res;
668 }
669 
670 
673  struct GNUNET_TIME_AbsoluteNBO *at)
674 {
675  struct GNUNET_PQ_ResultSpec res =
676  GNUNET_PQ_result_spec_auto_from_type (name, &at->abs_value_us__);
677 
678  return res;
679 }
680 
681 
695 static int
697  PGresult *result,
698  int row,
699  const char *fname,
700  size_t *dst_size,
701  void *dst)
702 {
703  uint16_t *udst = dst;
704  const uint16_t *res;
705  int fnum;
706 
707  (void) cls;
708  fnum = PQfnumber (result,
709  fname);
710  if (fnum < 0)
711  {
712  GNUNET_break (0);
713  return GNUNET_SYSERR;
714  }
715  if (PQgetisnull (result,
716  row,
717  fnum))
718  {
719  GNUNET_break (0);
720  return GNUNET_SYSERR;
721  }
722  GNUNET_assert (NULL != dst);
723  if (sizeof(uint16_t) != *dst_size)
724  {
725  GNUNET_break (0);
726  return GNUNET_SYSERR;
727  }
728  if (sizeof(uint16_t) !=
729  PQgetlength (result,
730  row,
731  fnum))
732  {
733  GNUNET_break (0);
734  return GNUNET_SYSERR;
735  }
736  res = (uint16_t *) PQgetvalue (result,
737  row,
738  fnum);
739  *udst = ntohs (*res);
740  return GNUNET_OK;
741 }
742 
743 
746  uint16_t *u16)
747 {
748  struct GNUNET_PQ_ResultSpec res =
749  { &extract_uint16,
750  NULL,
751  NULL,
752  (void *) u16, sizeof(*u16), (name), NULL };
753 
754  return res;
755 }
756 
757 
771 static int
773  PGresult *result,
774  int row,
775  const char *fname,
776  size_t *dst_size,
777  void *dst)
778 {
779  uint32_t *udst = dst;
780  const uint32_t *res;
781  int fnum;
782 
783  (void) cls;
784  fnum = PQfnumber (result,
785  fname);
786  if (fnum < 0)
787  {
788  GNUNET_break (0);
789  return GNUNET_SYSERR;
790  }
791  if (PQgetisnull (result,
792  row,
793  fnum))
794  {
795  GNUNET_break (0);
796  return GNUNET_SYSERR;
797  }
798  GNUNET_assert (NULL != dst);
799  if (sizeof(uint32_t) != *dst_size)
800  {
801  GNUNET_break (0);
802  return GNUNET_SYSERR;
803  }
804  if (sizeof(uint32_t) !=
805  PQgetlength (result,
806  row,
807  fnum))
808  {
809  GNUNET_break (0);
810  return GNUNET_SYSERR;
811  }
812  res = (uint32_t *) PQgetvalue (result,
813  row,
814  fnum);
815  *udst = ntohl (*res);
816  return GNUNET_OK;
817 }
818 
819 
822  uint32_t *u32)
823 {
824  struct GNUNET_PQ_ResultSpec res =
825  { &extract_uint32,
826  NULL,
827  NULL,
828  (void *) u32, sizeof(*u32), (name), NULL };
829 
830  return res;
831 }
832 
833 
847 static int
849  PGresult *result,
850  int row,
851  const char *fname,
852  size_t *dst_size,
853  void *dst)
854 {
855  uint64_t *udst = dst;
856  const uint64_t *res;
857  int fnum;
858 
859  (void) cls;
860  fnum = PQfnumber (result,
861  fname);
862  if (fnum < 0)
863  {
864  GNUNET_break (0);
865  return GNUNET_SYSERR;
866  }
867  if (PQgetisnull (result,
868  row,
869  fnum))
870  {
871  GNUNET_break (0);
872  return GNUNET_SYSERR;
873  }
874  GNUNET_assert (NULL != dst);
875  if (sizeof(uint64_t) != *dst_size)
876  {
877  GNUNET_break (0);
878  return GNUNET_SYSERR;
879  }
880  if (sizeof(uint64_t) !=
881  PQgetlength (result,
882  row,
883  fnum))
884  {
885  GNUNET_break (0);
886  return GNUNET_SYSERR;
887  }
888  res = (uint64_t *) PQgetvalue (result,
889  row,
890  fnum);
891  *udst = GNUNET_ntohll (*res);
892  return GNUNET_OK;
893 }
894 
895 
898  uint64_t *u64)
899 {
900  struct GNUNET_PQ_ResultSpec res = {
902  NULL,
903  NULL,
904  (void *) u64, sizeof(*u64), (name), NULL
905  };
906 
907  return res;
908 }
909 
910 
911 /* end of pq_result_helper.c */
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_rsa_public_key(const char *name, struct GNUNET_CRYPTO_RsaPublicKey **rsa)
RSA public key expected.
static void clean_string(void *cls, void *rd)
Function called to clean up memory allocated by a GNUNET_PQ_ResultConverter.
uint64_t rel_value_us
The actual value.
an RSA signature
Definition: crypto_rsa.c:63
void GNUNET_CRYPTO_rsa_signature_free(struct GNUNET_CRYPTO_RsaSignature *sig)
Free memory occupied by signature.
Definition: crypto_rsa.c:1061
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint16(const char *name, uint16_t *u16)
uint16_t expected.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_absolute_time_nbo(const char *name, struct GNUNET_TIME_AbsoluteNBO *at)
Absolute time expected.
const char * fname
Field name of the desired result.
Description of a DB result cell.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int extract_uint64(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
bool is_nullable
True if NULL is allowed for a value in the database.
static void clean_rsa_signature(void *cls, void *rd)
Function called to clean up memory allocated by a GNUNET_PQ_ResultConverter.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
uint64_t abs_value_us
The actual value.
The public information of an RSA key pair.
Definition: crypto_rsa.c:51
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_signature_decode(const void *buf, size_t buf_size)
Decode the signature from the data-format back to the "normal", internal format.
Definition: crypto_rsa.c:1124
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static int extract_fixed_blob(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint64(const char *name, uint64_t *u64)
uint64_t expected.
static int extract_varsize_blob(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_rsa_signature(const char *name, struct GNUNET_CRYPTO_RsaSignature **sig)
RSA signature expected.
void * cls
Closure for conv and cleaner.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint32(const char *name, uint32_t *u32)
uint32_t expected.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_fixed_size(const char *name, void *dst, size_t dst_size)
Fixed-size result expected.
static int extract_string(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
struct GNUNET_CRYPTO_RsaPublicKey * GNUNET_CRYPTO_rsa_public_key_decode(const char *buf, size_t len)
Decode the public key from the data-format back to the "normal", internal format. ...
Definition: crypto_rsa.c:443
static int extract_uint32(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
static int result
Global testing status.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
size_t dst_size
Allowed size for the data, 0 for variable-size (in this case, the type of dst is a void ** and we nee...
static int res
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_string(const char *name, char **dst)
0-terminated string expected.
bool * is_null
Points to a location where we should store "true" if the result found is NULL, and otherwise "false"...
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_allow_null(struct GNUNET_PQ_ResultSpec rs, bool *is_null)
Allow NULL value to be found in the database for the given value.
#define GNUNET_PQ_result_spec_auto_from_type(name, dst)
We expect a fixed-size result, with size determined by the type of * dst
static int extract_abs_time(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
helper functions for Postgres DB interactions
static int extract_rsa_signature(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
static void clean_rsa_public_key(void *cls, void *rd)
Function called to clean up memory allocated by a GNUNET_PQ_ResultConverter.
static void clean_varsize_blob(void *cls, void *rd)
Function called to clean up memory allocated by a GNUNET_PQ_ResultConverter.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
static int extract_rsa_public_key(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
const char * name
static int extract_uint16(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
void GNUNET_CRYPTO_rsa_public_key_free(struct GNUNET_CRYPTO_RsaPublicKey *key)
Free memory occupied by the public key.
Definition: crypto_rsa.c:305
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_variable_size(const char *name, void **dst, size_t *sptr)
Variable-size result expected.
Time for absolute times used by GNUnet, in microseconds.
void * dst
Destination for the data.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_relative_time(const char *name, struct GNUNET_TIME_Relative *rt)
Relative time expected.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_absolute_time(const char *name, struct GNUNET_TIME_Absolute *at)
Absolute time expected.
static int extract_rel_time(void *cls, PGresult *result, int row, const char *fname, size_t *dst_size, void *dst)
Extract data from a Postgres database result at row row.
#define GNUNET_malloc(size)
Wrapper around malloc.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...