1 /* 2 * names.c db names 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 */ 10 11 #include <stdio.h> 12 #include <string.h> 13 #include <stdlib.h> 14 #include <errno.h> 15 16 #include "names.h" 17 #include "utils.h" 18 19 #define MAX_ENTRIES 256 20 #define NAME_MAX_LEN 512 21 22 static int read_id_name(FILE *fp, int *id, char *name) 23 { 24 char buf[NAME_MAX_LEN]; 25 int min, maj; 26 27 while (fgets(buf, sizeof(buf), fp)) { 28 char *p = buf; 29 30 while (*p == ' ' || *p == '\t') 31 p++; 32 33 if (*p == '#' || *p == '\n' || *p == 0) 34 continue; 35 36 if (sscanf(p, "%x:%x %s\n", &maj, &min, name) == 3) { 37 *id = (maj << 16) | min; 38 } else if (sscanf(p, "%x:%x %s #", &maj, &min, name) == 3) { 39 *id = (maj << 16) | min; 40 } else if (sscanf(p, "0x%x %s\n", id, name) != 2 && 41 sscanf(p, "0x%x %s #", id, name) != 2 && 42 sscanf(p, "%d %s\n", id, name) != 2 && 43 sscanf(p, "%d %s #", id, name) != 2) { 44 strcpy(name, p); 45 return -1; 46 } 47 return 1; 48 } 49 50 return 0; 51 } 52 53 struct db_names *db_names_alloc(void) 54 { 55 struct db_names *db; 56 57 db = malloc(sizeof(*db)); 58 if (!db) 59 return NULL; 60 61 memset(db, 0, sizeof(*db)); 62 63 db->size = MAX_ENTRIES; 64 db->hash = malloc(sizeof(struct db_entry *) * db->size); 65 memset(db->hash, 0, sizeof(struct db_entry *) * db->size); 66 67 return db; 68 } 69 70 int db_names_load(struct db_names *db, const char *path) 71 { 72 struct db_entry *entry; 73 FILE *fp; 74 int id; 75 char namebuf[NAME_MAX_LEN] = {0}; 76 int ret = -1; 77 78 fp = fopen(path, "r"); 79 if (!fp) 80 return -ENOENT; 81 82 while ((ret = read_id_name(fp, &id, &namebuf[0]))) { 83 if (ret == -1) { 84 fprintf(stderr, "Database %s is corrupted at %s\n", 85 path, namebuf); 86 goto Exit; 87 } 88 ret = -1; 89 90 if (id < 0) 91 continue; 92 93 entry = malloc(sizeof(*entry)); 94 if (!entry) 95 goto Exit; 96 97 entry->name = strdup(namebuf); 98 if (!entry->name) { 99 free(entry); 100 goto Exit; 101 } 102 103 entry->id = id; 104 entry->next = db->hash[id & (db->size - 1)]; 105 db->hash[id & (db->size - 1)] = entry; 106 } 107 ret = 0; 108 109 Exit: 110 fclose(fp); 111 return ret; 112 } 113 114 void db_names_free(struct db_names *db) 115 { 116 int i; 117 118 if (!db) 119 return; 120 121 for (i = 0; i < db->size; i++) { 122 struct db_entry *entry = db->hash[i]; 123 124 while (entry) { 125 struct db_entry *next = entry->next; 126 127 free(entry->name); 128 free(entry); 129 entry = next; 130 } 131 } 132 133 free(db->hash); 134 free(db); 135 } 136 137 char *id_to_name(struct db_names *db, int id, char *name) 138 { 139 struct db_entry *entry; 140 141 if (!db) 142 return NULL; 143 144 entry = db->hash[id & (db->size - 1)]; 145 while (entry && entry->id != id) 146 entry = entry->next; 147 148 if (entry) { 149 strncpy(name, entry->name, IDNAME_MAX); 150 return name; 151 } 152 153 snprintf(name, IDNAME_MAX, "%d", id); 154 return NULL; 155 } 156 157 int name_to_id(struct db_names *db, int *id, const char *name) 158 { 159 struct db_entry *entry; 160 int i; 161 162 if (!db) 163 return -1; 164 165 if (db->cached && strcmp(db->cached->name, name) == 0) { 166 *id = db->cached->id; 167 return 0; 168 } 169 170 for (i = 0; i < db->size; i++) { 171 entry = db->hash[i]; 172 while (entry && strcmp(entry->name, name)) 173 entry = entry->next; 174 175 if (entry) { 176 db->cached = entry; 177 *id = entry->id; 178 return 0; 179 } 180 } 181 182 return -1; 183 } 184