mirror of
				https://git.proxmox.com/git/mirror_iproute2
				synced 2025-11-04 02:56:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			153 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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;
 | 
						|
}
 |