structvar.c (6216B)
1 /* Copyright (c) 2001 Matej Pfajfar. 2 * Copyright (c) 2001-2004, Roger Dingledine. 3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 4 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 5 /* See LICENSE for licensing information */ 6 7 /** 8 * @file structvar.c 9 * @brief Functions to manipulate named and typed elements of 10 * a structure. 11 * 12 * These functions represent a low-level API for accessing a member of a 13 * structure. They use typedvar.c to work, and they are used in turn by the 14 * configuration system to examine and set fields in configuration objects 15 * used by individual modules. 16 * 17 * Almost no code should call these directly. 18 **/ 19 20 #include "orconfig.h" 21 #include "lib/confmgt/structvar.h" 22 #include "lib/cc/compat_compiler.h" 23 #include "lib/conf/conftypes.h" 24 #include "lib/confmgt/type_defs.h" 25 #include "lib/confmgt/typedvar.h" 26 #include "lib/log/util_bug.h" 27 28 #include "lib/confmgt/var_type_def_st.h" 29 30 #include <stddef.h> 31 32 /** 33 * Return true iff all fields on <b>decl</b> are NULL or 0, indicating that 34 * there is no object or no magic number to check. 35 **/ 36 static inline bool 37 magic_is_null(const struct_magic_decl_t *decl) 38 { 39 return decl->typename == NULL && 40 decl->magic_offset == 0 && 41 decl->magic_val == 0; 42 } 43 44 /** 45 * Set the 'magic number' on <b>object</b> to correspond to decl. 46 **/ 47 void 48 struct_set_magic(void *object, const struct_magic_decl_t *decl) 49 { 50 tor_assert(decl); 51 if (magic_is_null(decl)) 52 return; 53 54 tor_assert(object); 55 uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset); 56 *ptr = decl->magic_val; 57 } 58 59 /** 60 * Assert that the 'magic number' on <b>object</b> to corresponds to decl. 61 **/ 62 void 63 struct_check_magic(const void *object, const struct_magic_decl_t *decl) 64 { 65 tor_assert(decl); 66 if (magic_is_null(decl)) 67 return; 68 69 tor_assert(object); 70 71 const uint32_t *ptr = STRUCT_VAR_P(object, decl->magic_offset); 72 tor_assertf(*ptr == decl->magic_val, 73 "Bad magic number on purported %s object. " 74 "Expected %"PRIu32"x but got %"PRIu32"x.", 75 decl->typename, decl->magic_val, *ptr); 76 } 77 78 /** 79 * Return a mutable pointer to the member of <b>object</b> described 80 * by <b>member</b>. 81 **/ 82 void * 83 struct_get_mptr(void *object, const struct_member_t *member) 84 { 85 tor_assert(object); 86 return STRUCT_VAR_P(object, member->offset); 87 } 88 89 /** 90 * Return a const pointer to the member of <b>object</b> described 91 * by <b>member</b>. 92 **/ 93 const void * 94 struct_get_ptr(const void *object, const struct_member_t *member) 95 { 96 tor_assert(object); 97 return STRUCT_VAR_P(object, member->offset); 98 } 99 100 /** 101 * Helper: given a struct_member_t, look up the type definition for its 102 * variable. 103 */ 104 static const var_type_def_t * 105 get_type_def(const struct_member_t *member) 106 { 107 if (member->type_def) 108 return member->type_def; 109 110 return lookup_type_def(member->type); 111 } 112 113 /** 114 * (As typed_var_free, but free and clear the member of <b>object</b> defined 115 * by <b>member</b>.) 116 **/ 117 void 118 struct_var_free(void *object, const struct_member_t *member) 119 { 120 void *p = struct_get_mptr(object, member); 121 const var_type_def_t *def = get_type_def(member); 122 123 typed_var_free(p, def); 124 } 125 126 /** 127 * (As typed_var_copy, but copy from <b>src</b> to <b>dest</b> the member 128 * defined by <b>member</b>.) 129 **/ 130 int 131 struct_var_copy(void *dest, const void *src, const struct_member_t *member) 132 { 133 void *p_dest = struct_get_mptr(dest, member); 134 const void *p_src = struct_get_ptr(src, member); 135 const var_type_def_t *def = get_type_def(member); 136 137 return typed_var_copy(p_dest, p_src, def); 138 } 139 140 /** 141 * (As typed_var_eq, but compare the members of <b>a</b> and <b>b</b> 142 * defined by <b>member</b>.) 143 **/ 144 bool 145 struct_var_eq(const void *a, const void *b, const struct_member_t *member) 146 { 147 const void *p_a = struct_get_ptr(a, member); 148 const void *p_b = struct_get_ptr(b, member); 149 const var_type_def_t *def = get_type_def(member); 150 151 return typed_var_eq(p_a, p_b, def); 152 } 153 154 /** 155 * (As typed_var_ok, but validate the member of <b>object</b> defined by 156 * <b>member</b>.) 157 **/ 158 bool 159 struct_var_ok(const void *object, const struct_member_t *member) 160 { 161 const void *p = struct_get_ptr(object, member); 162 const var_type_def_t *def = get_type_def(member); 163 164 return typed_var_ok(p, def); 165 } 166 167 /** 168 * (As typed_var_kvassign, but assign a value to the member of <b>object</b> 169 * defined by <b>member</b>.) 170 **/ 171 int 172 struct_var_kvassign(void *object, const struct config_line_t *line, 173 char **errmsg, 174 const struct_member_t *member) 175 { 176 void *p = struct_get_mptr(object, member); 177 const var_type_def_t *def = get_type_def(member); 178 179 return typed_var_kvassign(p, line, errmsg, def); 180 } 181 182 /** 183 * (As typed_var_kvencode, but encode the value of the member of <b>object</b> 184 * defined by <b>member</b>.) 185 **/ 186 struct config_line_t * 187 struct_var_kvencode(const void *object, const struct_member_t *member) 188 { 189 const void *p = struct_get_ptr(object, member); 190 const var_type_def_t *def = get_type_def(member); 191 192 return typed_var_kvencode(member->name, p, def); 193 } 194 195 /** 196 * Mark the field in <b>object</b> determined by <b>member</b> -- a variable 197 * that ordinarily would be extended by assignment -- as "fragile", so that it 198 * will get replaced by the next assignment instead. 199 */ 200 void 201 struct_var_mark_fragile(void *object, const struct_member_t *member) 202 { 203 void *p = struct_get_mptr(object, member); 204 const var_type_def_t *def = get_type_def(member); 205 return typed_var_mark_fragile(p, def); 206 } 207 208 /** 209 * Return the official name of this struct member. 210 **/ 211 const char * 212 struct_var_get_name(const struct_member_t *member) 213 { 214 return member->name; 215 } 216 217 /** 218 * Return the type name for this struct member. 219 * 220 * Do not use the output of this function to inspect a type within Tor. It is 221 * suitable for debugging, informing the controller or user of a variable's 222 * type, etc. 223 **/ 224 const char * 225 struct_var_get_typename(const struct_member_t *member) 226 { 227 const var_type_def_t *def = get_type_def(member); 228 229 return def ? def->name : NULL; 230 } 231 232 /** Return all of the flags set for this struct member. */ 233 uint32_t 234 struct_var_get_flags(const struct_member_t *member) 235 { 236 const var_type_def_t *def = get_type_def(member); 237 238 return def ? def->flags : 0; 239 }