You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
3.1 KiB
181 lines
3.1 KiB
/*
|
|
* names.c db names
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
|
|
#include "names.h"
|
|
#include "utils.h"
|
|
|
|
#define MAX_ENTRIES 256
|
|
#define NAME_MAX_LEN 512
|
|
|
|
static int read_id_name(FILE *fp, int *id, char *name)
|
|
{
|
|
char buf[NAME_MAX_LEN];
|
|
int min, maj;
|
|
|
|
while (fgets(buf, sizeof(buf), fp)) {
|
|
char *p = buf;
|
|
|
|
while (*p == ' ' || *p == '\t')
|
|
p++;
|
|
|
|
if (*p == '#' || *p == '\n' || *p == 0)
|
|
continue;
|
|
|
|
if (sscanf(p, "%x:%x %s\n", &maj, &min, name) == 3) {
|
|
*id = (maj << 16) | min;
|
|
} else if (sscanf(p, "%x:%x %s #", &maj, &min, name) == 3) {
|
|
*id = (maj << 16) | min;
|
|
} else if (sscanf(p, "0x%x %s\n", id, name) != 2 &&
|
|
sscanf(p, "0x%x %s #", id, name) != 2 &&
|
|
sscanf(p, "%d %s\n", id, name) != 2 &&
|
|
sscanf(p, "%d %s #", id, name) != 2) {
|
|
strcpy(name, p);
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct db_names *db_names_alloc(void)
|
|
{
|
|
struct db_names *db;
|
|
|
|
db = calloc(1, sizeof(*db));
|
|
if (!db)
|
|
return NULL;
|
|
|
|
db->size = MAX_ENTRIES;
|
|
db->hash = calloc(db->size, sizeof(struct db_entry *));
|
|
|
|
return db;
|
|
}
|
|
|
|
int db_names_load(struct db_names *db, const char *path)
|
|
{
|
|
struct db_entry *entry;
|
|
FILE *fp;
|
|
int id;
|
|
char namebuf[NAME_MAX_LEN] = {0};
|
|
int ret = -1;
|
|
|
|
fp = fopen(path, "r");
|
|
if (!fp)
|
|
return -ENOENT;
|
|
|
|
while ((ret = read_id_name(fp, &id, &namebuf[0]))) {
|
|
if (ret == -1) {
|
|
fprintf(stderr, "Database %s is corrupted at %s\n",
|
|
path, namebuf);
|
|
goto Exit;
|
|
}
|
|
ret = -1;
|
|
|
|
if (id < 0)
|
|
continue;
|
|
|
|
entry = malloc(sizeof(*entry));
|
|
if (!entry)
|
|
goto Exit;
|
|
|
|
entry->name = strdup(namebuf);
|
|
if (!entry->name) {
|
|
free(entry);
|
|
goto Exit;
|
|
}
|
|
|
|
entry->id = id;
|
|
entry->next = db->hash[id & (db->size - 1)];
|
|
db->hash[id & (db->size - 1)] = entry;
|
|
}
|
|
ret = 0;
|
|
|
|
Exit:
|
|
fclose(fp);
|
|
return ret;
|
|
}
|
|
|
|
void db_names_free(struct db_names *db)
|
|
{
|
|
int i;
|
|
|
|
if (!db)
|
|
return;
|
|
|
|
for (i = 0; i < db->size; i++) {
|
|
struct db_entry *entry = db->hash[i];
|
|
|
|
while (entry) {
|
|
struct db_entry *next = entry->next;
|
|
|
|
free(entry->name);
|
|
free(entry);
|
|
entry = next;
|
|
}
|
|
}
|
|
|
|
free(db->hash);
|
|
free(db);
|
|
}
|
|
|
|
char *id_to_name(struct db_names *db, int id, char *name)
|
|
{
|
|
struct db_entry *entry;
|
|
|
|
if (!db)
|
|
return NULL;
|
|
|
|
entry = db->hash[id & (db->size - 1)];
|
|
while (entry && entry->id != id)
|
|
entry = entry->next;
|
|
|
|
if (entry) {
|
|
strncpy(name, entry->name, IDNAME_MAX);
|
|
return name;
|
|
}
|
|
|
|
snprintf(name, IDNAME_MAX, "%d", id);
|
|
return NULL;
|
|
}
|
|
|
|
int name_to_id(struct db_names *db, int *id, const char *name)
|
|
{
|
|
struct db_entry *entry;
|
|
int i;
|
|
|
|
if (!db)
|
|
return -1;
|
|
|
|
if (db->cached && strcmp(db->cached->name, name) == 0) {
|
|
*id = db->cached->id;
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; i < db->size; i++) {
|
|
entry = db->hash[i];
|
|
while (entry && strcmp(entry->name, name))
|
|
entry = entry->next;
|
|
|
|
if (entry) {
|
|
db->cached = entry;
|
|
*id = entry->id;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|