kod_management.c revision 258945
1#include <config.h> 2#include <string.h> 3#include <sys/types.h> 4#include <sys/stat.h> 5 6#include "kod_management.h" 7#include "log.h" 8#include "sntp-opts.h" 9#include "ntp_stdlib.h" 10//#define DEBUG 11 12int kod_init = 0, kod_db_cnt = 0; 13const char *kod_db_file; 14struct kod_entry **kod_db; /* array of pointers to kod_entry */ 15 16 17/* 18 * Search for a KOD entry 19 */ 20int 21search_entry ( 22 char *hostname, 23 struct kod_entry **dst 24 ) 25{ 26 register int a, b, resc = 0; 27 28 for (a = 0; a < kod_db_cnt; a++) 29 if (!strcmp(kod_db[a]->hostname, hostname)) 30 resc++; 31 32 if (!resc) { 33 *dst = NULL; 34 return 0; 35 } 36 37 *dst = emalloc(resc * sizeof(**dst)); 38 39 b = 0; 40 for (a = 0; a < kod_db_cnt; a++) 41 if (!strcmp(kod_db[a]->hostname, hostname)) { 42 (*dst)[b] = *kod_db[a]; 43 b++; 44 } 45 46 return resc; 47} 48 49 50void 51add_entry( 52 char *hostname, 53 char *type /* 4 bytes not \0 terminated */ 54 ) 55{ 56 int n; 57 struct kod_entry *pke; 58 59 pke = emalloc(sizeof(*pke)); 60 pke->timestamp = time(NULL); 61 memcpy(pke->type, type, 4); 62 pke->type[sizeof(pke->type) - 1] = '\0'; 63 strncpy(pke->hostname, hostname, 64 sizeof(pke->hostname)); 65 pke->hostname[sizeof(pke->hostname) - 1] = '\0'; 66 67 /* 68 * insert in address ("hostname") order to find duplicates 69 */ 70 for (n = 0; n < kod_db_cnt; n++) 71 if (strcmp(kod_db[n]->hostname, pke->hostname) >= 0) 72 break; 73 74 if (n < kod_db_cnt && 75 0 == strcmp(kod_db[n]->hostname, pke->hostname)) { 76 kod_db[n]->timestamp = pke->timestamp; 77 free(pke); 78 return; 79 } 80 81 kod_db_cnt++; 82 kod_db = erealloc(kod_db, kod_db_cnt * sizeof(kod_db[0])); 83 if (n != kod_db_cnt - 1) 84 memmove(&kod_db[n + 1], &kod_db[n], 85 sizeof(kod_db[0]) * ((kod_db_cnt - 1) - n)); 86 kod_db[n] = pke; 87} 88 89 90void 91delete_entry( 92 char *hostname, 93 char *type 94 ) 95{ 96 register int a; 97 98 for (a = 0; a < kod_db_cnt; a++) 99 if (!strcmp(kod_db[a]->hostname, hostname) 100 && !strcmp(kod_db[a]->type, type)) 101 break; 102 103 if (a == kod_db_cnt) 104 return; 105 106 free(kod_db[a]); 107 kod_db_cnt--; 108 109 if (a < kod_db_cnt) 110 memmove(&kod_db[a], &kod_db[a + 1], 111 (kod_db_cnt - a) * sizeof(kod_db[0])); 112} 113 114 115void 116write_kod_db(void) 117{ 118 FILE *db_s; 119 char *pch; 120 int dirmode; 121 register int a; 122 123 db_s = fopen(kod_db_file, "w"); 124 125 /* 126 * If opening fails, blindly attempt to create each directory 127 * in the path first, then retry the open. 128 */ 129 if (NULL == db_s && strlen(kod_db_file)) { 130 dirmode = S_IRUSR | S_IWUSR | S_IXUSR 131 | S_IRGRP | S_IXGRP 132 | S_IROTH | S_IXOTH; 133 pch = strchr(kod_db_file + 1, DIR_SEP); 134 while (NULL != pch) { 135 *pch = '\0'; 136 mkdir(kod_db_file, dirmode); 137 *pch = DIR_SEP; 138 pch = strchr(pch + 1, DIR_SEP); 139 } 140 db_s = fopen(kod_db_file, "w"); 141 } 142 143 if (NULL == db_s) { 144 msyslog(LOG_WARNING, "Can't open KOD db file %s for writing!", 145 kod_db_file); 146 147 return; 148 } 149 150 for (a = 0; a < kod_db_cnt; a++) { 151 fprintf(db_s, "%16.16llx %s %s\n", (unsigned long long) 152 kod_db[a]->timestamp, kod_db[a]->type, 153 kod_db[a]->hostname); 154 } 155 156 fflush(db_s); 157 fclose(db_s); 158} 159 160 161void 162kod_init_kod_db( 163 const char *db_file 164 ) 165{ 166 /* 167 * Max. of 254 characters for hostname, 10 for timestamp, 4 for 168 * kisscode, 2 for spaces, 1 for \n, and 1 for \0 169 */ 170 char fbuf[254+10+4+2+1+1]; 171 FILE *db_s; 172 int a, b, sepc, len; 173 unsigned long long ull; 174 char *str_ptr; 175 char error = 0; 176 177 atexit(write_kod_db); 178 179#ifdef DEBUG 180 printf("Initializing KOD DB...\n"); 181#endif 182 183 kod_db_file = estrdup(db_file); 184 185 186 db_s = fopen(db_file, "r"); 187 188 if (NULL == db_s) { 189 msyslog(LOG_WARNING, "kod_init_kod_db(): Cannot open KoD db file %s", 190 db_file); 191 192 return; 193 } 194 195 if (ENABLED_OPT(NORMALVERBOSE)) 196 printf("Starting to read KoD file %s...\n", db_file); 197 /* First let's see how many entries there are and check for right syntax */ 198 199 while (!feof(db_s) && NULL != fgets(fbuf, sizeof(fbuf), db_s)) { 200 201 /* ignore blank lines */ 202 if ('\n' == fbuf[0]) 203 continue; 204 205 sepc = 0; 206 len = strlen(fbuf); 207 for (a = 0; a < len; a++) { 208 if (' ' == fbuf[a]) 209 sepc++; 210 211 if ('\n' == fbuf[a]) { 212 if (sepc != 2) { 213 if (strcmp(db_file, "/dev/null")) 214 msyslog(LOG_DEBUG, 215 "Syntax error in KoD db file %s in line %i (missing space)", 216 db_file, 217 kod_db_cnt + 1); 218 fclose(db_s); 219 return; 220 } 221 sepc = 0; 222 kod_db_cnt++; 223 } 224 } 225 } 226 227 if (0 == kod_db_cnt) { 228#ifdef DEBUG 229 printf("KoD DB %s empty.\n", db_file); 230#endif 231 fclose(db_s); 232 return; 233 } 234 235#ifdef DEBUG 236 printf("KoD DB %s contains %d entries, reading...\n", db_file, kod_db_cnt); 237#endif 238 239 rewind(db_s); 240 241 kod_db = emalloc(sizeof(kod_db[0]) * kod_db_cnt); 242 243 /* Read contents of file */ 244 for (b = 0; 245 !feof(db_s) && !ferror(db_s) && b < kod_db_cnt; 246 b++) { 247 248 str_ptr = fgets(fbuf, sizeof(fbuf), db_s); 249 if (NULL == str_ptr) { 250 error = 1; 251 break; 252 } 253 254 /* ignore blank lines */ 255 if ('\n' == fbuf[0]) { 256 b--; 257 continue; 258 } 259 260 kod_db[b] = emalloc(sizeof(*kod_db[b])); 261 262 if (3 != sscanf(fbuf, "%llx %4s %254s", &ull, 263 kod_db[b]->type, kod_db[b]->hostname)) { 264 265 free(kod_db[b]); 266 kod_db[b] = NULL; 267 error = 1; 268 break; 269 } 270 271 kod_db[b]->timestamp = (time_t)ull; 272 } 273 274 if (ferror(db_s) || error) { 275 kod_db_cnt = b; 276 msyslog(LOG_WARNING, "An error occured while parsing the KoD db file %s", 277 db_file); 278 fclose(db_s); 279 280 return; 281 } 282 283 fclose(db_s); 284#ifdef DEBUG 285 for (a = 0; a < kod_db_cnt; a++) 286 printf("KoD entry %d: %s at %llx type %s\n", a, 287 kod_db[a]->hostname, 288 (unsigned long long)kod_db[a]->timestamp, 289 kod_db[a]->type); 290#endif 291} 292