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.
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
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)
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)#"
$(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
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".
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);
if (a->methods)
a->methods->cleanup(a);
pci_free_name_list(a);
+ pci_set_name_list_path(a, NULL, 0);
pci_mfree(a);
}
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'`"
;;
esac
;;
-
freebsd)
echo_n " fbsd-device"
echo >>$c '#define PCI_HAVE_PM_FBSD_DEVICE'
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
#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;
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;
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'))
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;
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;
+}
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 */
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) */
show_tree++;
break;
case 'i':
- pacc->id_file_name = optarg;
+ pci_set_name_list_path(pacc, optarg, 0);
break;
case 'm':
machine_readable++;
.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
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
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