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>