Annotation of embedaddon/pciutils/lib/names-cache.c, revision 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>