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
read_id_name(FILE * fp,int * id,char * name)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
db_names_alloc(void)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
db_names_load(struct db_names * db,const char * path)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
db_names_free(struct db_names * db)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
id_to_name(struct db_names * db,int id,char * name)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
name_to_id(struct db_names * db,int * id,const char * name)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