names.c revision 8b90a9907ef361a25b55d31c2a8c372f4d632e99
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
22static 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
53struct 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
70int 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
109Exit:
110	fclose(fp);
111	return ret;
112}
113
114void 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
137char *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
157int 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