brintos

brintos / linux-shallow public Read only

0
0
Text · 10.4 KiB · aba7f41 Raw
487 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *      names.c  --  USB name database manipulation routines4 *5 *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)6 *7 *	Copyright (C) 2005 Takahiro Hirofuchi8 *		- names_deinit() is added.9 */10 11#include <sys/types.h>12#include <sys/stat.h>13#include <fcntl.h>14#include <dirent.h>15#include <string.h>16#include <errno.h>17#include <stdlib.h>18#include <unistd.h>19#include <stdio.h>20#include <ctype.h>21 22#include "names.h"23#include "usbip_common.h"24 25struct vendor {26	struct vendor *next;27	u_int16_t vendorid;28	char name[1];29};30 31struct product {32	struct product *next;33	u_int16_t vendorid, productid;34	char name[1];35};36 37struct class {38	struct class *next;39	u_int8_t classid;40	char name[1];41};42 43struct subclass {44	struct subclass *next;45	u_int8_t classid, subclassid;46	char name[1];47};48 49struct protocol {50	struct protocol *next;51	u_int8_t classid, subclassid, protocolid;52	char name[1];53};54 55struct genericstrtable {56	struct genericstrtable *next;57	unsigned int num;58	char name[1];59};60 61 62#define HASH1  0x1063#define HASH2  0x0264#define HASHSZ 1665 66static unsigned int hashnum(unsigned int num)67{68	unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;69 70	for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)71		if (num & mask1)72			num ^= mask2;73	return num & (HASHSZ-1);74}75 76 77static struct vendor *vendors[HASHSZ] = { NULL, };78static struct product *products[HASHSZ] = { NULL, };79static struct class *classes[HASHSZ] = { NULL, };80static struct subclass *subclasses[HASHSZ] = { NULL, };81static struct protocol *protocols[HASHSZ] = { NULL, };82 83const char *names_vendor(u_int16_t vendorid)84{85	struct vendor *v;86 87	v = vendors[hashnum(vendorid)];88	for (; v; v = v->next)89		if (v->vendorid == vendorid)90			return v->name;91	return NULL;92}93 94const char *names_product(u_int16_t vendorid, u_int16_t productid)95{96	struct product *p;97 98	p = products[hashnum((vendorid << 16) | productid)];99	for (; p; p = p->next)100		if (p->vendorid == vendorid && p->productid == productid)101			return p->name;102	return NULL;103}104 105const char *names_class(u_int8_t classid)106{107	struct class *c;108 109	c = classes[hashnum(classid)];110	for (; c; c = c->next)111		if (c->classid == classid)112			return c->name;113	return NULL;114}115 116const char *names_subclass(u_int8_t classid, u_int8_t subclassid)117{118	struct subclass *s;119 120	s = subclasses[hashnum((classid << 8) | subclassid)];121	for (; s; s = s->next)122		if (s->classid == classid && s->subclassid == subclassid)123			return s->name;124	return NULL;125}126 127const char *names_protocol(u_int8_t classid, u_int8_t subclassid,128			   u_int8_t protocolid)129{130	struct protocol *p;131 132	p = protocols[hashnum((classid << 16) | (subclassid << 8)133			      | protocolid)];134	for (; p; p = p->next)135		if (p->classid == classid && p->subclassid == subclassid &&136		    p->protocolid == protocolid)137			return p->name;138	return NULL;139}140 141/* add a cleanup function by takahiro */142struct pool {143	struct pool *next;144	void *mem;145};146 147static struct pool *pool_head;148 149static void *my_malloc(size_t size)150{151	struct pool *p;152 153	p = calloc(1, sizeof(struct pool));154	if (!p)155		return NULL;156 157	p->mem = calloc(1, size);158	if (!p->mem) {159		free(p);160		return NULL;161	}162 163	p->next = pool_head;164	pool_head = p;165 166	return p->mem;167}168 169void names_free(void)170{171	struct pool *pool;172 173	if (!pool_head)174		return;175 176	for (pool = pool_head; pool != NULL; ) {177		struct pool *tmp;178 179		if (pool->mem)180			free(pool->mem);181 182		tmp = pool;183		pool = pool->next;184		free(tmp);185	}186}187 188static int new_vendor(const char *name, u_int16_t vendorid)189{190	struct vendor *v;191	unsigned int h = hashnum(vendorid);192 193	v = vendors[h];194	for (; v; v = v->next)195		if (v->vendorid == vendorid)196			return -1;197	v = my_malloc(sizeof(struct vendor) + strlen(name));198	if (!v)199		return -1;200	strcpy(v->name, name);201	v->vendorid = vendorid;202	v->next = vendors[h];203	vendors[h] = v;204	return 0;205}206 207static int new_product(const char *name, u_int16_t vendorid,208		       u_int16_t productid)209{210	struct product *p;211	unsigned int h = hashnum((vendorid << 16) | productid);212 213	p = products[h];214	for (; p; p = p->next)215		if (p->vendorid == vendorid && p->productid == productid)216			return -1;217	p = my_malloc(sizeof(struct product) + strlen(name));218	if (!p)219		return -1;220	strcpy(p->name, name);221	p->vendorid = vendorid;222	p->productid = productid;223	p->next = products[h];224	products[h] = p;225	return 0;226}227 228static int new_class(const char *name, u_int8_t classid)229{230	struct class *c;231	unsigned int h = hashnum(classid);232 233	c = classes[h];234	for (; c; c = c->next)235		if (c->classid == classid)236			return -1;237	c = my_malloc(sizeof(struct class) + strlen(name));238	if (!c)239		return -1;240	strcpy(c->name, name);241	c->classid = classid;242	c->next = classes[h];243	classes[h] = c;244	return 0;245}246 247static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)248{249	struct subclass *s;250	unsigned int h = hashnum((classid << 8) | subclassid);251 252	s = subclasses[h];253	for (; s; s = s->next)254		if (s->classid == classid && s->subclassid == subclassid)255			return -1;256	s = my_malloc(sizeof(struct subclass) + strlen(name));257	if (!s)258		return -1;259	strcpy(s->name, name);260	s->classid = classid;261	s->subclassid = subclassid;262	s->next = subclasses[h];263	subclasses[h] = s;264	return 0;265}266 267static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,268			u_int8_t protocolid)269{270	struct protocol *p;271	unsigned int h = hashnum((classid << 16) | (subclassid << 8)272				 | protocolid);273 274	p = protocols[h];275	for (; p; p = p->next)276		if (p->classid == classid && p->subclassid == subclassid277		    && p->protocolid == protocolid)278			return -1;279	p = my_malloc(sizeof(struct protocol) + strlen(name));280	if (!p)281		return -1;282	strcpy(p->name, name);283	p->classid = classid;284	p->subclassid = subclassid;285	p->protocolid = protocolid;286	p->next = protocols[h];287	protocols[h] = p;288	return 0;289}290 291static void parse(FILE *f)292{293	char buf[512], *cp;294	unsigned int linectr = 0;295	int lastvendor = -1;296	int lastclass = -1;297	int lastsubclass = -1;298	int lasthut = -1;299	int lastlang = -1;300	unsigned int u;301 302	while (fgets(buf, sizeof(buf), f)) {303		linectr++;304		/* remove line ends */305		cp = strchr(buf, '\r');306		if (cp)307			*cp = 0;308		cp = strchr(buf, '\n');309		if (cp)310			*cp = 0;311		if (buf[0] == '#' || !buf[0])312			continue;313		cp = buf;314		if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&315		    buf[3] == 'S' && buf[4] == 'D' &&316		    buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/317		    buf[7] == ' ') {318			continue;319		}320		if (buf[0] == 'P' && buf[1] == 'H' &&321		    buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {322			continue;323		}324		if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&325		    buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {326			continue;327		}328		if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {329			lasthut = lastclass = lastvendor = lastsubclass = -1;330			/*331			 * set 1 as pseudo-id to indicate that the parser is332			 * in a `L' section.333			 */334			lastlang = 1;335			continue;336		}337		if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {338			/* class spec */339			cp = buf+2;340			while (isspace(*cp))341				cp++;342			if (!isxdigit(*cp)) {343				err("Invalid class spec at line %u", linectr);344				continue;345			}346			u = strtoul(cp, &cp, 16);347			while (isspace(*cp))348				cp++;349			if (!*cp) {350				err("Invalid class spec at line %u", linectr);351				continue;352			}353			if (new_class(cp, u))354				err("Duplicate class spec at line %u class %04x %s",355				    linectr, u, cp);356			dbg("line %5u class %02x %s", linectr, u, cp);357			lasthut = lastlang = lastvendor = lastsubclass = -1;358			lastclass = u;359			continue;360		}361		if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {362			/* audio terminal type spec */363			continue;364		}365		if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'366		    && isspace(buf[3])) {367			/* HID Descriptor bCountryCode */368			continue;369		}370		if (isxdigit(*cp)) {371			/* vendor */372			u = strtoul(cp, &cp, 16);373			while (isspace(*cp))374				cp++;375			if (!*cp) {376				err("Invalid vendor spec at line %u", linectr);377				continue;378			}379			if (new_vendor(cp, u))380				err("Duplicate vendor spec at line %u vendor %04x %s",381				    linectr, u, cp);382			dbg("line %5u vendor %04x %s", linectr, u, cp);383			lastvendor = u;384			lasthut = lastlang = lastclass = lastsubclass = -1;385			continue;386		}387		if (buf[0] == '\t' && isxdigit(buf[1])) {388			/* product or subclass spec */389			u = strtoul(buf+1, &cp, 16);390			while (isspace(*cp))391				cp++;392			if (!*cp) {393				err("Invalid product/subclass spec at line %u",394				    linectr);395				continue;396			}397			if (lastvendor != -1) {398				if (new_product(cp, lastvendor, u))399					err("Duplicate product spec at line %u product %04x:%04x %s",400					    linectr, lastvendor, u, cp);401				dbg("line %5u product %04x:%04x %s", linectr,402				    lastvendor, u, cp);403				continue;404			}405			if (lastclass != -1) {406				if (new_subclass(cp, lastclass, u))407					err("Duplicate subclass spec at line %u class %02x:%02x %s",408					    linectr, lastclass, u, cp);409				dbg("line %5u subclass %02x:%02x %s", linectr,410				    lastclass, u, cp);411				lastsubclass = u;412				continue;413			}414			if (lasthut != -1) {415				/* do not store hut */416				continue;417			}418			if (lastlang != -1) {419				/* do not store langid */420				continue;421			}422			err("Product/Subclass spec without prior Vendor/Class spec at line %u",423			    linectr);424			continue;425		}426		if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {427			/* protocol spec */428			u = strtoul(buf+2, &cp, 16);429			while (isspace(*cp))430				cp++;431			if (!*cp) {432				err("Invalid protocol spec at line %u",433				    linectr);434				continue;435			}436			if (lastclass != -1 && lastsubclass != -1) {437				if (new_protocol(cp, lastclass, lastsubclass,438						 u))439					err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",440					    linectr, lastclass, lastsubclass,441					    u, cp);442				dbg("line %5u protocol %02x:%02x:%02x %s",443				    linectr, lastclass, lastsubclass, u, cp);444				continue;445			}446			err("Protocol spec without prior Class and Subclass spec at line %u",447			    linectr);448			continue;449		}450		if (buf[0] == 'H' && buf[1] == 'I' &&451		    buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {452			continue;453		}454		if (buf[0] == 'H' && buf[1] == 'U' &&455		    buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {456			lastlang = lastclass = lastvendor = lastsubclass = -1;457			/*458			 * set 1 as pseudo-id to indicate that the parser is459			 * in a `HUT' section.460			 */461			lasthut = 1;462			continue;463		}464		if (buf[0] == 'R' && buf[1] == ' ')465			continue;466 467		if (buf[0] == 'V' && buf[1] == 'T')468			continue;469 470		err("Unknown line at line %u", linectr);471	}472}473 474 475int names_init(char *n)476{477	FILE *f;478 479	f = fopen(n, "r");480	if (!f)481		return errno;482 483	parse(f);484	fclose(f);485	return 0;486}487