4 * Date: Thu Jul 15 18:23:26 2010
6 * GNU recutils - Data integrity.
10 /* Copyright (C) 2010-2019 Jose E. Marchesi */
12 /* This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33 #define _(str) dgettext (PACKAGE, str)
36 #if defined REMOTE_DESCRIPTORS
37 # include <curl/curl.h>
41 #include <rec-utils.h>
47 static int rec_int_check_descriptor (rec_rset_t rset
, rec_buf_t errors
);
48 static int rec_int_check_record_key (rec_rset_t rset
,
49 rec_record_t orig_record
, rec_record_t record
,
51 static int rec_int_check_record_types (rec_db_t db
,
55 static int rec_int_check_record_mandatory (rec_rset_t rset
, rec_record_t record
,
57 static int rec_int_check_record_unique (rec_rset_t rset
, rec_record_t record
,
59 static int rec_int_check_record_prohibit (rec_rset_t rset
, rec_record_t record
,
61 static int rec_int_check_record_sex_constraints (rec_rset_t rset
, rec_record_t record
,
63 static int rec_int_check_record_allowed (rec_rset_t rset
, rec_record_t record
,
66 #if defined REC_CRYPT_SUPPORT
67 static int rec_int_check_record_secrets (rec_rset_t rset
, rec_record_t record
,
71 static int rec_int_merge_remote (rec_rset_t rset
, rec_buf_t errors
);
72 static bool rec_int_rec_type_p (const char *str
);
74 /* The following macros are used by some functions in this file to
77 #define FNAME(id) rec_std_field_name ((id))
79 #define ADD_ERROR(buf,str,...) \
83 if (asprintf (&tmp, (str), __VA_ARGS__) != -1) \
85 rec_buf_puts (tmp, (buf)); \
96 rec_int_check_db (rec_db_t db
,
97 bool check_descriptors_p
,
98 bool remote_descriptors_p
,
108 db_size
= rec_db_size (db
);
109 for (n_rset
= 0; n_rset
< db_size
; n_rset
++)
111 rset
= rec_db_get_rset (db
, n_rset
);
112 ret
= ret
+ rec_int_check_rset (db
,
115 remote_descriptors_p
,
123 rec_int_check_rset (rec_db_t db
,
125 bool check_descriptor_p
,
126 bool remote_descriptor_p
,
130 rec_mset_iterator_t iter
;
132 rec_record_t descriptor
;
133 size_t num_records
, min_records
, max_records
;
137 if (remote_descriptor_p
138 && (descriptor
= rec_rset_descriptor (rset
)))
140 /* Make a backup of the record descriptor to restore it
142 descriptor
= rec_record_dup (descriptor
);
144 /* Fetch the remote descriptor, if any, and merge it with the
145 local descriptor. If there is any error, stop and report
147 res
= rec_int_merge_remote (rset
, errors
);
154 if (check_descriptor_p
)
156 res
+= rec_int_check_descriptor (rset
, errors
);
161 /* Stop here, since a lot of errors in the records will be
162 generated due to errors in the record descriptor. */
166 /* Verify rset size restrictions. */
167 num_records
= rec_rset_num_records (rset
);
168 min_records
= rec_rset_min_records (rset
);
169 max_records
= rec_rset_max_records (rset
);
171 if (min_records
== max_records
)
173 if (num_records
!= min_records
)
176 _("%s: error: the number of records of type %s should be %zd.\n"),
177 rec_rset_source (rset
), rec_rset_type (rset
), min_records
);
183 if (num_records
> rec_rset_max_records (rset
))
186 _("%s: error: too many records of type %s. Maximum allowed are %zd.\n"),
187 rec_rset_source (rset
), rec_rset_type (rset
), rec_rset_max_records (rset
));
190 if (num_records
< rec_rset_min_records (rset
))
193 _("%s: error: too few records of type %s. Minimum allowed are %zd.\n"),
194 rec_rset_source (rset
), rec_rset_type (rset
), rec_rset_min_records (rset
));
199 iter
= rec_mset_iterator (rec_rset_mset (rset
));
200 while (rec_mset_iterator_next (&iter
, MSET_RECORD
, (const void **) &record
, NULL
))
202 res
+= rec_int_check_record (db
,
208 rec_mset_iterator_free (&iter
);
210 if (remote_descriptor_p
)
212 /* Restore the original descriptor in the record set. */
213 rec_rset_set_descriptor (rset
, descriptor
);
220 rec_int_check_record (rec_db_t db
,
222 rec_record_t orig_record
,
229 rec_int_check_record_key (rset
, orig_record
, record
, errors
)
230 + rec_int_check_record_types (db
, rset
, record
, errors
)
231 + rec_int_check_record_mandatory (rset
, record
, errors
)
232 + rec_int_check_record_unique (rset
, record
, errors
)
233 #if defined REC_CRYPT_SUPPORT
234 + rec_int_check_record_secrets (rset
, record
, errors
)
236 + rec_int_check_record_prohibit (rset
, record
, errors
)
237 + rec_int_check_record_sex_constraints (rset
, record
, errors
)
238 + rec_int_check_record_allowed (rset
, record
, errors
);
244 rec_int_check_field_type (rec_db_t db
,
256 /* Get the proper type to check 'field' with, checking with the type
257 from the type registry of 'rset', if any. */
259 type
= rec_rset_get_field_type (rset
, rec_field_name (field
));
261 /* Check the field with the type. This is done by simply invoking
262 rec_type_check on the field value. An exception to this is the
263 'rec' type. The 'rec' type is used to implement foreign keys,
264 and its effect on the type integrity system is that the value of
265 the field must be considered to be of whatever type the primary
266 key of the referred record set is. */
270 if (rec_type_kind (type
) == REC_TYPE_REC
)
272 /* Get the name of the referred record set. Check the type
275 - The referred rset exists in DB and
276 - The referred rset has a primary key.
277 - The primary key of the referred rset has a type.
280 const char *rset_type
= rec_type_rec (type
);
281 rec_rset_t rset
= rec_db_get_rset_by_type (db
, rset_type
);
285 const char *key
= rec_rset_key (rset
);
286 rec_type_t key_type
= rec_rset_get_field_type (rset
, key
);
290 if (!rec_type_check (key_type
, rec_field_value (field
), &errors_str
))
295 "%s:%s: error: %s\n",
296 rec_field_source (field
), rec_field_location_str (field
),
307 if (!rec_type_check (type
, rec_field_value (field
), &errors_str
))
312 "%s:%s: error: %s\n",
313 rec_field_source (field
), rec_field_location_str (field
),
330 rec_int_collect_field_list (rec_record_t record
,
334 size_t num_fields
= rec_record_get_num_fields_by_name (record
, fname
);
335 rec_fex_t res
= rec_fex_new (NULL
, REC_FEX_SIMPLE
);
338 return NULL
; /* Out of memory. */
340 for (i
= 0; i
< num_fields
; i
++)
342 rec_field_t field
= rec_record_get_field_by_name (record
, fname
, i
);
343 rec_fex_t fex
= rec_fex_new (rec_field_value (field
), REC_FEX_SIMPLE
);
345 /* Invalid value in the field. Ignore it. */
348 for (j
= 0; j
< rec_fex_size (fex
); j
++)
350 rec_fex_elem_t elem
= rec_fex_get (fex
, j
);
351 char *field_name
= strdup (rec_fex_elem_field_name (elem
));
354 || !rec_fex_append (res
,
356 rec_fex_elem_min (elem
),
357 rec_fex_elem_max (elem
)))
358 /* Not enough memory: panic and retreat! */
361 rec_fex_destroy (fex
);
368 rec_int_check_record_types (rec_db_t db
,
375 rec_mset_iterator_t iter
;
379 iter
= rec_mset_iterator (rec_record_mset (record
));
380 while (rec_mset_iterator_next (&iter
, MSET_FIELD
, (const void **) &field
, NULL
))
382 /* Check for the type. */
383 if (!rec_int_check_field_type (db
, rset
, field
, errors
))
389 rec_mset_iterator_free (&iter
);
395 rec_int_check_record_mandatory (rec_rset_t rset
,
399 rec_fex_t fex_mandatory
= NULL
;
403 rec_record_t descriptor
= rec_rset_descriptor (rset
);
406 fex_mandatory
= rec_int_collect_field_list (descriptor
, FNAME(REC_FIELD_MANDATORY
));
409 ADD_ERROR (errors
, _("out of memory\n"), "");
414 /* Make sure that all fields in the mandatory fields list are in
417 for (i
= 0; i
< rec_fex_size (fex_mandatory
); i
++)
419 const char *fname
= rec_fex_elem_field_name (rec_fex_get (fex_mandatory
, i
));
420 if (rec_record_get_num_fields_by_name (record
, fname
)
424 _("%s:%s: error: mandatory field '%s' not found in record\n"),
425 rec_record_source (record
),
426 rec_record_location_str (record
),
435 rec_fex_destroy (fex_mandatory
);
440 rec_int_check_record_allowed (rec_rset_t rset
,
444 /* If %allowed is specified then fields with names not in the union
445 of %allowed + %mandatory + %key are not allowed in records, and
446 thus that situation is an integrity error. */
448 rec_fex_t fex_allowed
= NULL
;
449 rec_fex_t fex_mandatory
= NULL
;
450 rec_fex_t fex_key
= NULL
;
453 rec_record_t descriptor
= rec_rset_descriptor (rset
);
457 fex_allowed
= rec_int_collect_field_list (descriptor
, FNAME(REC_FIELD_ALLOWED
));
458 fex_mandatory
= rec_int_collect_field_list (descriptor
, FNAME(REC_FIELD_MANDATORY
));
459 fex_key
= rec_int_collect_field_list (descriptor
, FNAME(REC_FIELD_KEY
));
461 if (!fex_allowed
|| !fex_mandatory
|| !fex_key
)
463 ADD_ERROR (errors
, _("out of memory\n"), "");
469 if (rec_fex_size (fex_allowed
) == 0)
473 /* Make sure that all the fields in RECORD are in either
474 %allowed, %mandatory or %key. */
476 rec_field_t field
= NULL
;
477 rec_mset_iterator_t iter
= rec_mset_iterator (rec_record_mset (record
));
478 while (rec_mset_iterator_next (&iter
, MSET_FIELD
, (const void **) &field
, NULL
))
480 const char *field_name
= rec_field_name (field
);
481 if (!(rec_fex_member_p (fex_allowed
, field_name
, -1, -1)
482 || rec_fex_member_p (fex_mandatory
, field_name
, -1, -1)
483 || rec_fex_member_p (fex_key
, field_name
, -1, -1)))
485 /* This field is not allowed. */
487 _("%s:%s: error: field '%s' not allowed in this record set\n"),
488 rec_record_source (record
),
489 rec_record_location_str (record
),
494 rec_mset_iterator_free (&iter
);
499 rec_fex_destroy (fex_allowed
);
500 rec_fex_destroy (fex_mandatory
);
501 rec_fex_destroy (fex_key
);
506 rec_int_check_record_unique (rec_rset_t rset
,
510 rec_fex_t fex_unique
= NULL
;
514 rec_record_t descriptor
= rec_rset_descriptor (rset
);
517 fex_unique
= rec_int_collect_field_list (descriptor
, FNAME(REC_FIELD_UNIQUE
));
520 ADD_ERROR (errors
, _("out of memory\n"), "");
525 /* Make sure that all fields in the unique fields list are
526 unique in this record. */
528 for (i
= 0; i
< rec_fex_size (fex_unique
); i
++)
530 const char *fname
= rec_fex_elem_field_name (rec_fex_get (fex_unique
, i
));
531 if (rec_record_get_num_fields_by_name (record
, fname
) > 1)
534 _("%s:%s: error: field '%s' should be unique in this record\n"),
535 rec_record_source (record
),
536 rec_record_location_str (record
),
545 rec_fex_destroy (fex_unique
);
550 rec_int_check_record_prohibit (rec_rset_t rset
,
554 rec_fex_t fex_prohibit
= NULL
;
558 rec_record_t descriptor
= rec_rset_descriptor (rset
);
561 fex_prohibit
= rec_int_collect_field_list (descriptor
, FNAME(REC_FIELD_PROHIBIT
));
564 ADD_ERROR (errors
, _("out of memory\n"), "");
569 /* Make sure that no field in the prohibit fields list is
570 present in the record. */
572 for (i
= 0; i
< rec_fex_size (fex_prohibit
); i
++)
574 const char *fname
= rec_fex_elem_field_name (rec_fex_get (fex_prohibit
, i
));
575 if (rec_record_get_num_fields_by_name (record
, fname
) > 0)
578 _("%s:%s: error: prohibited field '%s' found in record\n"),
579 rec_record_source (record
),
580 rec_record_location_str (record
),
589 rec_fex_destroy (fex_prohibit
);
594 rec_int_check_record_sex_constraints (rec_rset_t rset
,
600 size_t num_constraints
= rec_rset_num_sex_constraints (rset
);
602 for (i
= 0; i
< num_constraints
; i
++)
605 rec_sex_t sex
= rec_rset_sex_constraint (rset
, i
);
607 if (!rec_sex_eval (sex
, record
, &status
))
610 _("%s:%s: error: %%constraint[%d] violated in record\n"),
611 rec_record_source (record
),
612 rec_record_location_str (record
),
621 #if defined REC_CRYPT_SUPPORT
624 rec_int_check_record_secrets (rec_rset_t rset
,
630 rec_mset_iterator_t iter
;
634 iter
= rec_mset_iterator (rec_record_mset (record
));
635 while (rec_mset_iterator_next (&iter
, MSET_FIELD
, (const void**) &field
, NULL
))
637 /* If the field is confidential it must be encrypted. Encrypted
638 field values can be recognized by the "encrypted-"
640 #define REC_ENCRYPTED_PREFIX "encrypted-"
641 if (rec_rset_field_confidential_p (rset
, rec_field_name (field
))
642 && (strncmp (rec_field_value (field
),
643 REC_ENCRYPTED_PREFIX
,
644 strlen (REC_ENCRYPTED_PREFIX
)) != 0))
647 _("%s:%s: error: confidential field is not encrypted\n"),
648 rec_record_source (record
),
649 rec_record_location_str (record
));
654 rec_mset_iterator_free (&iter
);
659 #endif /* REC_CRYPT_SUPPORT */
662 rec_int_check_record_key (rec_rset_t rset
,
663 rec_record_t orig_record
,
668 rec_record_t descriptor
;
669 rec_record_t other_record
;
670 rec_mset_iterator_t iter
;
671 char *key_field_name
;
674 rec_field_t other_key
;
681 descriptor
= rec_rset_descriptor (rset
);
684 for (i
= 0; i
< rec_record_get_num_fields_by_name (descriptor
,
685 FNAME(REC_FIELD_KEY
));
688 field
= rec_record_get_field_by_name (descriptor
, FNAME(REC_FIELD_KEY
), i
);
690 /* Parse the field name from the value of %key: */
691 key_field_name
= rec_parse_field_name_str (rec_field_value (field
));
694 num_fields
= rec_record_get_num_fields_by_name (record
, key_field_name
);
699 _("%s:%s: error: key field '%s' not found in record\n"),
700 rec_record_source (record
),
701 rec_record_location_str (record
),
702 rec_field_value (field
));
705 else if (num_fields
> 1)
708 _("%s:%s: error: multiple key fields '%s' in record\n"),
709 rec_record_source (record
),
710 rec_record_location_str (record
),
711 rec_field_value (field
));
714 else /* num_fields == 1 */
716 /* Check that the value specified as the key is
717 unique in the whole record set. */
718 key
= rec_record_get_field_by_name (record
,
721 duplicated_key
= false;
723 iter
= rec_mset_iterator (rec_rset_mset (rset
));
724 while (rec_mset_iterator_next (&iter
, MSET_RECORD
, (const void**) &other_record
, NULL
))
726 if (other_record
!= orig_record
)
728 /* XXX: Only the first key field is considered. */
729 other_key
= rec_record_get_field_by_name (other_record
,
734 if (strcmp (rec_field_value (other_key
),
735 rec_field_value (key
)) == 0)
737 /* Found a key field with the same
738 value in other record. */
739 duplicated_key
= true;
746 rec_mset_iterator_free (&iter
);
751 _("%s:%s: error: duplicated key value in field '%s' in record\n"),
752 rec_record_source (orig_record
),
753 rec_record_location_str (orig_record
),
754 rec_field_name (key
));
760 free (key_field_name
);
769 rec_int_check_descriptor (rec_rset_t rset
,
773 rec_record_t descriptor
;
774 rec_mset_iterator_t iter
;
776 const char *field_name
;
777 const char *field_value
;
779 const char *auto_field_name
;
782 char *type_name
= NULL
;
783 const char *p
, *q
= NULL
;
787 descriptor
= rec_rset_descriptor (rset
);
790 /* Check the type of the record set:
792 1. There should be one (and only one) %rec: field in the
794 2. The value of the %rec: field shall be well-formed.
796 if (rec_record_get_num_fields_by_name (descriptor
, FNAME(REC_FIELD_REC
)) == 0)
799 _("%s:%s: error: missing %%rec field in record descriptor\n"),
800 rec_record_source (descriptor
),
801 rec_record_location_str (descriptor
));
804 else if (rec_record_get_num_fields_by_name (descriptor
, FNAME(REC_FIELD_REC
)) > 1)
807 _("%s:%s: error: too many %%rec fields in record descriptor\n"),
808 rec_record_source (descriptor
),
809 rec_record_location_str (descriptor
));
813 field
= rec_record_get_field_by_name (descriptor
, FNAME(REC_FIELD_REC
), 0);
814 if (!rec_int_rec_type_p (rec_field_value (field
)))
817 _("%s:%s: error: invalid record type %s\n"),
818 rec_field_source (field
),
819 rec_field_location_str (field
),
820 rec_field_value (field
));
824 /* Only one 'key:' entry is allowed, if any. */
825 if (rec_record_get_num_fields_by_name (descriptor
, FNAME(REC_FIELD_KEY
)) > 1)
828 _("%s:%s: error: only one %%key field is allowed in a record descriptor\n"),
829 rec_record_source (descriptor
),
830 rec_record_location_str (descriptor
));
834 /* Only one 'size:' entry is allowed, if any. */
835 if (rec_record_get_num_fields_by_name (descriptor
, FNAME(REC_FIELD_SIZE
)) > 1)
838 _("%s:%s: error: only one %%size field is allowed in a record descriptor\n"),
839 rec_record_source (descriptor
),
840 rec_record_location_str (descriptor
));
844 /* Only one 'sort:' entry is allowed, if any. */
845 if (rec_record_get_num_fields_by_name (descriptor
, FNAME(REC_FIELD_SORT
)) > 1)
848 _("%s:%s: error: only one %%sort field is allowed in a record descriptor\n"),
849 rec_record_source (descriptor
),
850 rec_record_location_str (descriptor
));
854 /* Iterate on fields. */
856 iter
= rec_mset_iterator (rec_record_mset (descriptor
));
857 while (rec_mset_iterator_next (&iter
, MSET_FIELD
, (const void**) &field
, NULL
))
859 field_name
= rec_field_name (field
);
860 field_value
= rec_field_value (field
);
862 if (rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_TYPE
)))
864 /* Check for the list of fields. */
866 rec_skip_blanks (&p
);
867 if (!rec_parse_regexp (&p
, "^" REC_FNAME_RE
"(," REC_FNAME_RE
")*",
871 _("%s:%s: error: expected a comma-separated list of fields \
872 before the type specification\n"),
873 rec_field_source (field
),
874 rec_field_location_str (field
));
878 /* Check the type descriptor. Note that it can be
879 either a type specification or a type name. */
880 rec_skip_blanks (&p
);
881 if (!rec_type_descr_p (p
))
884 if (rec_parse_regexp (&q
, "^" REC_TYPE_NAME_RE
"[ \t\n]*$",
887 /* The named type shall exist in the record set
890 XXX: but this is probably a warning rather
893 rec_parse_regexp (&p
, "^" REC_TYPE_NAME_RE
, &type_name
);
894 if (!rec_type_reg_get (rec_rset_get_type_reg (rset
), type_name
))
897 _("%s:%s: error: the referred type %s \
899 rec_field_source (field
),
900 rec_field_location_str (field
),
907 /* XXX: make rec_type_descr_p to report more details. */
909 _("%s:%s: error: invalid type specification\n"),
910 rec_field_source (field
),
911 rec_field_location_str (field
));
916 else if (rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_TYPEDEF
)))
918 /* Check for the type name. */
920 rec_skip_blanks (&p
);
921 if (!rec_parse_regexp (&p
, "^" REC_TYPE_NAME_RE
, NULL
))
924 _("%s:%s: error: expected a type name before the type \
926 rec_field_source (field
),
927 rec_field_location_str (field
));
931 /* Check the type descriptor. Note that it can be
932 either a type specification or a type name. */
933 rec_skip_blanks (&p
);
934 if (!rec_type_descr_p (p
))
937 if (rec_parse_regexp (&q
, "^" REC_TYPE_NAME_RE
"[ \t\n]*$",
940 /* The named type shall exist in the record set
943 XXX: but this is probably a warning rather
946 rec_parse_regexp (&p
, "^" REC_TYPE_NAME_RE
, &type_name
);
947 if (!rec_type_reg_get (rec_rset_get_type_reg (rset
), type_name
))
950 _("%s:%s: error: the referred type %s \
952 rec_field_source (field
),
953 rec_field_location_str (field
),
960 /* XXX: make rec_type_descr_p to report more details. */
962 _("%s:%s: error: invalid typedef specification\n"),
963 rec_field_source (field
),
964 rec_field_location_str (field
));
969 else if (rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_CONSTRAINT
)))
971 /* Check that the value of this field is a valid
972 selection expression. */
974 rec_sex_t sex
= rec_sex_new (false);
977 if (rec_sex_compile (sex
, field_value
))
979 rec_sex_destroy (sex
);
984 _("%s:%s: error: value for %s[%zd] is not a valid selection expression\n"),
985 rec_record_source (descriptor
),
986 rec_record_location_str (descriptor
),
987 rec_field_name (field
),
988 rec_record_get_field_index_by_name (descriptor
, field
));
998 else if (rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_MANDATORY
))
999 || rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_UNIQUE
))
1000 || rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_PROHIBIT
))
1001 || rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_AUTO
))
1002 || rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_SORT
))
1003 || rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_ALLOWED
)))
1005 /* Check that the value of this field is a parseable
1006 list of field names. */
1007 fex
= rec_fex_new (field_value
, REC_FEX_SIMPLE
);
1010 rec_fex_destroy (fex
);
1015 _("%s:%s: error: value for %s[%zd] is not a list of field names\n"),
1016 rec_record_source (descriptor
),
1017 rec_record_location_str (descriptor
),
1018 rec_field_name (field
),
1019 rec_record_get_field_index_by_name (descriptor
, field
));
1023 else if (rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_SIZE
)))
1025 if (!rec_match (field_value
, REC_INT_SIZE_RE
))
1028 _("%s:%s: error: value for %s should be a number optionally preceded by >, <, >= or <=.\n"),
1029 rec_field_source (field
),
1030 rec_field_location_str (field
),
1035 #if defined REC_CRYPT_SUPPORT
1036 else if (rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_CONFIDENTIAL
)))
1038 if (!rec_match (field_value
,
1040 "[ \n\t]*" REC_FNAME_RE
"([ \n\t]+" REC_FNAME_RE
")*"
1044 _("%s:%s: error: value for %s should be a list of field names.\n"),
1045 rec_field_source (field
),
1046 rec_field_location_str (field
),
1051 #endif /* REC_CRYPT_SUPPORT */
1053 if ((rec_field_name_equal_p (field_name
, FNAME(REC_FIELD_AUTO
)))
1054 && (fex
= rec_fex_new (field_value
, REC_FEX_SIMPLE
)))
1056 /* Check that the auto incremented fields have not been
1057 declared with a type other than 'int'. */
1058 for (i
= 0; i
< rec_fex_size (fex
); i
++)
1060 auto_field_name
= rec_fex_elem_field_name (rec_fex_get (fex
, i
));
1061 type
= rec_rset_get_field_type (rset
, auto_field_name
);
1063 ! ((rec_type_kind (type
) == REC_TYPE_INT
)
1064 || (rec_type_kind (type
) == REC_TYPE_RANGE
)
1065 #if defined UUID_TYPE
1066 || (rec_type_kind (type
) == REC_TYPE_UUID
)
1068 || (rec_type_kind (type
) == REC_TYPE_DATE
)))
1071 #if defined UUID_TYPE
1072 _("%s:%s: error: auto-incremented field %s should be of type int, range, uuid or date\n"),
1074 _("%s:%s: error: auto-incremented field %s should be of type int, range or date\n"),
1076 rec_record_source (descriptor
),
1077 rec_record_location_str (descriptor
),
1085 rec_mset_iterator_free (&iter
);
1092 rec_int_merge_remote (rec_rset_t rset
,
1096 rec_parser_t parser
;
1097 rec_record_t descriptor
;
1099 rec_rset_t remote_rset
;
1100 rec_field_t remote_field
;
1101 rec_mset_iterator_t iter
;
1102 rec_record_t remote_descriptor
;
1103 rec_field_t rec_field
;
1105 char *rec_url
= NULL
;
1106 char *rec_file
= NULL
;
1107 char *rec_source
= NULL
;
1108 FILE *external_file
;
1109 char tmpfile_name
[14];
1113 tmpfile_name
[0] = '\0';
1115 /* If a remote descriptor is defined in the record descriptor of
1116 RSET, fetch it and merge it with the local descriptor. */
1118 descriptor
= rec_rset_descriptor (rset
);
1121 /* Check if there is an URL in the %rec: field. */
1122 rec_field
= rec_record_get_field_by_name (descriptor
, FNAME(REC_FIELD_REC
), 0);
1124 if (!rec_int_rec_type_p (rec_field_value (rec_field
)))
1129 rec_type
= rec_extract_type (rec_field_value (rec_field
));
1130 rec_file
= rec_extract_file (rec_field_value (rec_field
));
1131 rec_url
= rec_extract_url (rec_field_value (rec_field
));
1133 if (rec_file
|| rec_url
)
1137 #if defined REMOTE_DESCRIPTORS
1141 /* Fetch the remote descriptor. */
1142 curl
= curl_easy_init ();
1144 /* Create a temporary file. */
1145 memcpy (tmpfile_name
, "recint-XXXXXX", 13);
1146 tmpfile_name
[13] = '\0';
1147 tmpfile_des
= gen_tempname (tmpfile_name
, 0, 0, GT_FILE
);
1148 external_file
= fdopen (tmpfile_des
, "r+");
1150 /* Fetch the remote file. */
1151 curl_easy_setopt (curl
, CURLOPT_URL
, rec_url
);
1152 curl_easy_setopt (curl
, CURLOPT_WRITEDATA
, external_file
);
1153 curl_easy_setopt (curl
, CURLOPT_FAILONERROR
, 1);
1154 if (curl_easy_perform (curl
) != 0)
1157 _("%s:%s: error: could not fetch remote descriptor from url %s.\n"),
1158 rec_field_source (rec_field
), rec_field_location_str (rec_field
),
1163 curl_easy_cleanup (curl
);
1164 rec_source
= rec_url
;
1167 #endif /* REMOTE_DESCRIPTORS */
1171 /* Try to open the file. */
1172 external_file
= fopen (rec_file
, "r");
1176 _("%s:%s: error: could not read external descriptor from file %s.\n"),
1177 rec_field_source (rec_field
), rec_field_location_str (rec_field
),
1182 rec_source
= rec_file
;
1185 /* Parse the contents of the external file. */
1186 fseek (external_file
, 0, SEEK_SET
);
1187 parser
= rec_parser_new (external_file
, rec_source
);
1188 if (!rec_parse_db (parser
, &remote_db
))
1191 _("%s:%s: error: %s does not contain valid rec data.\n"),
1192 rec_field_source (rec_field
), rec_field_location_str (rec_field
),
1197 rec_parser_destroy (parser
);
1199 /* Get the proper external descriptor and merge it with
1201 remote_rset
= rec_db_get_rset_by_type (remote_db
, rec_type
);
1205 _("%s:%s: error: %s does not contain information for type %s.\n"),
1206 rec_field_source (rec_field
), rec_field_location_str (rec_field
),
1207 rec_source
, rec_type
);
1211 remote_descriptor
= rec_rset_descriptor (remote_rset
);
1212 if (!remote_descriptor
)
1218 iter
= rec_mset_iterator (rec_record_mset (remote_descriptor
));
1219 while (rec_mset_iterator_next (&iter
, MSET_FIELD
, (const void**) &remote_field
, NULL
))
1221 /* Merge the descriptors, but take care to not add a new
1224 if (!rec_field_name_equal_p (rec_field_name (remote_field
), FNAME(REC_FIELD_REC
)))
1226 rec_mset_append (rec_record_mset (descriptor
), MSET_FIELD
, (void *) rec_field_dup (remote_field
), MSET_ANY
);
1230 rec_mset_iterator_free (&iter
);
1232 /* Update the record descriptor (triggering the creation
1233 of a new type registry). */
1234 rec_rset_set_descriptor (rset
, rec_record_dup (descriptor
));
1236 rec_db_destroy (remote_db
);
1237 fclose (external_file
);
1243 if (rec_url
&& (tmpfile_name
[0] != '\0'))
1245 remove (tmpfile_name
);
1255 rec_int_rec_type_p (const char *str
)
1257 return rec_match (str
,
1262 "(" REC_URL_REGEXP
")"
1264 "(" REC_FILE_REGEXP
")"
1269 /* End of rec-int.c */