~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/usb/usbip/libsrc/names.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  *      names.c  --  USB name database manipulation routines
  4  *
  5  *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  6  *
  7  *      Copyright (C) 2005 Takahiro Hirofuchi
  8  *              - 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 
 25 struct vendor {
 26         struct vendor *next;
 27         u_int16_t vendorid;
 28         char name[1];
 29 };
 30 
 31 struct product {
 32         struct product *next;
 33         u_int16_t vendorid, productid;
 34         char name[1];
 35 };
 36 
 37 struct class {
 38         struct class *next;
 39         u_int8_t classid;
 40         char name[1];
 41 };
 42 
 43 struct subclass {
 44         struct subclass *next;
 45         u_int8_t classid, subclassid;
 46         char name[1];
 47 };
 48 
 49 struct protocol {
 50         struct protocol *next;
 51         u_int8_t classid, subclassid, protocolid;
 52         char name[1];
 53 };
 54 
 55 struct genericstrtable {
 56         struct genericstrtable *next;
 57         unsigned int num;
 58         char name[1];
 59 };
 60 
 61 
 62 #define HASH1  0x10
 63 #define HASH2  0x02
 64 #define HASHSZ 16
 65 
 66 static 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 
 77 static struct vendor *vendors[HASHSZ] = { NULL, };
 78 static struct product *products[HASHSZ] = { NULL, };
 79 static struct class *classes[HASHSZ] = { NULL, };
 80 static struct subclass *subclasses[HASHSZ] = { NULL, };
 81 static struct protocol *protocols[HASHSZ] = { NULL, };
 82 
 83 const 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 
 94 const 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 
105 const 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 
116 const 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 
127 const 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 */
142 struct pool {
143         struct pool *next;
144         void *mem;
145 };
146 
147 static struct pool *pool_head;
148 
149 static 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 
169 void 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 
188 static 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 
207 static 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 
228 static 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 
247 static 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 
267 static 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 == subclassid
277                     && 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 
291 static 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 is
332                          * 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 is
459                          * 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 
475 int 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php