From: Martin Mares Date: Sat, 9 Sep 2006 10:51:31 +0000 (+0200) Subject: Added support for compressed pci.ids. X-Git-Tag: v3.0.0~31 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=cc062b4ade94481589af2b6dc94e280caab94498;p=pciutils.git Added support for compressed pci.ids. --- diff --git a/ChangeLog b/ChangeLog index 40fb8d6..bd403c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2006-09-09 Martin Mares + * 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. diff --git a/Makefile b/Makefile index 7b64441..aab4ee4 100644 --- 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 9d8df70..5c67759 100644 --- 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". diff --git a/lib/access.c b/lib/access.c index 0ee85c1..7e3fb71 100644 --- a/lib/access.c +++ b/lib/access.c @@ -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; iconfig) 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); } diff --git a/lib/configure b/lib/configure index 6a440d2..7c828d9 100755 --- a/lib/configure +++ b/lib/configure @@ -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 diff --git a/lib/names.c b/lib/names.c index af3cc15..c1b3081 100644 --- a/lib/names.c +++ b/lib/names.c @@ -14,6 +14,48 @@ #include "internal.h" +#ifdef PCI_COMPRESSED_IDS +#include +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 ""; } } + +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; +} diff --git a/lib/pci.h b/lib/pci.h index 8c208b4..9d28937 100644 --- 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 5d13fd8..98c0bb3 100644 --- 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++; diff --git a/lspci.man b/lspci.man index db7fce8..7f44fd1 100644 --- 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 diff --git a/update-pciids.sh b/update-pciids.sh index 0e21dff..a084f7b 100755 --- a/update-pciids.sh +++ b/update-pciids.sh @@ -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