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 = 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 
     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 
    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 
    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 
    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