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