]> mj.ucw.cz Git - pciutils.git/commitdiff
Added support for compressed pci.ids.
authorMartin Mares <mj@ucw.cz>
Sat, 9 Sep 2006 10:51:31 +0000 (12:51 +0200)
committerMartin Mares <mj@ucw.cz>
Sat, 9 Sep 2006 10:51:31 +0000 (12:51 +0200)
ChangeLog
Makefile
README
lib/access.c
lib/configure
lib/names.c
lib/pci.h
lspci.c
lspci.man
update-pciids.sh

index 40fb8d624c2fdd9cf6d7abe09c8cd2b7d3fe4436..bd403c7df4a7f33a1af4afaa69925e8cb9128c33 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2006-09-09  Martin Mares  <mj@ucw.cz>
 
+       * The pci.ids file can be stored compressed if zlib is available.
+       Added transparent decompression to lib/names.c, modified update-pciids.sh
+       to keep the file compressed if applicable, updated Makefiles.
+       Based on a patch by Matthew Wilcox, but all the bugs are mine.
+
        * Makefile, README: Allow installation to be done to a different directory
        from the one we will eventually be placed in by setting DESTDIR.
        Patch by Matthew Wilcox.
index 7b64441e66beeef062e5bbc46d961eae45c1b42d..aab4ee41f720c37d22741972c8a44e6612459af3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,6 +17,11 @@ DIRINSTALL=install -d
 PCILIB=lib/libpci.a
 PCIINC=lib/config.h lib/header.h lib/pci.h lib/types.h lib/sysdep.h
 
+-include lib/config.mk
+ifdef PCI_COMPRESSED_IDS
+LDFLAGS += -lz
+endif
+
 ifeq ($(shell uname),NetBSD)
 PCILIB=lib/libpciutils.a
 LDFLAGS+=-lpci
@@ -33,15 +38,15 @@ RELEASE=
 
 export
 
-all: $(PCILIB) lspci setpci lspci.8 setpci.8 update-pciids update-pciids.8 pci.ids
+all: $(PCILIB) lspci setpci lspci.8 setpci.8 update-pciids update-pciids.8 $(PCI_IDS)
 
 $(PCILIB): $(PCIINC) force
        $(MAKE) -C lib all
 
 force:
 
-lib/config.h:
-       cd lib && ./configure $(IDSDIR) $(VERSION) $(HOST) $(RELEASE)
+lib/config.h lib/config.mk:
+       cd lib && ./configure "$(IDSDIR)" "$(VERSION)" "$(HOST)" "$(RELEASE)" "$(ZLIB)"
 
 lspci: lspci.o common.o $(PCILIB)
 setpci: setpci.o common.o $(PCILIB)
@@ -51,7 +56,8 @@ setpci.o: setpci.c pciutils.h $(PCIINC)
 common.o: common.c pciutils.h $(PCIINC)
 
 update-pciids: update-pciids.sh
-       sed <$< >$@ "s@^DEST=.*@DEST=$(IDSDIR)/pci.ids@"
+       sed <$< >$@ "s@^DEST=.*@DEST=$(IDSDIR)/$(PCI_IDS)@;s@^PCI_COMPRESSED_IDS=.*@PCI_COMPRESSED_IDS=$(PCI_COMPRESSED_IDS)@"
+       chmod +x $@
 
 %.8: %.man
        M=`echo $(DATE) | sed 's/-01-/-January-/;s/-02-/-February-/;s/-03-/-March-/;s/-04-/-April-/;s/-05-/-May-/;s/-06-/-June-/;s/-07-/-July-/;s/-08-/-August-/;s/-09-/-September-/;s/-10-/-October-/;s/-11-/-November-/;s/-12-/-December-/;s/\(.*\)-\(.*\)-\(.*\)/\3 \2 \1/'` ; sed <$< >$@ "s/@TODAY@/$$M/;s/@VERSION@/pciutils-$(VERSION)/;s#@IDSDIR@#$(IDSDIR)#"
@@ -68,15 +74,15 @@ install: all
        $(DIRINSTALL) -m 755 $(DESTDIR)$(SBINDIR) $(DESTDIR)$(IDSDIR) $(DESTDIR)$(MANDIR)/man8
        $(INSTALL) -c -m 755 -s lspci setpci $(DESTDIR)$(SBINDIR)
        $(INSTALL) -c -m 755 update-pciids $(DESTDIR)$(SBINDIR)
-       $(INSTALL) -c -m 644 pci.ids $(DESTDIR)$(IDSDIR)
+       $(INSTALL) -c -m 644 $(PCI_IDS) $(DESTDIR)$(IDSDIR)
        $(INSTALL) -c -m 644 lspci.8 setpci.8 update-pciids.8 $(DESTDIR)$(MANDIR)/man8
 
 uninstall: all
        rm -f $(DESTDIR)$(SBINDIR)/lspci $(DESTDIR)$(SBINDIR)/setpci $(DESTDIR)$(SBINDIR)/update-pciids
-       rm -f $(DESTDIR)$(IDSDIR)/pci.ids
+       rm -f $(DESTDIR)$(IDSDIR)/$(PCI_IDS)
        rm -f $(DESTDIR)$(MANDIR)/man8/lspci.8 $(DESTDIR)$(MANDIR)/man8/setpci.8 $(DESTDIR)$(MANDIR)/man8/update-pciids.8
 
-get-ids:
-       cp ~/tree/pciids/pci.ids pci.ids
+pci.ids.gz: pci.ids
+       gzip -9 <$< >$@
 
-.PHONY: all clean distclean install uninstall get-ids force
+.PHONY: all clean distclean install uninstall force
diff --git a/README b/README
index 9d8df7070ce12879875ae38c29930cc01217d54c..5c67759216d364abe9fb3885184708892d9238b8 100644 (file)
--- a/README
+++ b/README
@@ -52,6 +52,13 @@ will allow you to install to a different directory from the one you intend
 to eventually run it from.  This is useful for people who are packaging
 pciutils to install on other computers.
 
+The configure script will automatically enable support for a compressed
+pci.ids if you have zlib installed.  You can override its guess by using
+"make ZLIB=no" or "make ZLIB=yes".  If compressed support is enabled,
+pciutils will use pci.ids.gz in preference to pci.ids, even if the
+pci.ids file is newer.  If the pci.ids.gz file is missing, it will use
+pci.ids instead.
+
 When you are bored of dumping PCI registers, just use "make uninstall".
 
 
index 0ee85c13aa454cd8880b0099c6054dcd1a00165a..7e3fb71b1a7d548e96809cd7f5c4c87a4ba8f1f0 100644 (file)
@@ -66,7 +66,7 @@ pci_alloc(void)
   int i;
 
   bzero(a, sizeof(*a));
-  a->id_file_name = PCI_PATH_IDS;
+  pci_set_name_list_path(a, PCI_PATH_IDS_DIR "/" PCI_IDS, 0);
   for(i=0; i<PCI_ACCESS_MAX; i++)
     if (pci_methods[i] && pci_methods[i]->config)
       pci_methods[i]->config(a);
@@ -182,6 +182,7 @@ pci_cleanup(struct pci_access *a)
   if (a->methods)
     a->methods->cleanup(a);
   pci_free_name_list(a);
+  pci_set_name_list_path(a, NULL, 0);
   pci_mfree(a);
 }
 
index 6a440d236a7a93648daa0e4405a16273f25c54aa..7c828d9974b96a7de0c4c17b91190a275abbb544 100755 (executable)
@@ -32,6 +32,7 @@ cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
 sys=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 rel=${4:-$rel}
 echo " $host $rel"
+zlib=$5
 
 c=config.h
 echo >$c "#define PCI_ARCH_`echo $cpu | tr 'a-z' 'A-Z'`"
@@ -71,7 +72,6 @@ case $sys in
                                                ;;
                esac
                ;;
-               
        freebsd)
                echo_n " fbsd-device"
                echo >>$c '#define PCI_HAVE_PM_FBSD_DEVICE'
@@ -111,6 +111,25 @@ echo " dump"
 if [ -z "$ok" ] ; then
        echo "WARNING: No real configuration access method is available."
 fi
-echo >>$c "#define PCI_PATH_IDS \"$idsdir/pci.ids\""
+
+echo_n "Checking for zlib support... "
+if [ "$zlib" = yes -o "$zlib" = no ] ; then
+       echo "$zlib (set manually)"
+else
+       if [ -f /usr/include/zlib.h ] ; then
+               zlib=yes
+       else
+               zlib=no
+       fi
+       echo "$zlib (auto-detected)"
+fi
+if [ "$zlib" = yes ] ; then
+       echo >>$c '#define PCI_COMPRESSED_IDS'
+       echo >>$c "#define PCI_IDS \"pci.ids.gz\""
+else
+       echo >>$c "#define PCI_IDS \"pci.ids\""
+fi
+echo >>$c "#define PCI_PATH_IDS_DIR \"$idsdir\""
+
 echo >>$c "#define PCILIB_VERSION \"$version\""
-sed '/^#define [^ ]*$/!d;s/^#define \(.*\)/\1=1/' <$c >config.mk
+sed '/"/{s/^#define \([^ ]*\) "\(.*\)"$/\1=\2/;p;d;};s/^#define \(.*\)/\1=1/' <$c >config.mk
index af3cc151c4a906d9cb1889e08ce05678cf405216..c1b3081c0915810126457f41addba4402e75d25d 100644 (file)
 
 #include "internal.h"
 
+#ifdef PCI_COMPRESSED_IDS
+#include <zlib.h>
+typedef gzFile pci_file;
+#define pci_gets(f, l, s)      gzgets(f, l, s)
+#define pci_eof(f)             gzeof(f)
+
+static pci_file pci_open(struct pci_access *a)
+{
+  pci_file result;
+  size_t len;
+  char *new_name;
+
+  result = gzopen(a->id_file_name, "r");
+  if (result)
+    return result;
+  len = strlen(a->id_file_name);
+  if (len >= 3 && memcmp(a->id_file_name + len - 3, ".gz", 3) != 0)
+    return result;
+  new_name = malloc(len - 2);
+  memcpy(new_name, a->id_file_name, len - 3);
+  new_name[len - 3] = 0;
+  pci_set_name_list_path(a, new_name, 1);
+  return gzopen(a->id_file_name, "r");
+}
+
+#define pci_close(f)           gzclose(f)
+#define PCI_ERROR(f, err)                                              \
+       if (!err) {                                                     \
+               int errnum;                                             \
+               err = gzerror(f, &errnum);                              \
+               if (errnum == Z_ERRNO)  err = "I/O error";              \
+               else if (errnum >= 0)   err = NULL;                     \
+       }
+#else
+typedef FILE * pci_file;
+#define pci_gets(f, l, s)      fgets(l, s, f)
+#define pci_eof(f)             feof(f)
+#define pci_open(a)            fopen(a->id_file_name, "r")
+#define pci_close(f)           fclose(f)
+#define PCI_ERROR(f, err)      if (!err && ferror(f))  err = "I/O error";
+#endif
+
 struct id_entry {
   struct id_entry *next;
   u32 id12, id34;
@@ -141,7 +183,7 @@ static inline int id_white_p(int c)
   return (c == ' ') || (c == '\t');
 }
 
-static const char *id_parse_list(struct pci_access *a, FILE *f, int *lino)
+static const char *id_parse_list(struct pci_access *a, pci_file f, int *lino)
 {
   char line[MAX_LINE];
   char *p;
@@ -151,13 +193,13 @@ static const char *id_parse_list(struct pci_access *a, FILE *f, int *lino)
   static const char parse_error[] = "Parse error";
 
   *lino = 0;
-  while (fgets(line, sizeof(line), f))
+  while (pci_gets(f, line, sizeof(line)))
     {
       (*lino)++;
       p = line;
       while (*p && *p != '\n' && *p != '\r')
        p++;
-      if (!*p && !feof(f))
+      if (!*p && !pci_eof(f))
        return "Line too long";
       *p = 0;
       if (p > line && (p[-1] == ' ' || p[-1] == '\t'))
@@ -275,20 +317,19 @@ static const char *id_parse_list(struct pci_access *a, FILE *f, int *lino)
 int
 pci_load_name_list(struct pci_access *a)
 {
-  FILE *f;
+  pci_file f;
   int lino;
   const char *err;
 
   pci_free_name_list(a);
   a->hash_load_failed = 1;
-  if (!(f = fopen(a->id_file_name, "r")))
+  if (!(f = pci_open(a)))
     return 0;
   a->id_hash = pci_malloc(a, sizeof(struct id_entry *) * HASH_SIZE);
   bzero(a->id_hash, sizeof(struct id_entry *) * HASH_SIZE);
   err = id_parse_list(a, f, &lino);
-  if (!err && ferror(f))
-    err = "I/O error";
-  fclose(f);
+  PCI_ERROR(f, err);
+  pci_close(f);
   if (err)
     a->error("%s at %s, line %d\n", err, a->id_file_name, lino);
   a->hash_load_failed = 0;
@@ -468,3 +509,11 @@ pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...)
       return "<pci_lookup_name: invalid request>";
     }
 }
+
+void pci_set_name_list_path(struct pci_access *a, char *name, int to_be_freed)
+{
+  if (a->free_id_name)
+    free(a->id_file_name);
+  a->id_file_name = name;
+  a->free_id_name = to_be_freed;
+}
index 8c208b406fdba92aea08ee6243e23c502a9d808f..9d2893788ba81706aea394f4d92d8905f191cdeb 100644 (file)
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -43,6 +43,7 @@ struct pci_access {
   int writeable;                       /* Open in read/write mode */
   int buscentric;                      /* Bus-centric view of the world */
   char *id_file_name;                  /* Name of ID list file */
+  int free_id_name;                    /* Set if id_file_name is malloced */
   int numeric_ids;                     /* Enforce PCI_LOOKUP_NUMERIC (>1 => PCI_LOOKUP_MIXED) */
   int debugging;                       /* Turn on debugging messages */
 
@@ -160,6 +161,7 @@ char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, ...)
 
 int pci_load_name_list(struct pci_access *a);  /* Called automatically by pci_lookup_*() when needed; returns success */
 void pci_free_name_list(struct pci_access *a); /* Called automatically by pci_cleanup() */
+void pci_set_name_list_path(struct pci_access *a, char *name, int to_be_freed);
 
 enum pci_lookup_mode {
   PCI_LOOKUP_VENDOR = 1,               /* Vendor name (args: vendorID) */
diff --git a/lspci.c b/lspci.c
index 5d13fd86a0969a25a27eea8dd89cfd608d01a646..98c0bb36804520d63e8aaef23ef6b56270c5b2db 100644 (file)
--- a/lspci.c
+++ b/lspci.c
@@ -2356,7 +2356,7 @@ main(int argc, char **argv)
        show_tree++;
        break;
       case 'i':
-       pacc->id_file_name = optarg;
+        pci_set_name_list_path(pacc, optarg, 0);
        break;
       case 'm':
        machine_readable++;
index db7fce8b0747a2d104382513866c4c418311b894..7f44fd1a160651c70f94b284801017c394060549 100644 (file)
--- a/lspci.man
+++ b/lspci.man
@@ -195,6 +195,9 @@ at http://pciids.sourceforge.net/, use the
 .B update-pciids
 utility to download the most recent version.
 .TP
+.B @IDSDIR@/pci.ids.gz
+If lspci is compiled with support for compression, this file is tried before pci.ids.
+.TP
 .B /proc/bus/pci
 An interface to PCI bus configuration space provided by the post-2.1.82 Linux
 kernels. Contains per-bus subdirectories with per-card config space files and a
index 0e21dff52348cee35d734139e5e8c7b93c69f6d4..a084f7b35de741ed91c75cdaf5d38ee42939122b 100755 (executable)
@@ -3,8 +3,14 @@
 set -e
 SRC="http://pciids.sourceforge.net/v2.2/pci.ids"
 DEST=pci.ids
+PCI_COMPRESSED_IDS=
+GREP=grep
 
-if which bzip2 >/dev/null ; then
+if [ -n "$PCI_COMPRESSED_IDS" ] ; then
+       DECOMP="cat"
+       SRC="$SRC.gz"
+       GREP=zgrep
+elif which bzip2 >/dev/null ; then
        DECOMP="bzip2 -d"
        SRC="$SRC.bz2"
 elif which gzip >/dev/null ; then
@@ -36,7 +42,7 @@ if ! $DECOMP <$DEST.new >$DEST.neww ; then
        exit 1
 fi
 
-if ! grep >/dev/null "^C " $DEST.neww ; then
+if ! $GREP >/dev/null "^C " $DEST.neww ; then
        echo >&2 "update-pciids: missing class info, probably truncated file"
        exit 1
 fi