aboutsummaryrefslogtreecommitdiff
path: root/src/lib/pq/pq_query_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pq/pq_query_helper.c')
-rw-r--r--src/lib/pq/pq_query_helper.c1585
1 files changed, 1585 insertions, 0 deletions
diff --git a/src/lib/pq/pq_query_helper.c b/src/lib/pq/pq_query_helper.c
new file mode 100644
index 000000000..913ce9235
--- /dev/null
+++ b/src/lib/pq/pq_query_helper.c
@@ -0,0 +1,1585 @@
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 */
20/**
21 * @file pq/pq_query_helper.c
22 * @brief functions to initialize parameter arrays
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_common.h"
27#include "gnunet_pq_lib.h"
28#include "gnunet_time_lib.h"
29#include "pq.h"
30
31
32/**
33 * Function called to convert input argument into SQL parameters.
34 *
35 * @param cls closure
36 * @param data pointer to input argument
37 * @param data_len number of bytes in @a data (if applicable)
38 * @param[out] param_values SQL data to set
39 * @param[out] param_lengths SQL length data to set
40 * @param[out] param_formats SQL format data to set
41 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
42 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
43 * @param scratch_length number of entries left in @a scratch
44 * @return -1 on error, number of offsets used in @a scratch otherwise
45 */
46static int
47qconv_null (void *cls,
48 const void *data,
49 size_t data_len,
50 void *param_values[],
51 int param_lengths[],
52 int param_formats[],
53 unsigned int param_length,
54 void *scratch[],
55 unsigned int scratch_length)
56{
57 (void) scratch;
58 (void) scratch_length;
59 (void) data;
60 (void) data_len;
61 GNUNET_break (NULL == cls);
62 if (1 != param_length)
63 return -1;
64 param_values[0] = NULL;
65 param_lengths[0] = 0;
66 param_formats[0] = 1;
67 return 0;
68}
69
70
71struct GNUNET_PQ_QueryParam
72GNUNET_PQ_query_param_null (void)
73{
74 struct GNUNET_PQ_QueryParam res = {
75 .conv = &qconv_null,
76 .num_params = 1
77 };
78
79 return res;
80}
81
82
83/**
84 * Function called to convert input argument into SQL parameters.
85 *
86 * @param cls closure
87 * @param data pointer to input argument
88 * @param data_len number of bytes in @a data (if applicable)
89 * @param[out] param_values SQL data to set
90 * @param[out] param_lengths SQL length data to set
91 * @param[out] param_formats SQL format data to set
92 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
93 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
94 * @param scratch_length number of entries left in @a scratch
95 * @return -1 on error, number of offsets used in @a scratch otherwise
96 */
97static int
98qconv_fixed (void *cls,
99 const void *data,
100 size_t data_len,
101 void *param_values[],
102 int param_lengths[],
103 int param_formats[],
104 unsigned int param_length,
105 void *scratch[],
106 unsigned int scratch_length)
107{
108 (void) scratch;
109 (void) scratch_length;
110 GNUNET_break (NULL == cls);
111 if (1 != param_length)
112 return -1;
113 param_values[0] = (void *) data;
114 param_lengths[0] = data_len;
115 param_formats[0] = 1;
116 return 0;
117}
118
119
120struct GNUNET_PQ_QueryParam
121GNUNET_PQ_query_param_fixed_size (const void *ptr,
122 size_t ptr_size)
123{
124 struct GNUNET_PQ_QueryParam res = {
125 .conv = &qconv_fixed,
126 .conv_cls = NULL,
127 .data = ptr,
128 .size = ptr_size,
129 .num_params = 1
130 };
131
132 return res;
133}
134
135
136struct GNUNET_PQ_QueryParam
137GNUNET_PQ_query_param_string (const char *ptr)
138{
139 return GNUNET_PQ_query_param_fixed_size (ptr,
140 strlen (ptr));
141}
142
143
144struct GNUNET_PQ_QueryParam
145GNUNET_PQ_query_param_bool (bool b)
146{
147 static uint8_t bt = 1;
148 static uint8_t bf = 0;
149
150 return GNUNET_PQ_query_param_fixed_size (b ? &bt : &bf,
151 sizeof (uint8_t));
152}
153
154
155/**
156 * Function called to convert input argument into SQL parameters.
157 *
158 * @param cls closure
159 * @param data pointer to input argument
160 * @param data_len number of bytes in @a data (if applicable)
161 * @param[out] param_values SQL data to set
162 * @param[out] param_lengths SQL length data to set
163 * @param[out] param_formats SQL format data to set
164 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
165 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
166 * @param scratch_length number of entries left in @a scratch
167 * @return -1 on error, number of offsets used in @a scratch otherwise
168 */
169static int
170qconv_uint16 (void *cls,
171 const void *data,
172 size_t data_len,
173 void *param_values[],
174 int param_lengths[],
175 int param_formats[],
176 unsigned int param_length,
177 void *scratch[],
178 unsigned int scratch_length)
179{
180 const uint16_t *u_hbo = data;
181 uint16_t *u_nbo;
182
183 (void) scratch;
184 (void) scratch_length;
185 GNUNET_break (NULL == cls);
186 if (1 != param_length)
187 return -1;
188 u_nbo = GNUNET_new (uint16_t);
189 scratch[0] = u_nbo;
190 *u_nbo = htons (*u_hbo);
191 param_values[0] = (void *) u_nbo;
192 param_lengths[0] = sizeof(uint16_t);
193 param_formats[0] = 1;
194 return 1;
195}
196
197
198struct GNUNET_PQ_QueryParam
199GNUNET_PQ_query_param_uint16 (const uint16_t *x)
200{
201 struct GNUNET_PQ_QueryParam res = {
202 .conv = &qconv_uint16,
203 .data = x,
204 .size = sizeof(*x),
205 .num_params = 1
206 };
207
208 return res;
209}
210
211
212/**
213 * Function called to convert input argument into SQL parameters.
214 *
215 * @param cls closure
216 * @param data pointer to input argument
217 * @param data_len number of bytes in @a data (if applicable)
218 * @param[out] param_values SQL data to set
219 * @param[out] param_lengths SQL length data to set
220 * @param[out] param_formats SQL format data to set
221 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
222 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
223 * @param scratch_length number of entries left in @a scratch
224 * @return -1 on error, number of offsets used in @a scratch otherwise
225 */
226static int
227qconv_uint32 (void *cls,
228 const void *data,
229 size_t data_len,
230 void *param_values[],
231 int param_lengths[],
232 int param_formats[],
233 unsigned int param_length,
234 void *scratch[],
235 unsigned int scratch_length)
236{
237 const uint32_t *u_hbo = data;
238 uint32_t *u_nbo;
239
240 (void) scratch;
241 (void) scratch_length;
242 GNUNET_break (NULL == cls);
243 if (1 != param_length)
244 return -1;
245 u_nbo = GNUNET_new (uint32_t);
246 scratch[0] = u_nbo;
247 *u_nbo = htonl (*u_hbo);
248 param_values[0] = (void *) u_nbo;
249 param_lengths[0] = sizeof(uint32_t);
250 param_formats[0] = 1;
251 return 1;
252}
253
254
255struct GNUNET_PQ_QueryParam
256GNUNET_PQ_query_param_uint32 (const uint32_t *x)
257{
258 struct GNUNET_PQ_QueryParam res = {
259 .conv = &qconv_uint32,
260 .data = x,
261 .size = sizeof(*x),
262 .num_params = 1
263 };
264
265 return res;
266}
267
268
269/**
270 * Function called to convert input argument into SQL parameters.
271 *
272 * @param cls closure
273 * @param data pointer to input argument
274 * @param data_len number of bytes in @a data (if applicable)
275 * @param[out] param_values SQL data to set
276 * @param[out] param_lengths SQL length data to set
277 * @param[out] param_formats SQL format data to set
278 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
279 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
280 * @param scratch_length number of entries left in @a scratch
281 * @return -1 on error, number of offsets used in @a scratch otherwise
282 */
283static int
284qconv_uint64 (void *cls,
285 const void *data,
286 size_t data_len,
287 void *param_values[],
288 int param_lengths[],
289 int param_formats[],
290 unsigned int param_length,
291 void *scratch[],
292 unsigned int scratch_length)
293{
294 const uint64_t *u_hbo = data;
295 uint64_t *u_nbo;
296
297 (void) scratch;
298 (void) scratch_length;
299 GNUNET_break (NULL == cls);
300 if (1 != param_length)
301 return -1;
302 u_nbo = GNUNET_new (uint64_t);
303 scratch[0] = u_nbo;
304 *u_nbo = GNUNET_htonll (*u_hbo);
305 param_values[0] = (void *) u_nbo;
306 param_lengths[0] = sizeof(uint64_t);
307 param_formats[0] = 1;
308 return 1;
309}
310
311
312struct GNUNET_PQ_QueryParam
313GNUNET_PQ_query_param_uint64 (const uint64_t *x)
314{
315 struct GNUNET_PQ_QueryParam res = {
316 .conv = &qconv_uint64,
317 .data = x,
318 .size = sizeof(*x),
319 .num_params = 1
320 };
321
322 return res;
323}
324
325
326/**
327 * Function called to convert input argument into SQL parameters.
328 *
329 * @param cls closure
330 * @param data pointer to input argument
331 * @param data_len number of bytes in @a data (if applicable)
332 * @param[out] param_values SQL data to set
333 * @param[out] param_lengths SQL length data to set
334 * @param[out] param_formats SQL format data to set
335 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
336 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
337 * @param scratch_length number of entries left in @a scratch
338 * @return -1 on error, number of offsets used in @a scratch otherwise
339 */
340static int
341qconv_int64 (void *cls,
342 const void *data,
343 size_t data_len,
344 void *param_values[],
345 int param_lengths[],
346 int param_formats[],
347 unsigned int param_length,
348 void *scratch[],
349 unsigned int scratch_length)
350{
351 const int64_t *u_hbo = data;
352 int64_t *u_nbo;
353
354 (void) scratch;
355 (void) scratch_length;
356 GNUNET_break (NULL == cls);
357 if (1 != param_length)
358 return -1;
359 u_nbo = GNUNET_new (int64_t);
360 scratch[0] = u_nbo;
361 *u_nbo = GNUNET_htonll (*u_hbo);
362 param_values[0] = (void *) u_nbo;
363 param_lengths[0] = sizeof(int64_t);
364 param_formats[0] = 1;
365 return 1;
366}
367
368
369struct GNUNET_PQ_QueryParam
370GNUNET_PQ_query_param_int64 (const int64_t *x)
371{
372 struct GNUNET_PQ_QueryParam res = {
373 .conv = &qconv_int64,
374 .data = x,
375 .size = sizeof(*x),
376 .num_params = 1
377 };
378
379 return res;
380}
381
382
383/**
384 * Function called to convert input argument into SQL parameters.
385 *
386 * @param cls closure
387 * @param data pointer to input argument
388 * @param data_len number of bytes in @a data (if applicable)
389 * @param[out] param_values SQL data to set
390 * @param[out] param_lengths SQL length data to set
391 * @param[out] param_formats SQL format data to set
392 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
393 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
394 * @param scratch_length number of entries left in @a scratch
395 * @return -1 on error, number of offsets used in @a scratch otherwise
396 */
397static int
398qconv_rsa_public_key (void *cls,
399 const void *data,
400 size_t data_len,
401 void *param_values[],
402 int param_lengths[],
403 int param_formats[],
404 unsigned int param_length,
405 void *scratch[],
406 unsigned int scratch_length)
407{
408 const struct GNUNET_CRYPTO_RsaPublicKey *rsa = data;
409 void *buf;
410 size_t buf_size;
411
412 GNUNET_break (NULL == cls);
413 if (1 != param_length)
414 return -1;
415 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa,
416 &buf);
417 scratch[0] = buf;
418 param_values[0] = (void *) buf;
419 param_lengths[0] = buf_size;
420 param_formats[0] = 1;
421 return 1;
422}
423
424
425struct GNUNET_PQ_QueryParam
426GNUNET_PQ_query_param_rsa_public_key (
427 const struct GNUNET_CRYPTO_RsaPublicKey *x)
428{
429 struct GNUNET_PQ_QueryParam res = {
430 .conv = &qconv_rsa_public_key,
431 .data = x,
432 .num_params = 1
433 };
434
435 return res;
436}
437
438
439/**
440 * Function called to convert input argument into SQL parameters.
441 *
442 * @param cls closure
443 * @param data pointer to input argument
444 * @param data_len number of bytes in @a data (if applicable)
445 * @param[out] param_values SQL data to set
446 * @param[out] param_lengths SQL length data to set
447 * @param[out] param_formats SQL format data to set
448 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
449 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
450 * @param scratch_length number of entries left in @a scratch
451 * @return -1 on error, number of offsets used in @a scratch otherwise
452 */
453static int
454qconv_rsa_signature (void *cls,
455 const void *data,
456 size_t data_len,
457 void *param_values[],
458 int param_lengths[],
459 int param_formats[],
460 unsigned int param_length,
461 void *scratch[],
462 unsigned int scratch_length)
463{
464 const struct GNUNET_CRYPTO_RsaSignature *sig = data;
465 void *buf;
466 size_t buf_size;
467
468 GNUNET_break (NULL == cls);
469 if (1 != param_length)
470 return -1;
471 buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig,
472 &buf);
473 scratch[0] = buf;
474 param_values[0] = (void *) buf;
475 param_lengths[0] = buf_size;
476 param_formats[0] = 1;
477 return 1;
478}
479
480
481struct GNUNET_PQ_QueryParam
482GNUNET_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x)
483{
484 struct GNUNET_PQ_QueryParam res = {
485 .conv = &qconv_rsa_signature,
486 .data = x,
487 .num_params = 1
488 };
489
490 return res;
491}
492
493
494/**
495 * Function called to convert input argument into SQL parameters.
496 *
497 * @param cls closure
498 * @param data pointer to input argument
499 * @param data_len number of bytes in @a data (if applicable)
500 * @param[out] param_values SQL data to set
501 * @param[out] param_lengths SQL length data to set
502 * @param[out] param_formats SQL format data to set
503 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
504 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
505 * @param scratch_length number of entries left in @a scratch
506 * @return -1 on error, number of offsets used in @a scratch otherwise
507 */
508static int
509qconv_rel_time (void *cls,
510 const void *data,
511 size_t data_len,
512 void *param_values[],
513 int param_lengths[],
514 int param_formats[],
515 unsigned int param_length,
516 void *scratch[],
517 unsigned int scratch_length)
518{
519 const struct GNUNET_TIME_Relative *u = data;
520 struct GNUNET_TIME_Relative rel;
521 uint64_t *u_nbo;
522
523 GNUNET_break (NULL == cls);
524 if (1 != param_length)
525 return -1;
526 rel = *u;
527 if (rel.rel_value_us > INT64_MAX)
528 rel.rel_value_us = INT64_MAX;
529 u_nbo = GNUNET_new (uint64_t);
530 scratch[0] = u_nbo;
531 *u_nbo = GNUNET_htonll (rel.rel_value_us);
532 param_values[0] = (void *) u_nbo;
533 param_lengths[0] = sizeof(uint64_t);
534 param_formats[0] = 1;
535 return 1;
536}
537
538
539struct GNUNET_PQ_QueryParam
540GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x)
541{
542 struct GNUNET_PQ_QueryParam res = {
543 .conv = &qconv_rel_time,
544 .data = x,
545 .size = sizeof(*x),
546 .num_params = 1
547 };
548
549 return res;
550}
551
552
553/**
554 * Function called to convert input argument into SQL parameters.
555 *
556 * @param cls closure
557 * @param data pointer to input argument
558 * @param data_len number of bytes in @a data (if applicable)
559 * @param[out] param_values SQL data to set
560 * @param[out] param_lengths SQL length data to set
561 * @param[out] param_formats SQL format data to set
562 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
563 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
564 * @param scratch_length number of entries left in @a scratch
565 * @return -1 on error, number of offsets used in @a scratch otherwise
566 */
567static int
568qconv_abs_time (void *cls,
569 const void *data,
570 size_t data_len,
571 void *param_values[],
572 int param_lengths[],
573 int param_formats[],
574 unsigned int param_length,
575 void *scratch[],
576 unsigned int scratch_length)
577{
578 const struct GNUNET_TIME_Absolute *u = data;
579 struct GNUNET_TIME_Absolute abs;
580 uint64_t *u_nbo;
581
582 GNUNET_break (NULL == cls);
583 if (1 != param_length)
584 return -1;
585 abs = *u;
586 if (abs.abs_value_us > INT64_MAX)
587 abs.abs_value_us = INT64_MAX;
588 u_nbo = GNUNET_new (uint64_t);
589 scratch[0] = u_nbo;
590 *u_nbo = GNUNET_htonll (abs.abs_value_us);
591 param_values[0] = (void *) u_nbo;
592 param_lengths[0] = sizeof(uint64_t);
593 param_formats[0] = 1;
594 return 1;
595}
596
597
598struct GNUNET_PQ_QueryParam
599GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
600{
601 struct GNUNET_PQ_QueryParam res = {
602 .conv = &qconv_abs_time,
603 .data = x,
604 .size = sizeof(*x),
605 .num_params = 1
606 };
607
608 return res;
609}
610
611
612struct GNUNET_PQ_QueryParam
613GNUNET_PQ_query_param_absolute_time_nbo (
614 const struct GNUNET_TIME_AbsoluteNBO *x)
615{
616 return GNUNET_PQ_query_param_auto_from_type (&x->abs_value_us__);
617}
618
619
620struct GNUNET_PQ_QueryParam
621GNUNET_PQ_query_param_timestamp (const struct GNUNET_TIME_Timestamp *x)
622{
623 return GNUNET_PQ_query_param_absolute_time (&x->abs_time);
624}
625
626
627struct GNUNET_PQ_QueryParam
628GNUNET_PQ_query_param_timestamp_nbo (
629 const struct GNUNET_TIME_TimestampNBO *x)
630{
631 return GNUNET_PQ_query_param_absolute_time_nbo (&x->abs_time_nbo);
632}
633
634
635/**
636 * Closure for the array type handlers.
637 *
638 * May contain sizes information for the data, given (and handled) by the
639 * caller.
640 */
641struct qconv_array_cls
642{
643 /**
644 * If not null, contains the array of sizes (the size of the array is the
645 * .size field in the ambient GNUNET_PQ_QueryParam struct). We do not free
646 * this memory.
647 *
648 * If not null, this value has precedence over @a sizes, which MUST be NULL */
649 const size_t *sizes;
650
651 /**
652 * If @a size and @a c_sizes are NULL, this field defines the same size
653 * for each element in the array.
654 */
655 size_t same_size;
656
657 /**
658 * If true, the array parameter to the data pointer to the qconv_array is a
659 * continuous byte array of data, either with @a same_size each or sizes
660 * provided bytes by @a sizes;
661 */
662 bool continuous;
663
664 /**
665 * Type of the array elements
666 */
667 enum array_types typ;
668
669 /**
670 * Oid of the array elements
671 */
672 Oid oid;
673};
674
675/**
676 * Callback to cleanup a qconv_array_cls to be used during
677 * GNUNET_PQ_cleanup_query_params_closures
678 */
679static void
680qconv_array_cls_cleanup (void *cls)
681{
682 GNUNET_free (cls);
683}
684
685
686/**
687 * Function called to convert input argument into SQL parameters for arrays
688 *
689 * Note: the format for the encoding of arrays for libpq is not very well
690 * documented. We peeked into various sources (postgresql and libpqtypes) for
691 * guidance.
692 *
693 * @param cls Closure of type struct qconv_array_cls*
694 * @param data Pointer to first element in the array
695 * @param data_len Number of _elements_ in array @a data (if applicable)
696 * @param[out] param_values SQL data to set
697 * @param[out] param_lengths SQL length data to set
698 * @param[out] param_formats SQL format data to set
699 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
700 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
701 * @param scratch_length number of entries left in @a scratch
702 * @return -1 on error, number of offsets used in @a scratch otherwise
703 */
704static int
705qconv_array (
706 void *cls,
707 const void *data,
708 size_t data_len,
709 void *param_values[],
710 int param_lengths[],
711 int param_formats[],
712 unsigned int param_length,
713 void *scratch[],
714 unsigned int scratch_length)
715{
716 struct qconv_array_cls *meta = cls;
717 size_t num = data_len;
718 size_t total_size;
719 const size_t *sizes;
720 bool same_sized;
721 size_t *string_lengths = NULL;
722 void *elements = NULL;
723 bool noerror = true;
724
725 (void) (param_length);
726 (void) (scratch_length);
727
728 GNUNET_assert (NULL != meta);
729 GNUNET_assert (num < INT_MAX);
730
731 sizes = meta->sizes;
732 same_sized = (0 != meta->same_size);
733
734#define RETURN_UNLESS(cond) \
735 do { \
736 if (! (cond)) \
737 { \
738 GNUNET_break ((cond)); \
739 noerror = false; \
740 goto DONE; \
741 } \
742 } while (0)
743
744 /* Calculate sizes and check bounds */
745 {
746 /* num * length-field */
747 size_t x = sizeof(uint32_t);
748 size_t y = x * num;
749 RETURN_UNLESS ((0 == num) || (y / num == x));
750
751 /* size of header */
752 total_size = x = sizeof(struct pq_array_header);
753 total_size += y;
754 RETURN_UNLESS (total_size >= x);
755
756 /* sizes of elements */
757 if (same_sized)
758 {
759 x = num * meta->same_size;
760 RETURN_UNLESS ((0 == num) || (x / num == meta->same_size));
761
762 y = total_size;
763 total_size += x;
764 RETURN_UNLESS (total_size >= y);
765 }
766 else /* sizes are different per element */
767 {
768 /* for an array of strings we need to get their length's first */
769 if (array_of_string == meta->typ)
770 {
771 string_lengths = GNUNET_new_array (num, size_t);
772
773 if (meta->continuous)
774 {
775 const char *ptr = data;
776 for (unsigned int i = 0; i < num; i++)
777 {
778 size_t len = strlen (ptr);
779 string_lengths[i] = len;
780 ptr += len + 1;
781 }
782 }
783 else
784 {
785 const char **str = (const char **) data;
786 for (unsigned int i = 0; i < num; i++)
787 string_lengths[i] = strlen (str[i]);
788 }
789
790 sizes = string_lengths;
791 }
792
793 for (unsigned int i = 0; i < num; i++)
794 {
795 x = total_size;
796 total_size += sizes[i];
797 RETURN_UNLESS (total_size >= x);
798 }
799 }
800
801 RETURN_UNLESS (total_size < INT_MAX);
802
803 elements = GNUNET_malloc (total_size);
804 }
805
806 /* Write data */
807 {
808 char *in = (char *) data;
809 char *out = elements;
810 size_t nullbyte = (array_of_string == meta->typ) ? 1 : 0;
811 struct pq_array_header h = {
812 .ndim = htonl (1), /* We only support one-dimensional arrays */
813 .has_null = htonl (0), /* We do not support NULL entries in arrays */
814 .lbound = htonl (1), /* Default start index value */
815 .dim = htonl (num),
816 .oid = htonl (meta->oid),
817 };
818
819 /* Write header */
820 GNUNET_memcpy (out, &h, sizeof(h));
821 out += sizeof(h);
822
823
824 /* Write elements */
825 for (unsigned int i = 0; i < num; i++)
826 {
827 size_t sz = same_sized ? meta->same_size : sizes[i];
828 size_t hsz = htonl (sz);
829
830 GNUNET_memcpy (out,
831 &hsz,
832 sizeof(hsz));
833 out += sizeof(uint32_t);
834
835 switch (meta->typ)
836 {
837 case array_of_bool:
838 {
839 GNUNET_assert (sizeof(bool) == sz);
840 *(bool *) out = (*(bool *) in);
841 in += sz;
842 break;
843 }
844 case array_of_uint16:
845 {
846 GNUNET_assert (sizeof(uint16_t) == sz);
847 *(uint16_t *) out = htons (*(uint16_t *) in);
848 in += sz;
849 break;
850 }
851 case array_of_uint32:
852 {
853 uint32_t v;
854 GNUNET_assert (sizeof(uint32_t) == sz);
855
856 v = htonl (*(uint32_t *) in);
857 GNUNET_memcpy (out,
858 &v,
859 sizeof(v));
860 in += sz;
861 break;
862 }
863 case array_of_uint64:
864 {
865 uint64_t tmp;
866 GNUNET_assert (sizeof(uint64_t) == sz);
867
868 tmp = GNUNET_htonll (*(uint64_t *) in);
869 GNUNET_memcpy (out,
870 &tmp,
871 sizeof(tmp));
872 in += sz;
873 break;
874 }
875 case array_of_byte:
876 case array_of_string:
877 {
878 const void *ptr;
879
880 if (meta->continuous)
881 {
882 ptr = in;
883 in += sz + nullbyte;
884 }
885 else
886 ptr = ((const void **) data)[i];
887
888 GNUNET_memcpy (out,
889 ptr,
890 sz);
891 break;
892 }
893 case array_of_abs_time:
894 case array_of_rel_time:
895 case array_of_timestamp:
896 {
897 uint64_t val;
898
899 switch (meta->typ)
900 {
901 case array_of_abs_time:
902 {
903 const struct GNUNET_TIME_Absolute *abs =
904 (const struct GNUNET_TIME_Absolute *) in;
905
906 GNUNET_assert (sizeof(struct GNUNET_TIME_Absolute) == sz);
907
908 if (! meta->continuous)
909 abs = ((const struct GNUNET_TIME_Absolute **) data)[i];
910
911 val = abs->abs_value_us;
912 break;
913 }
914 case array_of_rel_time:
915 {
916 const struct GNUNET_TIME_Relative *rel =
917 (const struct GNUNET_TIME_Relative *) in;
918
919 GNUNET_assert (sizeof(struct GNUNET_TIME_Relative) == sz);
920
921 if (! meta->continuous)
922 rel = ((const struct GNUNET_TIME_Relative **) data)[i];
923
924 val = rel->rel_value_us;
925 break;
926 }
927 case array_of_timestamp:
928 {
929 const struct GNUNET_TIME_Timestamp *ts =
930 (const struct GNUNET_TIME_Timestamp *) in;
931
932 GNUNET_assert (sizeof(struct GNUNET_TIME_Timestamp) == sz);
933
934 if (! meta->continuous)
935 ts = ((const struct GNUNET_TIME_Timestamp **) data)[i];
936
937 val = ts->abs_time.abs_value_us;
938 break;
939 }
940 default:
941 {
942 GNUNET_assert (0);
943 }
944 }
945
946 if (val > INT64_MAX)
947 val = INT64_MAX;
948
949 val = GNUNET_htonll (val);
950 GNUNET_memcpy (out,
951 &val,
952 sizeof(val));
953
954 if (meta->continuous)
955 in += sz;
956
957 break;
958 }
959 default:
960 {
961 GNUNET_assert (0);
962 break;
963 }
964 }
965 out += sz;
966 }
967 }
968
969 param_values[0] = elements;
970 param_lengths[0] = total_size;
971 param_formats[0] = 1;
972 scratch[0] = elements;
973
974DONE:
975 GNUNET_free (string_lengths);
976
977 if (noerror)
978 return 1;
979
980 return -1;
981}
982
983
984/**
985 * Function to genreate a typ specific query parameter and corresponding closure
986 *
987 * @param num Number of elements in @a elements
988 * @param continuous If true, @a elements is an continuous array of data
989 * @param elements Array of @a num elements, either continuous or pointers
990 * @param sizes Array of @a num sizes, one per element, may be NULL
991 * @param same_size If not 0, all elements in @a elements have this size
992 * @param typ Supported internal type of each element in @a elements
993 * @param oid Oid of the type to be used in Postgres
994 * @return Query parameter
995 */
996static struct GNUNET_PQ_QueryParam
997query_param_array_generic (
998 unsigned int num,
999 bool continuous,
1000 const void *elements,
1001 const size_t *sizes,
1002 size_t same_size,
1003 enum array_types typ,
1004 Oid oid)
1005{
1006 struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls);
1007
1008 meta->typ = typ;
1009 meta->oid = oid;
1010 meta->sizes = sizes;
1011 meta->same_size = same_size;
1012 meta->continuous = continuous;
1013
1014 {
1015 struct GNUNET_PQ_QueryParam res = {
1016 .conv = qconv_array,
1017 .conv_cls = meta,
1018 .conv_cls_cleanup = &qconv_array_cls_cleanup,
1019 .data = elements,
1020 .size = num,
1021 .num_params = 1,
1022 };
1023
1024 return res;
1025 }
1026}
1027
1028
1029struct GNUNET_PQ_QueryParam
1030GNUNET_PQ_query_param_array_bool (
1031 unsigned int num,
1032 const bool *elements,
1033 struct GNUNET_PQ_Context *db)
1034{
1035 Oid oid;
1036
1037 GNUNET_assert (GNUNET_OK ==
1038 GNUNET_PQ_get_oid_by_name (db,
1039 "bool",
1040 &oid));
1041 return query_param_array_generic (num,
1042 true,
1043 elements,
1044 NULL,
1045 sizeof(bool),
1046 array_of_bool,
1047 oid);
1048}
1049
1050
1051struct GNUNET_PQ_QueryParam
1052GNUNET_PQ_query_param_array_uint16 (
1053 unsigned int num,
1054 const uint16_t *elements,
1055 struct GNUNET_PQ_Context *db)
1056{
1057 Oid oid;
1058
1059 GNUNET_assert (GNUNET_OK ==
1060 GNUNET_PQ_get_oid_by_name (db,
1061 "int2",
1062 &oid));
1063 return query_param_array_generic (num,
1064 true,
1065 elements,
1066 NULL,
1067 sizeof(uint16_t),
1068 array_of_uint16,
1069 oid);
1070}
1071
1072
1073struct GNUNET_PQ_QueryParam
1074GNUNET_PQ_query_param_array_uint32 (
1075 unsigned int num,
1076 const uint32_t *elements,
1077 struct GNUNET_PQ_Context *db)
1078{
1079 Oid oid;
1080
1081 GNUNET_assert (GNUNET_OK ==
1082 GNUNET_PQ_get_oid_by_name (db,
1083 "int4",
1084 &oid));
1085 return query_param_array_generic (num,
1086 true,
1087 elements,
1088 NULL,
1089 sizeof(uint32_t),
1090 array_of_uint32,
1091 oid);
1092}
1093
1094
1095struct GNUNET_PQ_QueryParam
1096GNUNET_PQ_query_param_array_uint64 (
1097 unsigned int num,
1098 const uint64_t *elements,
1099 struct GNUNET_PQ_Context *db)
1100{
1101 Oid oid;
1102
1103 GNUNET_assert (GNUNET_OK ==
1104 GNUNET_PQ_get_oid_by_name (db,
1105 "int8",
1106 &oid));
1107 return query_param_array_generic (num,
1108 true,
1109 elements,
1110 NULL,
1111 sizeof(uint64_t),
1112 array_of_uint64,
1113 oid);
1114}
1115
1116
1117struct GNUNET_PQ_QueryParam
1118GNUNET_PQ_query_param_array_bytes (
1119 unsigned int num,
1120 const void *elements,
1121 const size_t *sizes,
1122 struct GNUNET_PQ_Context *db)
1123{
1124 Oid oid;
1125
1126 GNUNET_assert (GNUNET_OK ==
1127 GNUNET_PQ_get_oid_by_name (db,
1128 "bytea",
1129 &oid));
1130 return query_param_array_generic (num,
1131 true,
1132 elements,
1133 sizes,
1134 0,
1135 array_of_byte,
1136 oid);
1137}
1138
1139
1140struct GNUNET_PQ_QueryParam
1141GNUNET_PQ_query_param_array_ptrs_bytes (
1142 unsigned int num,
1143 const void *elements[static num],
1144 const size_t *sizes,
1145 struct GNUNET_PQ_Context *db)
1146{
1147 Oid oid;
1148
1149 GNUNET_assert (GNUNET_OK ==
1150 GNUNET_PQ_get_oid_by_name (db,
1151 "bytea",
1152 &oid));
1153 return query_param_array_generic (num,
1154 false,
1155 elements,
1156 sizes,
1157 0,
1158 array_of_byte,
1159 oid);
1160}
1161
1162
1163struct GNUNET_PQ_QueryParam
1164GNUNET_PQ_query_param_array_bytes_same_size (
1165 unsigned int num,
1166 const void *elements,
1167 size_t same_size,
1168 struct GNUNET_PQ_Context *db)
1169{
1170 Oid oid;
1171
1172 GNUNET_assert (GNUNET_OK ==
1173 GNUNET_PQ_get_oid_by_name (db,
1174 "bytea",
1175 &oid));
1176 return query_param_array_generic (num,
1177 true,
1178 elements,
1179 NULL,
1180 same_size,
1181 array_of_byte,
1182 oid);
1183}
1184
1185
1186struct GNUNET_PQ_QueryParam
1187GNUNET_PQ_query_param_array_ptrs_bytes_same_size (
1188 unsigned int num,
1189 const void *elements[static num],
1190 size_t same_size,
1191 struct GNUNET_PQ_Context *db)
1192{
1193 Oid oid;
1194
1195 GNUNET_assert (GNUNET_OK ==
1196 GNUNET_PQ_get_oid_by_name (db,
1197 "bytea",
1198 &oid));
1199 return query_param_array_generic (num,
1200 false,
1201 elements,
1202 NULL,
1203 same_size,
1204 array_of_byte,
1205 oid);
1206}
1207
1208
1209struct GNUNET_PQ_QueryParam
1210GNUNET_PQ_query_param_array_string (
1211 unsigned int num,
1212 const char *elements,
1213 struct GNUNET_PQ_Context *db)
1214{
1215 Oid oid;
1216
1217 GNUNET_assert (GNUNET_OK ==
1218 GNUNET_PQ_get_oid_by_name (db,
1219 "text",
1220 &oid));
1221 return query_param_array_generic (num,
1222 true,
1223 elements,
1224 NULL,
1225 0,
1226 array_of_string,
1227 oid);
1228}
1229
1230
1231struct GNUNET_PQ_QueryParam
1232GNUNET_PQ_query_param_array_ptrs_string (
1233 unsigned int num,
1234 const char *elements[static num],
1235 struct GNUNET_PQ_Context *db)
1236{
1237 Oid oid;
1238
1239 GNUNET_assert (GNUNET_OK ==
1240 GNUNET_PQ_get_oid_by_name (db,
1241 "text",
1242 &oid));
1243 return query_param_array_generic (num,
1244 false,
1245 elements,
1246 NULL,
1247 0,
1248 array_of_string,
1249 oid);
1250}
1251
1252
1253struct GNUNET_PQ_QueryParam
1254GNUNET_PQ_query_param_array_abs_time (
1255 unsigned int num,
1256 const struct GNUNET_TIME_Absolute *elements,
1257 struct GNUNET_PQ_Context *db)
1258{
1259 Oid oid;
1260
1261 GNUNET_assert (GNUNET_OK ==
1262 GNUNET_PQ_get_oid_by_name (db,
1263 "int8",
1264 &oid));
1265 return query_param_array_generic (num,
1266 true,
1267 elements,
1268 NULL,
1269 sizeof(struct GNUNET_TIME_Absolute),
1270 array_of_abs_time,
1271 oid);
1272}
1273
1274
1275struct GNUNET_PQ_QueryParam
1276GNUNET_PQ_query_param_array_ptrs_abs_time (
1277 unsigned int num,
1278 const struct GNUNET_TIME_Absolute *elements[],
1279 struct GNUNET_PQ_Context *db)
1280{
1281 Oid oid;
1282
1283 GNUNET_assert (GNUNET_OK ==
1284 GNUNET_PQ_get_oid_by_name (db,
1285 "int8",
1286 &oid));
1287 return query_param_array_generic (num,
1288 false,
1289 elements,
1290 NULL,
1291 sizeof(struct GNUNET_TIME_Absolute),
1292 array_of_abs_time,
1293 oid);
1294}
1295
1296
1297struct GNUNET_PQ_QueryParam
1298GNUNET_PQ_query_param_array_rel_time (
1299 unsigned int num,
1300 const struct GNUNET_TIME_Relative *elements,
1301 struct GNUNET_PQ_Context *db)
1302{
1303 Oid oid;
1304
1305 GNUNET_assert (GNUNET_OK ==
1306 GNUNET_PQ_get_oid_by_name (db,
1307 "int8",
1308 &oid));
1309 return query_param_array_generic (num,
1310 true,
1311 elements,
1312 NULL,
1313 sizeof(struct GNUNET_TIME_Relative),
1314 array_of_abs_time,
1315 oid);
1316}
1317
1318
1319struct GNUNET_PQ_QueryParam
1320GNUNET_PQ_query_param_array_ptrs_rel_time (
1321 unsigned int num,
1322 const struct GNUNET_TIME_Relative *elements[],
1323 struct GNUNET_PQ_Context *db)
1324{
1325 Oid oid;
1326
1327 GNUNET_assert (GNUNET_OK ==
1328 GNUNET_PQ_get_oid_by_name (db,
1329 "int8",
1330 &oid));
1331 return query_param_array_generic (num,
1332 false,
1333 elements,
1334 NULL,
1335 sizeof(struct GNUNET_TIME_Relative),
1336 array_of_abs_time,
1337 oid);
1338}
1339
1340
1341struct GNUNET_PQ_QueryParam
1342GNUNET_PQ_query_param_array_timestamp (
1343 unsigned int num,
1344 const struct GNUNET_TIME_Timestamp *elements,
1345 struct GNUNET_PQ_Context *db)
1346{
1347 Oid oid;
1348
1349 GNUNET_assert (GNUNET_OK ==
1350 GNUNET_PQ_get_oid_by_name (db,
1351 "int8",
1352 &oid));
1353 return query_param_array_generic (num,
1354 true,
1355 elements,
1356 NULL,
1357 sizeof(struct GNUNET_TIME_Timestamp),
1358 array_of_timestamp,
1359 oid);
1360}
1361
1362
1363struct GNUNET_PQ_QueryParam
1364GNUNET_PQ_query_param_array_ptrs_timestamp (
1365 unsigned int num,
1366 const struct GNUNET_TIME_Timestamp *elements[],
1367 struct GNUNET_PQ_Context *db)
1368{
1369 Oid oid;
1370
1371 GNUNET_assert (GNUNET_OK ==
1372 GNUNET_PQ_get_oid_by_name (db,
1373 "int8",
1374 &oid));
1375 return query_param_array_generic (num,
1376 false,
1377 elements,
1378 NULL,
1379 sizeof(struct GNUNET_TIME_Timestamp),
1380 array_of_timestamp,
1381 oid);
1382}
1383
1384
1385/**
1386 * Function called to convert input argument into SQL parameters.
1387 *
1388 * @param cls closure
1389 * @param data pointer to input argument
1390 * @param data_len number of bytes in @a data (if applicable)
1391 * @param[out] param_values SQL data to set
1392 * @param[out] param_lengths SQL length data to set
1393 * @param[out] param_formats SQL format data to set
1394 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
1395 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
1396 * @param scratch_length number of entries left in @a scratch
1397 * @return -1 on error, number of offsets used in @a scratch otherwise
1398 */
1399static int
1400qconv_blind_sign_pub (void *cls,
1401 const void *data,
1402 size_t data_len,
1403 void *param_values[],
1404 int param_lengths[],
1405 int param_formats[],
1406 unsigned int param_length,
1407 void *scratch[],
1408 unsigned int scratch_length)
1409{
1410 const struct GNUNET_CRYPTO_BlindSignPublicKey *public_key = data;
1411 size_t tlen;
1412 size_t len;
1413 uint32_t be;
1414 char *buf;
1415 void *tbuf;
1416
1417 (void) cls;
1418 (void) data_len;
1419 GNUNET_assert (1 == param_length);
1420 GNUNET_assert (scratch_length > 0);
1421 GNUNET_break (NULL == cls);
1422 be = htonl ((uint32_t) public_key->cipher);
1423 switch (public_key->cipher)
1424 {
1425 case GNUNET_CRYPTO_BSA_RSA:
1426 tlen = GNUNET_CRYPTO_rsa_public_key_encode (
1427 public_key->details.rsa_public_key,
1428 &tbuf);
1429 break;
1430 case GNUNET_CRYPTO_BSA_CS:
1431 tlen = sizeof (public_key->details.cs_public_key);
1432 break;
1433 default:
1434 GNUNET_assert (0);
1435 }
1436 len = tlen + sizeof (be);
1437 buf = GNUNET_malloc (len);
1438 GNUNET_memcpy (buf,
1439 &be,
1440 sizeof (be));
1441 switch (public_key->cipher)
1442 {
1443 case GNUNET_CRYPTO_BSA_RSA:
1444 GNUNET_memcpy (&buf[sizeof (be)],
1445 tbuf,
1446 tlen);
1447 GNUNET_free (tbuf);
1448 break;
1449 case GNUNET_CRYPTO_BSA_CS:
1450 GNUNET_memcpy (&buf[sizeof (be)],
1451 &public_key->details.cs_public_key,
1452 tlen);
1453 break;
1454 default:
1455 GNUNET_assert (0);
1456 }
1457
1458 scratch[0] = buf;
1459 param_values[0] = (void *) buf;
1460 param_lengths[0] = len;
1461 param_formats[0] = 1;
1462 return 1;
1463}
1464
1465
1466/**
1467 * Generate query parameter for a blind sign public key of variable size.
1468 *
1469 * @param pub pointer to the query parameter to pass
1470 */
1471struct GNUNET_PQ_QueryParam
1472GNUNET_PQ_query_param_blind_sign_pub (
1473 const struct GNUNET_CRYPTO_BlindSignPublicKey *pub)
1474{
1475 struct GNUNET_PQ_QueryParam res = {
1476 .conv = &qconv_blind_sign_pub,
1477 .data = pub,
1478 .num_params = 1
1479 };
1480
1481 return res;
1482}
1483
1484
1485/**
1486 * Function called to convert input argument into SQL parameters.
1487 *
1488 * @param cls closure
1489 * @param data pointer to input argument
1490 * @param data_len number of bytes in @a data (if applicable)
1491 * @param[out] param_values SQL data to set
1492 * @param[out] param_lengths SQL length data to set
1493 * @param[out] param_formats SQL format data to set
1494 * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
1495 * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
1496 * @param scratch_length number of entries left in @a scratch
1497 * @return -1 on error, number of offsets used in @a scratch otherwise
1498 */
1499static int
1500qconv_blind_sign_priv (void *cls,
1501 const void *data,
1502 size_t data_len,
1503 void *param_values[],
1504 int param_lengths[],
1505 int param_formats[],
1506 unsigned int param_length,
1507 void *scratch[],
1508 unsigned int scratch_length)
1509{
1510 const struct GNUNET_CRYPTO_BlindSignPrivateKey *private_key = data;
1511 size_t tlen;
1512 size_t len;
1513 uint32_t be;
1514 char *buf;
1515 void *tbuf;
1516
1517 (void) cls;
1518 (void) data_len;
1519 GNUNET_assert (1 == param_length);
1520 GNUNET_assert (scratch_length > 0);
1521 GNUNET_break (NULL == cls);
1522 be = htonl ((uint32_t) private_key->cipher);
1523 switch (private_key->cipher)
1524 {
1525 case GNUNET_CRYPTO_BSA_RSA:
1526 tlen = GNUNET_CRYPTO_rsa_private_key_encode (
1527 private_key->details.rsa_private_key,
1528 &tbuf);
1529 break;
1530 case GNUNET_CRYPTO_BSA_CS:
1531 tlen = sizeof (private_key->details.cs_private_key);
1532 break;
1533 default:
1534 GNUNET_assert (0);
1535 }
1536 len = tlen + sizeof (be);
1537 buf = GNUNET_malloc (len);
1538 GNUNET_memcpy (buf,
1539 &be,
1540 sizeof (be));
1541 switch (private_key->cipher)
1542 {
1543 case GNUNET_CRYPTO_BSA_RSA:
1544 GNUNET_memcpy (&buf[sizeof (be)],
1545 tbuf,
1546 tlen);
1547 GNUNET_free (tbuf);
1548 break;
1549 case GNUNET_CRYPTO_BSA_CS:
1550 GNUNET_memcpy (&buf[sizeof (be)],
1551 &private_key->details.cs_private_key,
1552 tlen);
1553 break;
1554 default:
1555 GNUNET_assert (0);
1556 }
1557
1558 scratch[0] = buf;
1559 param_values[0] = (void *) buf;
1560 param_lengths[0] = len;
1561 param_formats[0] = 1;
1562 return 1;
1563}
1564
1565
1566/**
1567 * Generate query parameter for a blind sign private key of variable size.
1568 *
1569 * @param priv pointer to the query parameter to pass
1570 */
1571struct GNUNET_PQ_QueryParam
1572GNUNET_PQ_query_param_blind_sign_priv (
1573 const struct GNUNET_CRYPTO_BlindSignPrivateKey *priv)
1574{
1575 struct GNUNET_PQ_QueryParam res = {
1576 .conv = &qconv_blind_sign_priv,
1577 .data = priv,
1578 .num_params = 1
1579 };
1580
1581 return res;
1582}
1583
1584
1585/* end of pq_query_helper.c */