File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pciutils / lib / names-cache.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:18:43 2012 UTC (13 years, 1 month ago) by misho
Branches: pciutils, MAIN
CVS tags: v3_1_9, HEAD
pciutils

    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>