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