| | 31 | inline GB_ERROR gb_transactable_type(GB_TYPES type, GBDATA *gbd) { |
| | 32 | GB_ERROR error = NULL; |
| | 33 | if (!GB_MAIN(gbd)->transaction) { |
| | 34 | error = "No running transaction"; |
| | 35 | } |
| | 36 | else if (GB_ARRAY_FLAGS(gbd).changed == GB_DELETED) { |
| | 37 | error = "Entry has been deleted"; |
| | 38 | } |
| | 39 | else { |
| | 40 | GB_TYPES gb_type = GB_TYPE(gbd); |
| | 41 | if (gb_type != type && (type != GB_STRING || GB_TYPE(gbd) != GB_LINK)) { |
| | 42 | error = GBS_global_string("type mismatch (want=%i, got=%i)", type, gb_type); |
| | 43 | } |
| | 44 | } |
| | 45 | if (error) { |
| | 46 | GBK_dump_backtrace(stderr, error); // it's a bug: none of the above errors should ever happen |
| | 47 | gb_assert(0); |
| | 48 | } |
| | 49 | return error; |
| | 50 | } |
| | 51 | inline GB_ERROR gb_type_writeable_to(GB_TYPES type, GBDATA *gbd) { |
| | 52 | GB_ERROR error = gb_transactable_type(type, gbd); |
| | 53 | if (!error) { |
| | 54 | if (GB_GET_SECURITY_WRITE(gbd) > GB_MAIN(gbd)->security_level) { |
| | 55 | error = gb_security_error(gbd); |
| | 56 | } |
| | 57 | } |
| | 58 | return error; |
| | 59 | } |
| | 60 | inline GB_ERROR gb_type_readable_from(GB_TYPES type, GBDATA *gbd) { |
| | 61 | return gb_transactable_type(type, gbd); |
| | 62 | } |
| | 63 | |
| | 64 | inline GB_ERROR error_with_dbentry(const char *action, GBDATA *gbd, GB_ERROR error) { |
| | 65 | const char *path = GB_get_db_path(gbd); |
| | 66 | return GBS_global_string("Can't %s '%s':\n%s", action, path, error); |
| | 67 | } |
| | 68 | |
| | 69 | |
| | 70 | #define RETURN_ERROR_IF_NOT_WRITEABLE_AS_TYPE(gbd, type) \ |
| | 71 | do { \ |
| | 72 | GB_ERROR error = gb_type_writeable_to(type, gbd); \ |
| | 73 | if (error) { \ |
| | 74 | return error_with_dbentry("write", gbd, error); \ |
| | 75 | } \ |
| | 76 | } while(0) |
| | 77 | |
| | 78 | #define EXPORT_ERROR_AND_RETURN_0_IF_NOT_READABLE_AS_TYPE(gbd, type) \ |
| | 79 | do { \ |
| | 80 | GB_ERROR error = gb_type_readable_from(type, gbd); \ |
| | 81 | if (error) { \ |
| | 82 | error = error_with_dbentry("read", gbd, error); \ |
| | 83 | GB_export_error(error); \ |
| | 84 | return 0; \ |
| | 85 | } \ |
| | 86 | } while(0) \ |
| | 87 | |
| | 88 | |
| 35 | | |
| 36 | | #define GB_TEST_READ(gbd, ty, error) \ |
| 37 | | do { \ |
| 38 | | GB_TEST_TRANSACTION(gbd); \ |
| 39 | | if (GB_ARRAY_FLAGS(gbd).changed == GB_DELETED) { \ |
| 40 | | GB_internal_errorf("%s: %s", error, "Entry is deleted !!"); \ |
| 41 | | return 0; } \ |
| 42 | | if (GB_TYPE(gbd) != ty && (ty != GB_STRING || GB_TYPE(gbd) == GB_LINK)) { \ |
| 43 | | GB_internal_errorf("%s: %s", error, "wrong type"); \ |
| 44 | | return 0; } \ |
| 45 | | } while (0) |
| 46 | | |
| 47 | | #define GB_TEST_WRITE(gbd, ty, gerror) \ |
| 48 | | do { \ |
| 49 | | GB_TEST_TRANSACTION(gbd); \ |
| 50 | | if (GB_ARRAY_FLAGS(gbd).changed == GB_DELETED) { \ |
| 51 | | GB_internal_errorf("%s: %s", gerror, "Entry is deleted !!"); \ |
| 52 | | return 0; } \ |
| 53 | | if (GB_TYPE(gbd) != ty && (ty != GB_STRING || GB_TYPE(gbd) != GB_LINK)) { \ |
| 54 | | GB_internal_errorf("%s: %s", gerror, "type conflict !!"); \ |
| 55 | | return 0; } \ |
| 56 | | if (GB_GET_SECURITY_WRITE(gbd)>GB_MAIN(gbd)->security_level) \ |
| 57 | | return gb_security_error(gbd); \ |
| 58 | | } while (0) |
| | 93 | #define GB_TEST_READ(gbd, type, ignored) EXPORT_ERROR_AND_RETURN_0_IF_NOT_READABLE_AS_TYPE(gbd, type) |
| | 94 | #define GB_TEST_WRITE(gbd, type, ignored) RETURN_ERROR_IF_NOT_WRITEABLE_AS_TYPE(gbd, type) |