Home | History | Annotate | Download | only in lib
      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 
     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 
     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 
     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 
    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 
    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 
    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