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 = calloc(1, sizeof(*db)); 58 if (!db) 59 return NULL; 60 61 db->size = MAX_ENTRIES; 62 db->hash = calloc(db->size, sizeof(struct db_entry *)); 63 64 return db; 65 } 66 67 int db_names_load(struct db_names *db, const char *path) 68 { 69 struct db_entry *entry; 70 FILE *fp; 71 int id; 72 char namebuf[NAME_MAX_LEN] = {0}; 73 int ret = -1; 74 75 fp = fopen(path, "r"); 76 if (!fp) 77 return -ENOENT; 78 79 while ((ret = read_id_name(fp, &id, &namebuf[0]))) { 80 if (ret == -1) { 81 fprintf(stderr, "Database %s is corrupted at %s\n", 82 path, namebuf); 83 goto Exit; 84 } 85 ret = -1; 86 87 if (id < 0) 88 continue; 89 90 entry = malloc(sizeof(*entry)); 91 if (!entry) 92 goto Exit; 93 94 entry->name = strdup(namebuf); 95 if (!entry->name) { 96 free(entry); 97 goto Exit; 98 } 99 100 entry->id = id; 101 entry->next = db->hash[id & (db->size - 1)]; 102 db->hash[id & (db->size - 1)] = entry; 103 } 104 ret = 0; 105 106 Exit: 107 fclose(fp); 108 return ret; 109 } 110 111 void db_names_free(struct db_names *db) 112 { 113 int i; 114 115 if (!db) 116 return; 117 118 for (i = 0; i < db->size; i++) { 119 struct db_entry *entry = db->hash[i]; 120 121 while (entry) { 122 struct db_entry *next = entry->next; 123 124 free(entry->name); 125 free(entry); 126 entry = next; 127 } 128 } 129 130 free(db->hash); 131 free(db); 132 } 133 134 char *id_to_name(struct db_names *db, int id, char *name) 135 { 136 struct db_entry *entry; 137 138 if (!db) 139 return NULL; 140 141 entry = db->hash[id & (db->size - 1)]; 142 while (entry && entry->id != id) 143 entry = entry->next; 144 145 if (entry) { 146 strncpy(name, entry->name, IDNAME_MAX); 147 return name; 148 } 149 150 snprintf(name, IDNAME_MAX, "%d", id); 151 return NULL; 152 } 153 154 int name_to_id(struct db_names *db, int *id, const char *name) 155 { 156 struct db_entry *entry; 157 int i; 158 159 if (!db) 160 return -1; 161 162 if (db->cached && strcmp(db->cached->name, name) == 0) { 163 *id = db->cached->id; 164 return 0; 165 } 166 167 for (i = 0; i < db->size; i++) { 168 entry = db->hash[i]; 169 while (entry && strcmp(entry->name, name)) 170 entry = entry->next; 171 172 if (entry) { 173 db->cached = entry; 174 *id = entry->id; 175 return 0; 176 } 177 } 178 179 return -1; 180 } 181