Annotation of embedaddon/pciutils/lib/names-cache.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *     The PCI Library -- ID to Name Cache
                      3:  *
                      4:  *     Copyright (c) 2008--2009 Martin Mares <mj@ucw.cz>
                      5:  *
                      6:  *     Can be freely distributed and used under the terms of the GNU GPL.
                      7:  */
                      8: 
                      9: #include "internal.h"
                     10: #include "names.h"
                     11: 
                     12: #ifdef PCI_USE_DNS
                     13: 
                     14: #include <stdio.h>
                     15: #include <stdlib.h>
                     16: #include <string.h>
                     17: #include <errno.h>
                     18: #include <sys/types.h>
                     19: #include <pwd.h>
                     20: #include <unistd.h>
                     21: 
                     22: static const char cache_version[] = "#PCI-CACHE-1.0";
                     23: 
                     24: static char *get_cache_name(struct pci_access *a)
                     25: {
                     26:   char *name, *buf;
                     27: 
                     28:   name = pci_get_param(a, "net.cache_name");
                     29:   if (!name || !name[0])
                     30:     return NULL;
                     31:   if (strncmp(name, "~/", 2))
                     32:     return name;
                     33: 
                     34:   uid_t uid = getuid();
                     35:   struct passwd *pw = getpwuid(uid);
                     36:   if (!pw)
                     37:     return name;
                     38: 
                     39:   buf = pci_malloc(a, strlen(pw->pw_dir) + strlen(name+1) + 1);
                     40:   sprintf(buf, "%s%s", pw->pw_dir, name+1);
                     41:   pci_set_param_internal(a, "net.cache_name", buf, 0);
                     42:   return buf;
                     43: }
                     44: 
                     45: int
                     46: pci_id_cache_load(struct pci_access *a, int flags)
                     47: {
                     48:   char *name;
                     49:   char line[MAX_LINE];
                     50:   FILE *f;
                     51:   int lino;
                     52: 
                     53:   a->id_cache_status = 1;
                     54:   name = get_cache_name(a);
                     55:   if (!name)
                     56:     return 0;
                     57:   a->debug("Using cache %s\n", name);
                     58:   if (flags & PCI_LOOKUP_REFRESH_CACHE)
                     59:     {
                     60:       a->debug("Not loading cache, will refresh everything\n");
                     61:       a->id_cache_status = 2;
                     62:       return 0;
                     63:     }
                     64: 
                     65:   f = fopen(name, "rb");
                     66:   if (!f)
                     67:     {
                     68:       a->debug("Cache file does not exist\n");
                     69:       return 0;
                     70:     }
                     71:   /* FIXME: Compare timestamp with the pci.ids file? */
                     72: 
                     73:   lino = 0;
                     74:   while (fgets(line, sizeof(line), f))
                     75:     {
                     76:       char *p = strchr(line, '\n');
                     77:       lino++;
                     78:       if (p)
                     79:         {
                     80:          *p = 0;
                     81:          if (lino == 1)
                     82:            {
                     83:              if (strcmp(line, cache_version))
                     84:                {
                     85:                  a->debug("Unrecognized cache version %s, ignoring\n", line);
                     86:                  break;
                     87:                }
                     88:              continue;
                     89:            }
                     90:          else
                     91:            {
                     92:              int cat, id1, id2, id3, id4, cnt;
                     93:              if (sscanf(line, "%d%x%x%x%x%n", &cat, &id1, &id2, &id3, &id4, &cnt) >= 5)
                     94:                {
                     95:                  p = line + cnt;
                     96:                  while (*p && *p == ' ')
                     97:                    p++;
                     98:                  pci_id_insert(a, cat, id1, id2, id3, id4, p, SRC_CACHE);
                     99:                  continue;
                    100:                }
                    101:            }
                    102:        }
                    103:       a->warning("Malformed cache file %s (line %d), ignoring", name, lino);
                    104:       break;
                    105:     }
                    106: 
                    107:   if (ferror(f))
                    108:     a->warning("Error while reading %s", name);
                    109:   fclose(f);
                    110:   return 1;
                    111: }
                    112: 
                    113: void
                    114: pci_id_cache_flush(struct pci_access *a)
                    115: {
                    116:   int orig_status = a->id_cache_status;
                    117:   FILE *f;
                    118:   unsigned int h;
                    119:   struct id_entry *e, *e2;
                    120:   char hostname[256], *tmpname, *name;
                    121:   int this_pid;
                    122: 
                    123:   a->id_cache_status = 0;
                    124:   if (orig_status < 2)
                    125:     return;
                    126:   name = get_cache_name(a);
                    127:   if (!name)
                    128:     return;
                    129: 
                    130:   this_pid = getpid();
                    131:   if (gethostname(hostname, sizeof(hostname)) < 0)
                    132:     hostname[0] = 0;
                    133:   else
                    134:     hostname[sizeof(hostname)-1] = 0;
                    135:   tmpname = pci_malloc(a, strlen(name) + strlen(hostname) + 64);
                    136:   sprintf(tmpname, "%s.tmp-%s-%d", name, hostname, this_pid);
                    137: 
                    138:   f = fopen(tmpname, "wb");
                    139:   if (!f)
                    140:     {
                    141:       a->warning("Cannot write to %s: %s", name, strerror(errno));
                    142:       pci_mfree(tmpname);
                    143:       return;
                    144:     }
                    145:   a->debug("Writing cache to %s\n", name);
                    146:   fprintf(f, "%s\n", cache_version);
                    147: 
                    148:   for (h=0; h<HASH_SIZE; h++)
                    149:     for (e=a->id_hash[h]; e; e=e->next)
                    150:       if (e->src == SRC_CACHE || e->src == SRC_NET)
                    151:        {
                    152:          /* Negative entries are not written */
                    153:          if (!e->name[0])
                    154:            continue;
                    155: 
                    156:          /* Verify that every entry is written at most once */
                    157:          for (e2=a->id_hash[h]; e2 != e; e2=e2->next)
                    158:            if ((e2->src == SRC_CACHE || e2->src == SRC_NET) &&
                    159:                e2->cat == e->cat &&
                    160:                e2->id12 == e->id12 && e2->id34 == e->id34)
                    161:            break;
                    162:          if (e2 == e)
                    163:            fprintf(f, "%d %x %x %x %x %s\n",
                    164:                    e->cat,
                    165:                    pair_first(e->id12), pair_second(e->id12),
                    166:                    pair_first(e->id34), pair_second(e->id34),
                    167:                    e->name);
                    168:        }
                    169: 
                    170:   fflush(f);
                    171:   if (ferror(f))
                    172:     a->warning("Error writing %s", name);
                    173:   fclose(f);
                    174: 
                    175:   if (rename(tmpname, name) < 0)
                    176:     {
                    177:       a->warning("Cannot rename %s to %s: %s", tmpname, name, strerror(errno));
                    178:       unlink(tmpname);
                    179:     }
                    180:   pci_mfree(tmpname);
                    181: }
                    182: 
                    183: #else
                    184: 
                    185: int pci_id_cache_load(struct pci_access *a UNUSED, int flags UNUSED)
                    186: {
                    187:   a->id_cache_status = 1;
                    188:   return 0;
                    189: }
                    190: 
                    191: void pci_id_cache_flush(struct pci_access *a)
                    192: {
                    193:   a->id_cache_status = 0;
                    194: }
                    195: 
                    196: #endif
                    197: 
                    198: void
                    199: pci_id_cache_dirty(struct pci_access *a)
                    200: {
                    201:   if (a->id_cache_status >= 1)
                    202:     a->id_cache_status = 2;
                    203: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>