[PATCH] Support gzip-compressed pci.ids

Daniel Drake dsd at gentoo.org
Thu Jun 21 05:04:04 PDT 2007


There is some idiocy involved with gzipping pci.ids, but pciutils
upstream appears to be going that way.

This patch adds in a fallback to read a .gz version if the plaintext version
is not available. As zlib is used for decompression, hald now links
against libz.

I have assumed that embedded users who truly care about footprint won't
be using pci.ids support anyway so the extra link isn't significant, but
if people disagree it's not too much hassle to make this a compile-time
option. It's also worth noting that libpci support already requires zlib.
---
 configure.in     |    9 +++++-
 hald/Makefile.am |    2 +-
 hald/ids.c       |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 90 insertions(+), 5 deletions(-)

diff --git a/configure.in b/configure.in
index bc1eb8a..0f434af 100644
--- a/configure.in
+++ b/configure.in
@@ -73,6 +73,8 @@ AC_ARG_WITH([socket-dir],
 	    AS_HELP_STRING([--with-socket-dir=<dir>],
 			   [Location of the HAL D-BUS listening sockets (auto)]))
 
+AC_CHECK_HEADERS([zlib.h], [AC_CHECK_LIB([z], [zlibVersion], [ZLIB_AVAILABLE="yes"]) ])
+
 if ! test -z "$with_hwdata" ; then
   PCI_IDS_DIR="$with_hwdata"
   USB_IDS_DIR="$with_hwdata"
@@ -86,10 +88,13 @@ fi
 
 if test "x$enable_pci_ids" = "xno" ; then
   USE_PCI_IDS=no
+elif test "x$ZLIB_AVAILABLE" != "xyes"; then
+  AC_ERROR([pci.ids support requires zlib])
 else
    if test -z "$PCI_IDS_DIR"; then
      for dir in /usr/share/hwdata /usr/share/misc /usr/share /var/lib/misc; do
        AC_CHECK_FILE([$dir/pci.ids], [PCI_IDS_DIR=$dir])
+       AC_CHECK_FILE([$dir/pci.ids.gz], [PCI_IDS_DIR=$dir])
      done
      if test -z "$PCI_IDS_DIR"; then
        AC_MSG_ERROR([cannot find pci.ids. Use --with-pci-ids to specify location])
@@ -422,7 +427,9 @@ AC_ARG_WITH([libpci],
 	    [], [with_libpci=yes])
 
 USE_LIBPCI="no"
-if test "x$with_libpci" != xno ; then
+if test "x$with_libpci" != xno -a test "x$ZLIB_AVAILABLE" != "xyes"; then
+   AC_ERROR([libpci support requires zlib])
+elif test "x$with_libpci" != xno ; then
   dnl check for libpci
   AC_CHECK_HEADERS([pci/pci.h],
                    [AC_CHECK_LIB([pci], [pci_init], [USE_LIBPCI="yes"], [], [-lz])])
diff --git a/hald/Makefile.am b/hald/Makefile.am
index ea396f6..ec0e876 100644
--- a/hald/Makefile.am
+++ b/hald/Makefile.am
@@ -73,7 +73,7 @@ if HAVE_CONKIT
 hald_SOURCES += ck-tracker.h ck-tracker.c
 endif
 
-hald_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @POLKIT_LIBS@ -lm @HALD_OS_LIBS@ $(top_builddir)/hald/$(HALD_BACKEND)/libhald_$(HALD_BACKEND).la
+hald_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @POLKIT_LIBS@ -lz -lm @HALD_OS_LIBS@ $(top_builddir)/hald/$(HALD_BACKEND)/libhald_$(HALD_BACKEND).la
 
 #### Init scripts fun
 SCRIPT_IN_FILES=haldaemon.in
diff --git a/hald/ids.c b/hald/ids.c
index 9949eab..3ba9d44 100644
--- a/hald/ids.c
+++ b/hald/ids.c
@@ -45,6 +45,8 @@
 #include "ids.h"
 
 #ifdef USE_PCI_IDS
+#include <zlib.h>
+
 /** Pointer to where the pci.ids file is loaded */
 static char *pci_ids = NULL;
 
@@ -271,6 +273,80 @@ ids_find_pci (int vendor_id, int product_id,
 	}
 }
 
+/**
+ *  pci_ids_load_gz:
+ *  @path:               Path of the pci.ids.gz file, e.g. /usr/share/hwdata/pci.ids.gz
+ *
+ *  Returns:             #TRUE if the file was succesfully loaded
+ *
+ *  Load the compressed PCI database used for mapping vendor, product,
+ *  subsys_vendor and subsys_product numbers into names.
+ *
+ *  As it's not possible to know the uncompressed size of a gz until you reach
+ *  EOF, this function grows a buffer in ZLIB_BUFFER_STEP increments until EOF
+ *  is reached.
+ */
+static dbus_bool_t
+pci_ids_load_gz (const char *path)
+{
+#define ZLIB_BUFFER_STEP 0x40000 /* 256kb */
+	gzFile fd;
+	unsigned char *buf = malloc(ZLIB_BUFFER_STEP);
+	int offset = 0;
+	int chunk_used = 0;
+	gboolean ret = FALSE;
+
+	if (!buf)
+		return FALSE;
+
+	fd = gzopen(path, "rb");
+	if (fd == NULL) {
+		HAL_WARNING (("Couldn't open pci.ids.gz file '%s', errno=%d: %s", path, errno, strerror (errno)));
+		return FALSE;
+	}
+
+	while (TRUE) {
+		unsigned int len;
+		int rdsize = ZLIB_BUFFER_STEP - chunk_used;
+
+		if (rdsize == 0) {
+			unsigned char *new_buf = realloc(buf, offset + ZLIB_BUFFER_STEP);
+			if (!new_buf) {
+				free(buf);
+				goto out;
+			}
+			buf = new_buf;
+			chunk_used = 0;
+			rdsize = ZLIB_BUFFER_STEP;
+		}
+
+		len = gzread(fd, buf + offset, rdsize);
+		if (len == 0) { /* EOF */
+			break;
+		} else if (len < 0) {
+			HAL_WARNING (("Error reading pci.ids.gz, len=%d errno=%d: %s", len, errno, strerror (errno)));
+			goto out;
+		}
+
+		chunk_used += len;
+		offset += len;
+	}
+
+	pci_ids = realloc(buf, offset);
+	if (!pci_ids) {
+		free(buf);
+		goto out;
+	}
+
+	pci_ids_len = offset;
+	ret = TRUE;
+	HAL_INFO (("Loaded PCI IDs from %s", path));
+
+out:
+	gzclose(fd);
+	return ret;
+
+}
 
 /**  
  *  pci_ids_load:
@@ -282,7 +358,7 @@ ids_find_pci (int vendor_id, int product_id,
  *  and subsys_product numbers into names.
  */
 static dbus_bool_t
-pci_ids_load (const char *path)
+pci_ids_load_text (const char *path)
 {
 	int fd;
 	struct stat statbuf;
@@ -310,6 +386,7 @@ pci_ids_load (const char *path)
 	}
 
 	ret = TRUE;
+	HAL_INFO (("Loaded PCI IDs from %s", path));
 
 	close (fd);
 out:
@@ -319,8 +396,9 @@ out:
 void
 pci_ids_init (void)
 {
-	/* Load /usr/share/hwdata/pci.ids */
-	pci_ids_load (PCI_IDS_DIR "/pci.ids");
+	/* Load /usr/share/hwdata/pci.ids or fallback on .gz version */
+	if (!pci_ids_load_text (PCI_IDS_DIR "/pci.ids"))
+		pci_ids_load_gz (PCI_IDS_DIR "/pci.ids.gz");
 }
 
 #endif /*USE_PCI_IDS*/
-- 
1.5.2.2



More information about the hal mailing list