linux_dsm_epyc7002/tools/usb/usbip/libsrc/names.c
Thomas Gleixner 74ba9207e1 treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 61
Based on 1 normalized pattern(s):

  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 this program is distributed in the
  hope that it will be useful but without any warranty without even
  the implied warranty of merchantability or fitness for a particular
  purpose see the gnu general public license for more details you
  should have received a copy of the gnu general public license along
  with this program if not write to the free software foundation inc
  675 mass ave cambridge ma 02139 usa

extracted by the scancode license scanner the SPDX license identifier

  GPL-2.0-or-later

has been chosen to replace the boilerplate/reference in 441 file(s).

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
Reviewed-by: Richard Fontana <rfontana@redhat.com>
Reviewed-by: Allison Randal <allison@lohutok.net>
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Cc: linux-spdx@vger.kernel.org
Link: https://lkml.kernel.org/r/20190520071858.739733335@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-24 17:36:45 +02:00

487 lines
10 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* names.c -- USB name database manipulation routines
*
* Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* Copyright (C) 2005 Takahiro Hirofuchi
* - names_deinit() is added.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include "names.h"
#include "usbip_common.h"
struct vendor {
struct vendor *next;
u_int16_t vendorid;
char name[1];
};
struct product {
struct product *next;
u_int16_t vendorid, productid;
char name[1];
};
struct class {
struct class *next;
u_int8_t classid;
char name[1];
};
struct subclass {
struct subclass *next;
u_int8_t classid, subclassid;
char name[1];
};
struct protocol {
struct protocol *next;
u_int8_t classid, subclassid, protocolid;
char name[1];
};
struct genericstrtable {
struct genericstrtable *next;
unsigned int num;
char name[1];
};
#define HASH1 0x10
#define HASH2 0x02
#define HASHSZ 16
static unsigned int hashnum(unsigned int num)
{
unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
if (num & mask1)
num ^= mask2;
return num & (HASHSZ-1);
}
static struct vendor *vendors[HASHSZ] = { NULL, };
static struct product *products[HASHSZ] = { NULL, };
static struct class *classes[HASHSZ] = { NULL, };
static struct subclass *subclasses[HASHSZ] = { NULL, };
static struct protocol *protocols[HASHSZ] = { NULL, };
const char *names_vendor(u_int16_t vendorid)
{
struct vendor *v;
v = vendors[hashnum(vendorid)];
for (; v; v = v->next)
if (v->vendorid == vendorid)
return v->name;
return NULL;
}
const char *names_product(u_int16_t vendorid, u_int16_t productid)
{
struct product *p;
p = products[hashnum((vendorid << 16) | productid)];
for (; p; p = p->next)
if (p->vendorid == vendorid && p->productid == productid)
return p->name;
return NULL;
}
const char *names_class(u_int8_t classid)
{
struct class *c;
c = classes[hashnum(classid)];
for (; c; c = c->next)
if (c->classid == classid)
return c->name;
return NULL;
}
const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
{
struct subclass *s;
s = subclasses[hashnum((classid << 8) | subclassid)];
for (; s; s = s->next)
if (s->classid == classid && s->subclassid == subclassid)
return s->name;
return NULL;
}
const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
u_int8_t protocolid)
{
struct protocol *p;
p = protocols[hashnum((classid << 16) | (subclassid << 8)
| protocolid)];
for (; p; p = p->next)
if (p->classid == classid && p->subclassid == subclassid &&
p->protocolid == protocolid)
return p->name;
return NULL;
}
/* add a cleanup function by takahiro */
struct pool {
struct pool *next;
void *mem;
};
static struct pool *pool_head;
static void *my_malloc(size_t size)
{
struct pool *p;
p = calloc(1, sizeof(struct pool));
if (!p)
return NULL;
p->mem = calloc(1, size);
if (!p->mem) {
free(p);
return NULL;
}
p->next = pool_head;
pool_head = p;
return p->mem;
}
void names_free(void)
{
struct pool *pool;
if (!pool_head)
return;
for (pool = pool_head; pool != NULL; ) {
struct pool *tmp;
if (pool->mem)
free(pool->mem);
tmp = pool;
pool = pool->next;
free(tmp);
}
}
static int new_vendor(const char *name, u_int16_t vendorid)
{
struct vendor *v;
unsigned int h = hashnum(vendorid);
v = vendors[h];
for (; v; v = v->next)
if (v->vendorid == vendorid)
return -1;
v = my_malloc(sizeof(struct vendor) + strlen(name));
if (!v)
return -1;
strcpy(v->name, name);
v->vendorid = vendorid;
v->next = vendors[h];
vendors[h] = v;
return 0;
}
static int new_product(const char *name, u_int16_t vendorid,
u_int16_t productid)
{
struct product *p;
unsigned int h = hashnum((vendorid << 16) | productid);
p = products[h];
for (; p; p = p->next)
if (p->vendorid == vendorid && p->productid == productid)
return -1;
p = my_malloc(sizeof(struct product) + strlen(name));
if (!p)
return -1;
strcpy(p->name, name);
p->vendorid = vendorid;
p->productid = productid;
p->next = products[h];
products[h] = p;
return 0;
}
static int new_class(const char *name, u_int8_t classid)
{
struct class *c;
unsigned int h = hashnum(classid);
c = classes[h];
for (; c; c = c->next)
if (c->classid == classid)
return -1;
c = my_malloc(sizeof(struct class) + strlen(name));
if (!c)
return -1;
strcpy(c->name, name);
c->classid = classid;
c->next = classes[h];
classes[h] = c;
return 0;
}
static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
{
struct subclass *s;
unsigned int h = hashnum((classid << 8) | subclassid);
s = subclasses[h];
for (; s; s = s->next)
if (s->classid == classid && s->subclassid == subclassid)
return -1;
s = my_malloc(sizeof(struct subclass) + strlen(name));
if (!s)
return -1;
strcpy(s->name, name);
s->classid = classid;
s->subclassid = subclassid;
s->next = subclasses[h];
subclasses[h] = s;
return 0;
}
static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
u_int8_t protocolid)
{
struct protocol *p;
unsigned int h = hashnum((classid << 16) | (subclassid << 8)
| protocolid);
p = protocols[h];
for (; p; p = p->next)
if (p->classid == classid && p->subclassid == subclassid
&& p->protocolid == protocolid)
return -1;
p = my_malloc(sizeof(struct protocol) + strlen(name));
if (!p)
return -1;
strcpy(p->name, name);
p->classid = classid;
p->subclassid = subclassid;
p->protocolid = protocolid;
p->next = protocols[h];
protocols[h] = p;
return 0;
}
static void parse(FILE *f)
{
char buf[512], *cp;
unsigned int linectr = 0;
int lastvendor = -1;
int lastclass = -1;
int lastsubclass = -1;
int lasthut = -1;
int lastlang = -1;
unsigned int u;
while (fgets(buf, sizeof(buf), f)) {
linectr++;
/* remove line ends */
cp = strchr(buf, '\r');
if (cp)
*cp = 0;
cp = strchr(buf, '\n');
if (cp)
*cp = 0;
if (buf[0] == '#' || !buf[0])
continue;
cp = buf;
if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
buf[3] == 'S' && buf[4] == 'D' &&
buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
buf[7] == ' ') {
continue;
}
if (buf[0] == 'P' && buf[1] == 'H' &&
buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
continue;
}
if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
continue;
}
if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
lasthut = lastclass = lastvendor = lastsubclass = -1;
/*
* set 1 as pseudo-id to indicate that the parser is
* in a `L' section.
*/
lastlang = 1;
continue;
}
if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
/* class spec */
cp = buf+2;
while (isspace(*cp))
cp++;
if (!isxdigit(*cp)) {
err("Invalid class spec at line %u", linectr);
continue;
}
u = strtoul(cp, &cp, 16);
while (isspace(*cp))
cp++;
if (!*cp) {
err("Invalid class spec at line %u", linectr);
continue;
}
if (new_class(cp, u))
err("Duplicate class spec at line %u class %04x %s",
linectr, u, cp);
dbg("line %5u class %02x %s", linectr, u, cp);
lasthut = lastlang = lastvendor = lastsubclass = -1;
lastclass = u;
continue;
}
if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
/* audio terminal type spec */
continue;
}
if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
&& isspace(buf[3])) {
/* HID Descriptor bCountryCode */
continue;
}
if (isxdigit(*cp)) {
/* vendor */
u = strtoul(cp, &cp, 16);
while (isspace(*cp))
cp++;
if (!*cp) {
err("Invalid vendor spec at line %u", linectr);
continue;
}
if (new_vendor(cp, u))
err("Duplicate vendor spec at line %u vendor %04x %s",
linectr, u, cp);
dbg("line %5u vendor %04x %s", linectr, u, cp);
lastvendor = u;
lasthut = lastlang = lastclass = lastsubclass = -1;
continue;
}
if (buf[0] == '\t' && isxdigit(buf[1])) {
/* product or subclass spec */
u = strtoul(buf+1, &cp, 16);
while (isspace(*cp))
cp++;
if (!*cp) {
err("Invalid product/subclass spec at line %u",
linectr);
continue;
}
if (lastvendor != -1) {
if (new_product(cp, lastvendor, u))
err("Duplicate product spec at line %u product %04x:%04x %s",
linectr, lastvendor, u, cp);
dbg("line %5u product %04x:%04x %s", linectr,
lastvendor, u, cp);
continue;
}
if (lastclass != -1) {
if (new_subclass(cp, lastclass, u))
err("Duplicate subclass spec at line %u class %02x:%02x %s",
linectr, lastclass, u, cp);
dbg("line %5u subclass %02x:%02x %s", linectr,
lastclass, u, cp);
lastsubclass = u;
continue;
}
if (lasthut != -1) {
/* do not store hut */
continue;
}
if (lastlang != -1) {
/* do not store langid */
continue;
}
err("Product/Subclass spec without prior Vendor/Class spec at line %u",
linectr);
continue;
}
if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
/* protocol spec */
u = strtoul(buf+2, &cp, 16);
while (isspace(*cp))
cp++;
if (!*cp) {
err("Invalid protocol spec at line %u",
linectr);
continue;
}
if (lastclass != -1 && lastsubclass != -1) {
if (new_protocol(cp, lastclass, lastsubclass,
u))
err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
linectr, lastclass, lastsubclass,
u, cp);
dbg("line %5u protocol %02x:%02x:%02x %s",
linectr, lastclass, lastsubclass, u, cp);
continue;
}
err("Protocol spec without prior Class and Subclass spec at line %u",
linectr);
continue;
}
if (buf[0] == 'H' && buf[1] == 'I' &&
buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
continue;
}
if (buf[0] == 'H' && buf[1] == 'U' &&
buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
lastlang = lastclass = lastvendor = lastsubclass = -1;
/*
* set 1 as pseudo-id to indicate that the parser is
* in a `HUT' section.
*/
lasthut = 1;
continue;
}
if (buf[0] == 'R' && buf[1] == ' ')
continue;
if (buf[0] == 'V' && buf[1] == 'T')
continue;
err("Unknown line at line %u", linectr);
}
}
int names_init(char *n)
{
FILE *f;
f = fopen(n, "r");
if (!f)
return errno;
parse(f);
fclose(f);
return 0;
}