1*7f2fe78bSCy Schubert /* 2*7f2fe78bSCy Schubert * prof-int.h 3*7f2fe78bSCy Schubert */ 4*7f2fe78bSCy Schubert 5*7f2fe78bSCy Schubert #include "k5-platform.h" 6*7f2fe78bSCy Schubert #include "k5-thread.h" 7*7f2fe78bSCy Schubert #include "k5-plugin.h" 8*7f2fe78bSCy Schubert 9*7f2fe78bSCy Schubert #include <time.h> 10*7f2fe78bSCy Schubert 11*7f2fe78bSCy Schubert #if defined(__MACH__) && defined(__APPLE__) 12*7f2fe78bSCy Schubert #include <TargetConditionals.h> 13*7f2fe78bSCy Schubert #define PROFILE_SUPPORTS_FOREIGN_NEWLINES 14*7f2fe78bSCy Schubert #endif 15*7f2fe78bSCy Schubert 16*7f2fe78bSCy Schubert #include "com_err.h" 17*7f2fe78bSCy Schubert #include "profile.h" 18*7f2fe78bSCy Schubert 19*7f2fe78bSCy Schubert typedef long prf_magic_t; 20*7f2fe78bSCy Schubert 21*7f2fe78bSCy Schubert /* 22*7f2fe78bSCy Schubert * This is the structure which stores the profile information for a 23*7f2fe78bSCy Schubert * particular configuration file. 24*7f2fe78bSCy Schubert * 25*7f2fe78bSCy Schubert * Locking strategy: 26*7f2fe78bSCy Schubert * - filespec, fslen are fixed after creation 27*7f2fe78bSCy Schubert * - refcount and next should only be tweaked with the global lock held 28*7f2fe78bSCy Schubert * - other fields can be tweaked after grabbing the in-struct lock 29*7f2fe78bSCy Schubert */ 30*7f2fe78bSCy Schubert struct _prf_data_t { 31*7f2fe78bSCy Schubert prf_magic_t magic; 32*7f2fe78bSCy Schubert k5_mutex_t lock; 33*7f2fe78bSCy Schubert struct profile_node *root; 34*7f2fe78bSCy Schubert time_t last_stat; 35*7f2fe78bSCy Schubert time_t timestamp; /* time tree was last updated from file */ 36*7f2fe78bSCy Schubert unsigned long frac_ts; /* fractional part of timestamp, if any */ 37*7f2fe78bSCy Schubert int flags; /* r/w, dirty */ 38*7f2fe78bSCy Schubert int upd_serial; /* incremented when data changes */ 39*7f2fe78bSCy Schubert 40*7f2fe78bSCy Schubert size_t fslen; 41*7f2fe78bSCy Schubert 42*7f2fe78bSCy Schubert /* Some separation between fields controlled by different 43*7f2fe78bSCy Schubert mutexes. Theoretically, both could be accessed at the same 44*7f2fe78bSCy Schubert time from different threads on different CPUs with separate 45*7f2fe78bSCy Schubert caches. Don't let the threads clobber each other's 46*7f2fe78bSCy Schubert changes. One mutex controlling the whole thing would be 47*7f2fe78bSCy Schubert better, but sufficient separation might suffice. 48*7f2fe78bSCy Schubert 49*7f2fe78bSCy Schubert This is icky. I just hope it's adequate. 50*7f2fe78bSCy Schubert 51*7f2fe78bSCy Schubert For next major release, fix this. */ 52*7f2fe78bSCy Schubert union { double d; void *p; uint64_t ll; k5_mutex_t m; } pad; 53*7f2fe78bSCy Schubert 54*7f2fe78bSCy Schubert int refcount; /* prf_file_t references */ 55*7f2fe78bSCy Schubert struct _prf_data_t *next; 56*7f2fe78bSCy Schubert /* Was: "profile_filespec_t filespec". Now: flexible char 57*7f2fe78bSCy Schubert array ... except, we need to work in C89, so an array 58*7f2fe78bSCy Schubert length must be specified. */ 59*7f2fe78bSCy Schubert const char filespec[sizeof("/etc/krb5.conf")]; 60*7f2fe78bSCy Schubert }; 61*7f2fe78bSCy Schubert 62*7f2fe78bSCy Schubert typedef struct _prf_data_t *prf_data_t; 63*7f2fe78bSCy Schubert prf_data_t profile_make_prf_data(const char *); 64*7f2fe78bSCy Schubert 65*7f2fe78bSCy Schubert struct _prf_file_t { 66*7f2fe78bSCy Schubert prf_magic_t magic; 67*7f2fe78bSCy Schubert struct _prf_data_t *data; 68*7f2fe78bSCy Schubert struct _prf_file_t *next; 69*7f2fe78bSCy Schubert }; 70*7f2fe78bSCy Schubert 71*7f2fe78bSCy Schubert typedef struct _prf_file_t *prf_file_t; 72*7f2fe78bSCy Schubert 73*7f2fe78bSCy Schubert /* 74*7f2fe78bSCy Schubert * The profile flags 75*7f2fe78bSCy Schubert */ 76*7f2fe78bSCy Schubert #define PROFILE_FILE_NO_RELOAD 0x0001 77*7f2fe78bSCy Schubert #define PROFILE_FILE_DIRTY 0x0002 78*7f2fe78bSCy Schubert #define PROFILE_FILE_SHARED 0x0004 79*7f2fe78bSCy Schubert 80*7f2fe78bSCy Schubert struct _prf_lib_handle_t { 81*7f2fe78bSCy Schubert k5_mutex_t lock; 82*7f2fe78bSCy Schubert int refcount; 83*7f2fe78bSCy Schubert struct plugin_file_handle *plugin_handle; 84*7f2fe78bSCy Schubert }; 85*7f2fe78bSCy Schubert 86*7f2fe78bSCy Schubert typedef struct _prf_lib_handle_t *prf_lib_handle_t; 87*7f2fe78bSCy Schubert 88*7f2fe78bSCy Schubert /* 89*7f2fe78bSCy Schubert * This structure defines the high-level, user visible profile_t 90*7f2fe78bSCy Schubert * object, which is used as a handle by users who need to query some 91*7f2fe78bSCy Schubert * configuration file(s) 92*7f2fe78bSCy Schubert */ 93*7f2fe78bSCy Schubert struct _profile_t { 94*7f2fe78bSCy Schubert prf_magic_t magic; 95*7f2fe78bSCy Schubert prf_file_t first_file; 96*7f2fe78bSCy Schubert 97*7f2fe78bSCy Schubert /* If non-null, use vtable operations instead of native ones. */ 98*7f2fe78bSCy Schubert struct profile_vtable *vt; 99*7f2fe78bSCy Schubert void *cbdata; 100*7f2fe78bSCy Schubert prf_lib_handle_t lib_handle; 101*7f2fe78bSCy Schubert }; 102*7f2fe78bSCy Schubert 103*7f2fe78bSCy Schubert /* 104*7f2fe78bSCy Schubert * Used by the profile iterator in prof_get.c 105*7f2fe78bSCy Schubert */ 106*7f2fe78bSCy Schubert #define PROFILE_ITER_LIST_SECTION 0x0001 107*7f2fe78bSCy Schubert #define PROFILE_ITER_SECTIONS_ONLY 0x0002 108*7f2fe78bSCy Schubert #define PROFILE_ITER_RELATIONS_ONLY 0x0004 109*7f2fe78bSCy Schubert 110*7f2fe78bSCy Schubert #define PROFILE_ITER_FINAL_SEEN 0x0100 111*7f2fe78bSCy Schubert 112*7f2fe78bSCy Schubert /* 113*7f2fe78bSCy Schubert * Check if a filespec is last in a list (NULL on UNIX, invalid FSSpec on MacOS 114*7f2fe78bSCy Schubert */ 115*7f2fe78bSCy Schubert 116*7f2fe78bSCy Schubert #define PROFILE_LAST_FILESPEC(x) (((x) == NULL) || ((x)[0] == '\0')) 117*7f2fe78bSCy Schubert 118*7f2fe78bSCy Schubert /* profile_parse.c */ 119*7f2fe78bSCy Schubert 120*7f2fe78bSCy Schubert errcode_t profile_parse_file 121*7f2fe78bSCy Schubert (FILE *f, struct profile_node **root, char **ret_modspec); 122*7f2fe78bSCy Schubert 123*7f2fe78bSCy Schubert errcode_t profile_process_directory 124*7f2fe78bSCy Schubert (const char *dirname, struct profile_node **root); 125*7f2fe78bSCy Schubert 126*7f2fe78bSCy Schubert errcode_t profile_write_tree_file 127*7f2fe78bSCy Schubert (struct profile_node *root, FILE *dstfile); 128*7f2fe78bSCy Schubert 129*7f2fe78bSCy Schubert errcode_t profile_write_tree_to_buffer 130*7f2fe78bSCy Schubert (struct profile_node *root, char **buf); 131*7f2fe78bSCy Schubert 132*7f2fe78bSCy Schubert 133*7f2fe78bSCy Schubert /* prof_tree.c */ 134*7f2fe78bSCy Schubert 135*7f2fe78bSCy Schubert void profile_free_node 136*7f2fe78bSCy Schubert (struct profile_node *relation); 137*7f2fe78bSCy Schubert 138*7f2fe78bSCy Schubert errcode_t profile_create_node 139*7f2fe78bSCy Schubert (const char *name, const char *value, 140*7f2fe78bSCy Schubert struct profile_node **ret_node); 141*7f2fe78bSCy Schubert 142*7f2fe78bSCy Schubert errcode_t profile_verify_node 143*7f2fe78bSCy Schubert (struct profile_node *node); 144*7f2fe78bSCy Schubert 145*7f2fe78bSCy Schubert errcode_t profile_add_node 146*7f2fe78bSCy Schubert (struct profile_node *section, 147*7f2fe78bSCy Schubert const char *name, const char *value, 148*7f2fe78bSCy Schubert struct profile_node **ret_node); 149*7f2fe78bSCy Schubert 150*7f2fe78bSCy Schubert errcode_t profile_make_node_final 151*7f2fe78bSCy Schubert (struct profile_node *node); 152*7f2fe78bSCy Schubert 153*7f2fe78bSCy Schubert int profile_is_node_final 154*7f2fe78bSCy Schubert (struct profile_node *node); 155*7f2fe78bSCy Schubert 156*7f2fe78bSCy Schubert const char *profile_get_node_name 157*7f2fe78bSCy Schubert (struct profile_node *node); 158*7f2fe78bSCy Schubert 159*7f2fe78bSCy Schubert const char *profile_get_node_value 160*7f2fe78bSCy Schubert (struct profile_node *node); 161*7f2fe78bSCy Schubert 162*7f2fe78bSCy Schubert errcode_t profile_find_node 163*7f2fe78bSCy Schubert (struct profile_node *section, 164*7f2fe78bSCy Schubert const char *name, const char *value, 165*7f2fe78bSCy Schubert int section_flag, void **state, 166*7f2fe78bSCy Schubert struct profile_node **node); 167*7f2fe78bSCy Schubert 168*7f2fe78bSCy Schubert errcode_t profile_find_node_relation 169*7f2fe78bSCy Schubert (struct profile_node *section, 170*7f2fe78bSCy Schubert const char *name, void **state, 171*7f2fe78bSCy Schubert char **ret_name, char **value); 172*7f2fe78bSCy Schubert 173*7f2fe78bSCy Schubert errcode_t profile_find_node_subsection 174*7f2fe78bSCy Schubert (struct profile_node *section, 175*7f2fe78bSCy Schubert const char *name, void **state, 176*7f2fe78bSCy Schubert char **ret_name, struct profile_node **subsection); 177*7f2fe78bSCy Schubert 178*7f2fe78bSCy Schubert errcode_t profile_get_node_parent 179*7f2fe78bSCy Schubert (struct profile_node *section, 180*7f2fe78bSCy Schubert struct profile_node **parent); 181*7f2fe78bSCy Schubert 182*7f2fe78bSCy Schubert errcode_t profile_delete_node_relation 183*7f2fe78bSCy Schubert (struct profile_node *section, const char *name); 184*7f2fe78bSCy Schubert 185*7f2fe78bSCy Schubert errcode_t profile_find_node_name 186*7f2fe78bSCy Schubert (struct profile_node *section, void **state, 187*7f2fe78bSCy Schubert char **ret_name); 188*7f2fe78bSCy Schubert 189*7f2fe78bSCy Schubert errcode_t profile_node_iterator_create 190*7f2fe78bSCy Schubert (profile_t profile, const char *const *names, 191*7f2fe78bSCy Schubert int flags, void **ret_iter); 192*7f2fe78bSCy Schubert 193*7f2fe78bSCy Schubert void profile_node_iterator_free 194*7f2fe78bSCy Schubert (void **iter_p); 195*7f2fe78bSCy Schubert 196*7f2fe78bSCy Schubert errcode_t profile_node_iterator 197*7f2fe78bSCy Schubert (void **iter_p, struct profile_node **ret_node, 198*7f2fe78bSCy Schubert char **ret_name, char **ret_value); 199*7f2fe78bSCy Schubert 200*7f2fe78bSCy Schubert errcode_t profile_remove_node 201*7f2fe78bSCy Schubert (struct profile_node *node); 202*7f2fe78bSCy Schubert 203*7f2fe78bSCy Schubert errcode_t profile_set_relation_value 204*7f2fe78bSCy Schubert (struct profile_node *node, const char *new_value); 205*7f2fe78bSCy Schubert 206*7f2fe78bSCy Schubert errcode_t profile_rename_node 207*7f2fe78bSCy Schubert (struct profile_node *node, const char *new_name); 208*7f2fe78bSCy Schubert 209*7f2fe78bSCy Schubert /* prof_file.c */ 210*7f2fe78bSCy Schubert 211*7f2fe78bSCy Schubert errcode_t KRB5_CALLCONV profile_copy (profile_t, profile_t *); 212*7f2fe78bSCy Schubert 213*7f2fe78bSCy Schubert errcode_t profile_open_file 214*7f2fe78bSCy Schubert (const_profile_filespec_t file, prf_file_t *ret_prof, 215*7f2fe78bSCy Schubert char **ret_modspec); 216*7f2fe78bSCy Schubert 217*7f2fe78bSCy Schubert #define profile_update_file(P, M) profile_update_file_data((P)->data, M) 218*7f2fe78bSCy Schubert errcode_t profile_update_file_data 219*7f2fe78bSCy Schubert (prf_data_t profile, char **ret_modspec); 220*7f2fe78bSCy Schubert #define profile_update_file_locked(P, M) profile_update_file_data_locked((P)->data, M) 221*7f2fe78bSCy Schubert errcode_t profile_update_file_data_locked 222*7f2fe78bSCy Schubert (prf_data_t data, char **ret_modspec); 223*7f2fe78bSCy Schubert 224*7f2fe78bSCy Schubert #define profile_flush_file(P) (((P) && (P)->magic == PROF_MAGIC_FILE) ? profile_flush_file_data((P)->data) : PROF_MAGIC_FILE) 225*7f2fe78bSCy Schubert errcode_t profile_flush_file_data 226*7f2fe78bSCy Schubert (prf_data_t data); 227*7f2fe78bSCy Schubert 228*7f2fe78bSCy Schubert #define profile_flush_file_to_file(P,F) (((P) && (P)->magic == PROF_MAGIC_FILE) ? profile_flush_file_data_to_file((P)->data, (F)) : PROF_MAGIC_FILE) 229*7f2fe78bSCy Schubert errcode_t profile_flush_file_data_to_file 230*7f2fe78bSCy Schubert (prf_data_t data, const char *outfile); 231*7f2fe78bSCy Schubert 232*7f2fe78bSCy Schubert errcode_t profile_flush_file_data_to_buffer 233*7f2fe78bSCy Schubert (prf_data_t data, char **bufp); 234*7f2fe78bSCy Schubert 235*7f2fe78bSCy Schubert void profile_free_file 236*7f2fe78bSCy Schubert (prf_file_t profile); 237*7f2fe78bSCy Schubert 238*7f2fe78bSCy Schubert errcode_t profile_close_file 239*7f2fe78bSCy Schubert (prf_file_t profile); 240*7f2fe78bSCy Schubert 241*7f2fe78bSCy Schubert int profile_file_is_writable 242*7f2fe78bSCy Schubert (prf_file_t profile); 243*7f2fe78bSCy Schubert 244*7f2fe78bSCy Schubert void profile_dereference_data (prf_data_t); 245*7f2fe78bSCy Schubert void profile_dereference_data_locked (prf_data_t); 246*7f2fe78bSCy Schubert 247*7f2fe78bSCy Schubert void profile_lock_global (void); 248*7f2fe78bSCy Schubert void profile_unlock_global (void); 249*7f2fe78bSCy Schubert 250*7f2fe78bSCy Schubert /* prof_init.c -- included from profile.h */ 251*7f2fe78bSCy Schubert errcode_t profile_ser_size 252*7f2fe78bSCy Schubert (const char *, profile_t, size_t *); 253*7f2fe78bSCy Schubert 254*7f2fe78bSCy Schubert errcode_t profile_ser_externalize 255*7f2fe78bSCy Schubert (const char *, profile_t, unsigned char **, size_t *); 256*7f2fe78bSCy Schubert 257*7f2fe78bSCy Schubert errcode_t profile_ser_internalize 258*7f2fe78bSCy Schubert (const char *, profile_t *, unsigned char **, size_t *); 259*7f2fe78bSCy Schubert 260*7f2fe78bSCy Schubert /* prof_get.c */ 261*7f2fe78bSCy Schubert 262*7f2fe78bSCy Schubert errcode_t profile_get_value 263*7f2fe78bSCy Schubert (profile_t profile, const char **names, char **ret_value); 264*7f2fe78bSCy Schubert /* Others included from profile.h */ 265*7f2fe78bSCy Schubert 266*7f2fe78bSCy Schubert /* prof_set.c -- included from profile.h */ 267