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 enum GNUNET_GenericReturnValue
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  return GNUNET_NO;
106  /* if a field is null, continue but
107  * remember that we now return a different result */
108  len = PQgetlength (result,
109  row,
110  fnum);
111  res = PQgetvalue (result,
112  row,
113  fnum);
114  GNUNET_assert (NULL != res);
115  *dst_size = len;
116  idst = GNUNET_malloc (len);
117  *((void **) dst) = idst;
118  GNUNET_memcpy (idst,
119  res,
120  len);
121  return GNUNET_OK;
122 }
123 
124 
127  void **dst,
128  size_t *sptr)
129 {
130  struct GNUNET_PQ_ResultSpec res = {
131  .conv = &extract_varsize_blob,
132  .cleaner = &clean_varsize_blob,
133  .dst = (void *) (dst),
134  .fname = name,
135  .result_size = sptr
136  };
137 
138  return res;
139 }
140 
141 
155 static enum GNUNET_GenericReturnValue
156 extract_fixed_blob (void *cls,
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);
174  "Result does not have field %s\n",
175  fname);
176  return GNUNET_SYSERR;
177  }
178  if (PQgetisnull (result,
179  row,
180  fnum))
181  return GNUNET_NO;
182  /* if a field is null, continue but
183  * remember that we now return a different result */
184  len = PQgetlength (result,
185  row,
186  fnum);
187  if (*dst_size != len)
188  {
190  "Expected %u bytes for field `%s', got %u\n",
191  (unsigned int) *dst_size,
192  fname,
193  (unsigned int) len);
194  GNUNET_break (0);
195  return GNUNET_SYSERR;
196  }
197  res = PQgetvalue (result,
198  row,
199  fnum);
200  GNUNET_assert (NULL != res);
202  res,
203  len);
204  return GNUNET_OK;
205 }
206 
207 
210  void *dst,
211  size_t dst_size)
212 {
213  struct GNUNET_PQ_ResultSpec res = {
214  .conv = &extract_fixed_blob,
215  .dst = (dst),
216  .dst_size = dst_size,
217  .fname = name
218  };
219 
220  return res;
221 }
222 
223 
237 static enum GNUNET_GenericReturnValue
239  PGresult *result,
240  int row,
241  const char *fname,
242  size_t *dst_size,
243  void *dst)
244 {
245  struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
246  size_t len;
247  const char *res;
248  int fnum;
249 
250  (void) cls;
251  *pk = NULL;
252  fnum = PQfnumber (result,
253  fname);
254  if (fnum < 0)
255  {
256  GNUNET_break (0);
257  return GNUNET_SYSERR;
258  }
259  if (PQgetisnull (result,
260  row,
261  fnum))
262  return GNUNET_NO;
263 
264  /* if a field is null, continue but
265  * remember that we now return a different result */
266  len = PQgetlength (result,
267  row,
268  fnum);
269  res = PQgetvalue (result,
270  row,
271  fnum);
273  len);
274  if (NULL == *pk)
275  {
276  GNUNET_break (0);
277  return GNUNET_SYSERR;
278  }
279  return GNUNET_OK;
280 }
281 
282 
290 static void
292  void *rd)
293 {
294  struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
295 
296  (void) cls;
297  if (NULL != *pk)
298  {
300  *pk = NULL;
301  }
302 }
303 
304 
307  struct GNUNET_CRYPTO_RsaPublicKey **rsa)
308 {
309  struct GNUNET_PQ_ResultSpec res = {
310  .conv = &extract_rsa_public_key,
311  .cleaner = &clean_rsa_public_key,
312  .dst = (void *) rsa,
313  .fname = name
314  };
315 
316  return res;
317 }
318 
319 
333 static enum GNUNET_GenericReturnValue
335  PGresult *result,
336  int row,
337  const char *fname,
338  size_t *dst_size,
339  void *dst)
340 {
341  struct GNUNET_CRYPTO_RsaSignature **sig = dst;
342  size_t len;
343  const void *res;
344  int fnum;
345 
346  (void) cls;
347  *sig = NULL;
348  fnum = PQfnumber (result,
349  fname);
350  if (fnum < 0)
351  {
352  GNUNET_break (0);
353  return GNUNET_SYSERR;
354  }
355  if (PQgetisnull (result,
356  row,
357  fnum))
358  return GNUNET_NO;
359  /* if a field is null, continue but
360  * remember that we now return a different result */
361  len = PQgetlength (result,
362  row,
363  fnum);
364  res = PQgetvalue (result,
365  row,
366  fnum);
368  len);
369  if (NULL == *sig)
370  {
371  GNUNET_break (0);
372  return GNUNET_SYSERR;
373  }
374  return GNUNET_OK;
375 }
376 
377 
385 static void
387  void *rd)
388 {
389  struct GNUNET_CRYPTO_RsaSignature **sig = rd;
390 
391  (void) cls;
392  if (NULL != *sig)
393  {
395  *sig = NULL;
396  }
397 }
398 
399 
402  struct GNUNET_CRYPTO_RsaSignature **sig)
403 {
404  struct GNUNET_PQ_ResultSpec res = {
405  .conv = &extract_rsa_signature,
406  .cleaner = &clean_rsa_signature,
407  .dst = (void *) sig,
408  .fname = name
409  };
410 
411  return res;
412 }
413 
414 
428 static enum GNUNET_GenericReturnValue
429 extract_string (void *cls,
430  PGresult *result,
431  int row,
432  const char *fname,
433  size_t *dst_size,
434  void *dst)
435 {
436  char **str = dst;
437  size_t len;
438  const char *res;
439  int fnum;
440 
441  (void) cls;
442  *str = NULL;
443  fnum = PQfnumber (result,
444  fname);
445  if (fnum < 0)
446  {
447  GNUNET_break (0);
448  return GNUNET_SYSERR;
449  }
450  if (PQgetisnull (result,
451  row,
452  fnum))
453  return GNUNET_NO;
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 enum GNUNET_GenericReturnValue
523 extract_rel_time (void *cls,
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  return GNUNET_NO;
546  GNUNET_assert (NULL != dst);
547  if (sizeof(struct GNUNET_TIME_Relative) != *dst_size)
548  {
549  GNUNET_break (0);
550  return GNUNET_SYSERR;
551  }
552  if (sizeof(int64_t) !=
553  PQgetlength (result,
554  row,
555  fnum))
556  {
557  GNUNET_break (0);
558  return GNUNET_SYSERR;
559  }
560  res = (int64_t *) PQgetvalue (result,
561  row,
562  fnum);
563  if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
565  else
566  udst->rel_value_us = GNUNET_ntohll ((uint64_t) *res);
567  return GNUNET_OK;
568 }
569 
570 
573  struct GNUNET_TIME_Relative *rt)
574 {
575  struct GNUNET_PQ_ResultSpec res = {
577  NULL,
578  NULL,
579  (void *) rt,
580  sizeof(*rt),
581  name,
582  NULL
583  };
584 
585  return res;
586 }
587 
588 
602 static enum GNUNET_GenericReturnValue
603 extract_abs_time (void *cls,
604  PGresult *result,
605  int row,
606  const char *fname,
607  size_t *dst_size,
608  void *dst)
609 {
610  struct GNUNET_TIME_Absolute *udst = dst;
611  const int64_t *res;
612  int fnum;
613 
614  (void) cls;
615  fnum = PQfnumber (result,
616  fname);
617  if (fnum < 0)
618  {
619  GNUNET_break (0);
620  return GNUNET_SYSERR;
621  }
622  if (PQgetisnull (result,
623  row,
624  fnum))
625  return GNUNET_NO;
626  GNUNET_assert (NULL != dst);
627  if (sizeof(struct GNUNET_TIME_Absolute) != *dst_size)
628  {
629  GNUNET_break (0);
630  return GNUNET_SYSERR;
631  }
632  if (sizeof(int64_t) !=
633  PQgetlength (result,
634  row,
635  fnum))
636  {
637  GNUNET_break (0);
638  return GNUNET_SYSERR;
639  }
640  res = (int64_t *) PQgetvalue (result,
641  row,
642  fnum);
643  if (INT64_MAX == GNUNET_ntohll ((uint64_t) *res))
645  else
646  udst->abs_value_us = GNUNET_ntohll ((uint64_t) *res);
647  return GNUNET_OK;
648 }
649 
650 
653  struct GNUNET_TIME_Absolute *at)
654 {
655  struct GNUNET_PQ_ResultSpec res =
656  { &extract_abs_time,
657  NULL,
658  NULL,
659  (void *) at, sizeof(*at), (name), NULL };
660 
661  return res;
662 }
663 
664 
667  struct GNUNET_TIME_AbsoluteNBO *at)
668 {
669  struct GNUNET_PQ_ResultSpec res =
670  GNUNET_PQ_result_spec_auto_from_type (name, &at->abs_value_us__);
671 
672  return res;
673 }
674 
675 
689 static enum GNUNET_GenericReturnValue
690 extract_uint16 (void *cls,
691  PGresult *result,
692  int row,
693  const char *fname,
694  size_t *dst_size,
695  void *dst)
696 {
697  uint16_t *udst = dst;
698  const uint16_t *res;
699  int fnum;
700 
701  (void) cls;
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_NO;
713  GNUNET_assert (NULL != dst);
714  if (sizeof(uint16_t) != *dst_size)
715  {
716  GNUNET_break (0);
717  return GNUNET_SYSERR;
718  }
719  if (sizeof(uint16_t) !=
720  PQgetlength (result,
721  row,
722  fnum))
723  {
724  GNUNET_break (0);
725  return GNUNET_SYSERR;
726  }
727  res = (uint16_t *) PQgetvalue (result,
728  row,
729  fnum);
730  *udst = ntohs (*res);
731  return GNUNET_OK;
732 }
733 
734 
737  uint16_t *u16)
738 {
739  struct GNUNET_PQ_ResultSpec res =
740  { &extract_uint16,
741  NULL,
742  NULL,
743  (void *) u16, sizeof(*u16), (name), NULL };
744 
745  return res;
746 }
747 
748 
762 static enum GNUNET_GenericReturnValue
763 extract_uint32 (void *cls,
764  PGresult *result,
765  int row,
766  const char *fname,
767  size_t *dst_size,
768  void *dst)
769 {
770  uint32_t *udst = dst;
771  const uint32_t *res;
772  int fnum;
773 
774  (void) cls;
775  fnum = PQfnumber (result,
776  fname);
777  if (fnum < 0)
778  {
779  GNUNET_break (0);
780  return GNUNET_SYSERR;
781  }
782  if (PQgetisnull (result,
783  row,
784  fnum))
785  return GNUNET_NO;
786  GNUNET_assert (NULL != dst);
787  if (sizeof(uint32_t) != *dst_size)
788  {
789  GNUNET_break (0);
790  return GNUNET_SYSERR;
791  }
792  if (sizeof(uint32_t) !=
793  PQgetlength (result,
794  row,
795  fnum))
796  {
797  GNUNET_break (0);
798  return GNUNET_SYSERR;
799  }
800  res = (uint32_t *) PQgetvalue (result,
801  row,
802  fnum);
803  *udst = ntohl (*res);
804  return GNUNET_OK;
805 }
806 
807 
810  uint32_t *u32)
811 {
812  struct GNUNET_PQ_ResultSpec res = {
814  NULL,
815  NULL,
816  (void *) u32,
817  sizeof(*u32),
818  (name),
819  NULL
820  };
821 
822  return res;
823 }
824 
825 
839 static enum GNUNET_GenericReturnValue
840 extract_uint64 (void *cls,
841  PGresult *result,
842  int row,
843  const char *fname,
844  size_t *dst_size,
845  void *dst)
846 {
847  uint64_t *udst = dst;
848  const uint64_t *res;
849  int fnum;
850 
851  (void) cls;
852  fnum = PQfnumber (result,
853  fname);
854  if (fnum < 0)
855  {
857  "Field %s missing in result\n",
858  fname);
859  GNUNET_break (0);
860  return GNUNET_SYSERR;
861  }
862  if (PQgetisnull (result,
863  row,
864  fnum))
865  return GNUNET_NO;
866 
867  GNUNET_assert (NULL != dst);
868  if (sizeof(uint64_t) != *dst_size)
869  {
870  GNUNET_break (0);
871  return GNUNET_SYSERR;
872  }
873  if (sizeof(uint64_t) !=
874  PQgetlength (result,
875  row,
876  fnum))
877  {
878  GNUNET_break (0);
879  return GNUNET_SYSERR;
880  }
881  res = (uint64_t *) PQgetvalue (result,
882  row,
883  fnum);
884  *udst = GNUNET_ntohll (*res);
885  return GNUNET_OK;
886 }
887 
888 
891  uint64_t *u64)
892 {
893  struct GNUNET_PQ_ResultSpec res = {
895  NULL,
896  NULL,
897  (void *) u64,
898  sizeof(*u64),
899  (name),
900  NULL
901  };
902 
903  return res;
904 }
905 
906 
907 /* end of pq_result_helper.c */
static int res
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static int result
Global testing status.
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:92
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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:1008
void GNUNET_CRYPTO_rsa_signature_free(struct GNUNET_CRYPTO_RsaSignature *sig)
Free memory occupied by signature.
Definition: crypto_rsa.c:960
void GNUNET_CRYPTO_rsa_public_key_free(struct GNUNET_CRYPTO_RsaPublicKey *key)
Free memory occupied by the public key.
Definition: crypto_rsa.c:267
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:398
helper functions for Postgres DB interactions
#define GNUNET_PQ_result_spec_auto_from_type(name, dst)
We expect a fixed-size result, with size determined by the type of * dst
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
const char * name
static enum GNUNET_GenericReturnValue 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.
static enum GNUNET_GenericReturnValue 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.
static enum GNUNET_GenericReturnValue 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_uint32(const char *name, uint32_t *u32)
uint32_t expected.
static enum GNUNET_GenericReturnValue 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.
static enum GNUNET_GenericReturnValue 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.
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.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_fixed_size(const char *name, void *dst, size_t dst_size)
Fixed-size result expected.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_absolute_time_nbo(const char *name, struct GNUNET_TIME_AbsoluteNBO *at)
Absolute time expected.
static enum GNUNET_GenericReturnValue 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.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint64(const char *name, uint64_t *u64)
uint64_t expected.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_string(const char *name, char **dst)
0-terminated string expected.
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.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_absolute_time(const char *name, struct GNUNET_TIME_Absolute *at)
Absolute time expected.
static void clean_string(void *cls, void *rd)
Function called to clean up memory allocated by a GNUNET_PQ_ResultConverter.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_uint16(const char *name, uint16_t *u16)
uint16_t expected.
static enum GNUNET_GenericReturnValue 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.
static enum GNUNET_GenericReturnValue 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.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_relative_time(const char *name, struct GNUNET_TIME_Relative *rt)
Relative time expected.
static enum GNUNET_GenericReturnValue 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_PQ_ResultSpec GNUNET_PQ_result_spec_variable_size(const char *name, void **dst, size_t *sptr)
Variable-size result expected.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_rsa_public_key(const char *name, struct GNUNET_CRYPTO_RsaPublicKey **rsa)
RSA public key expected.
static enum GNUNET_GenericReturnValue 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.
struct GNUNET_PQ_ResultSpec GNUNET_PQ_result_spec_rsa_signature(const char *name, struct GNUNET_CRYPTO_RsaSignature **sig)
RSA signature expected.
static void clean_rsa_signature(void *cls, void *rd)
Function called to clean up memory allocated by a GNUNET_PQ_ResultConverter.
The public information of an RSA key pair.
Definition: crypto_rsa.c:52
an RSA signature
Definition: crypto_rsa.c:64
Description of a DB result cell.
const char * fname
Field name of the desired result.
bool * is_null
Points to a location where we should store "true" if the result found is NULL, and otherwise "false".
void * dst
Destination for the data.
bool is_nullable
True if NULL is allowed for a value in the database.
void * cls
Closure for conv and cleaner.
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...
Time for absolute time used by GNUnet, in microseconds and in network byte order.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.