about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--elf/dl-load.c8
-rw-r--r--elf/ldsodefs.h23
-rw-r--r--elf/link.h4
-rw-r--r--nss/nsswitch.c2
-rw-r--r--resolv/netdb.h6
-rw-r--r--sysdeps/generic/dl-sysdep.c119
7 files changed, 138 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 5400d1ac11..7b28c906cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 1998-03-30  Ulrich Drepper  <drepper@cygnus.com>
 
+	* nss/nsswitch.c (__nss_lookup): Adjust comment.
+
 	* sysdeps/generic/dl-sysdep.c (_dl_important_hwcaps): New
 	function.
 
diff --git a/elf/dl-load.c b/elf/dl-load.c
index c75a91392e..212b22307a 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -331,6 +331,10 @@ _dl_init_paths (const char *llp)
      variable.  */
   struct link_map *l;
 
+  /* Names of important hardware capabilities.  */
+  char **hwcap_names;
+  size_t nhwcap_names;
+
   /* Number of elements in the library path.  */
   size_t nllp;
 
@@ -347,6 +351,10 @@ _dl_init_paths (const char *llp)
   else
     nllp = 0;
 
+  /* Get the capabilities.  */
+  hwcap_names = _dl_important_hwcaps (&nhwcap_names,
+				      _dl_platform, _dl_platformlen);
+
   l = _dl_loaded;
   if (l != NULL)
     {
diff --git a/elf/ldsodefs.h b/elf/ldsodefs.h
index 3154bf2a2b..578e085d75 100644
--- a/elf/ldsodefs.h
+++ b/elf/ldsodefs.h
@@ -53,20 +53,22 @@ enum r_dir_status { unknown, nonexisting, existing };
 
 struct r_search_path_elem
   {
-    const char *dirname;
-
-    size_t dirnamelen;
-    enum r_dir_status dirstatus;
-
-    size_t machdirnamelen;
-    enum r_dir_status machdirstatus;
+    /* This link is only used in the `all_dirs' member of `r_search_path'.  */
+    struct r_search_path_elem *next;
 
     /* Strings saying where the definition came from.  */
     const char *what;
     const char *where;
 
-    /* This link is only used in the `all_dirs' member of `r_search_path'.  */
-    struct r_search_path_elem *next;
+    const char *dirname;
+
+    enum r_dir_status exists[0];
+  };
+
+struct r_strlenpair
+  {
+    const char *str;
+    size_t len;
   };
 
 
@@ -383,6 +385,9 @@ extern void _dl_show_auxv (void);
    other.  */
 extern char *_dl_next_ld_env_entry (char ***position);
 
+/* Return an array with the names of the important hardware capabilities.  */
+extern char **_dl_important_hwcap (size_t *sz);
+
 __END_DECLS
 
 #endif /* ldsodefs.h */
diff --git a/elf/link.h b/elf/link.h
index 30efa0ed25..edf1303595 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -156,6 +156,10 @@ struct link_map
     /* Collected information about own RPATH directories.  */
     struct r_search_path_elem **l_rpath_dirs;
 
+    /* Directory names composed from capability names.  */
+    struct r_strlenpair *l_capstrs;
+    size_t l_ncapstrs;
+
     /* Collected results of relocation while profiling.  */
     ElfW(Addr) *l_reloc_result;
 
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index ab0f850091..c968502cdf 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -135,7 +135,7 @@ __nss_database_lookup (const char *database, const char *alternate_name,
 
 
 /* -1 == not found
-    0 == adjusted for next function
+    0 == function found
     1 == finished */
 int
 __nss_lookup (service_user **ni, const char *fct_name, void **fctp)
diff --git a/resolv/netdb.h b/resolv/netdb.h
index fdfc056750..9282be334a 100644
--- a/resolv/netdb.h
+++ b/resolv/netdb.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it
@@ -49,13 +49,11 @@ extern int h_errno;
 extern int *__h_errno_location __P ((void)) __attribute__ ((__const__));
 
 #ifdef _LIBC
-/* Retain some binary compatibility with old libraries by having both the
-   global variable and the per-thread variable set on error.  */
 # ifdef _LIBC_REENTRANT
 static inline int
 __set_h_errno (int __err)
 {
-  return *__h_errno_location () = h_errno = __err;
+  return *__h_errno_location () = __err;
 }
 # else
 #  define __set_h_errno(x) (h_errno = (x))
diff --git a/sysdeps/generic/dl-sysdep.c b/sysdeps/generic/dl-sysdep.c
index 7f5e32193a..a113c14c42 100644
--- a/sysdeps/generic/dl-sysdep.c
+++ b/sysdeps/generic/dl-sysdep.c
@@ -272,28 +272,123 @@ _dl_next_ld_env_entry (char ***position)
 }
 
 /* Return an array of useful/necessary hardware capability names.  */
-char **
-_dl_important_hwcaps (size_t *sz)
+const struct r_strlenpair *
+_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz)
 {
   /* Determine how many important bits are set.  */
   unsigned long int important = hwcap & HWCAP_IMPORTANT;
-  size_t cnt = 0;
-  size_t n;
-  char **result;
+  size_t cnt = platform != NULL;
+  size_t n, m;
+  size_t total;
+  struct r_strlenpair *temp;
+  struct r_strlenpair *result;
 
   for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n)
     if ((important & (1UL << n)) != 0)
       ++cnt;
 
-  *sz = 0;
   if (cnt == 0)
-    return NULL;
+    {
+      /* If we have platform name and no important capability we only have
+	 the base directory to search.  */
+      result = (struct r_strlenpair *) malloc (sizeof (*result));
+      if (result == NULL)
+	{
+	no_memory:
+	  _dl_signal_error (ENOMEM, NULL, "cannot create capability list");
+	}
+
+      result[0]->str = (char *) result;	/* Does not really matter.  */
+      result[0]->len = 0;
+
+      *sz = 1;
+      return &only_base;
+    }
+
+  /* Create temporary data structure to generate result table.  */
+  temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
+  m = 0;
+  for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n)
+    if ((important & (1UL << n)) != 0)
+      {
+	temp[m].str = _dl_hwcap_string (n);
+	temp[m].len = strlen (temp[m].str);
+	++m
+      }
+  if (platform != NULL)
+    {
+      temp[m].str = platform;
+      temp[m].len = platform_len;
+      ++m;
+    }
+
+  if (cnt == 1)
+    {
+      result = (struct r_strlenpair *) malloc (2 * sizeof (*result)
+					       + temp[0].len + 1);
+      if (result == NULL)
+	goto no_memory;
+
+      result[0].str = (char *) (result + 1);
+      result[0].len = len;
+      result[1].str = (char *) (result + 1);
+      result[1].len = 0;
+      result[0].str[0] = '/';
+      memcpy (&result[0].str[1], temp[0].str, temp[0].len);
+      *sz = 2;
+
+      return result;
+    }
+
+  /* Determine the total size of all strings together.  */
+  total = cnt * (temp[0].len + temp[cnt - 1].len + 2);
+  for (n = 1; n + 1 < cnt; ++n)
+    total += 2 * (temp[n].len + 1);
+
+  /* The result structure: we use a very compressed way to store the
+     various combinations of capability names.  */
+  result = (struct r_strlenpair *) malloc (1 << (cnt - 2) * sizeof (*result)
+					   + total);
+  if (result == NULL)
+    goto no_memory;
+
+  /* Fill in the information.  This follows the following scheme
+     (indeces from TEMP for four strings):
+	entry #0: 0, 1, 2, 3	binary: 1111
+	      #1: 0, 1, 3	        1101
+	      #2: 0, 2, 3	        1011
+	      #3: 0, 3		        1001
+     This allows to represent all possible combinations of capability
+     names in the string.  First generate the strings.  */
+  n = 1 << cnt;
+  cp = result[0].str = (char *) (result + 1 << (cnt - 2));
+  do
+    {
+#define add(idx) \
+      cp = __mempcpy (__mempcpy (cp, "/", 1), temp[idx].str, temp[idx].len)
+
+      n -= 2;
+
+      /* We always add the last string.  */
+      add (cnt - 1);
+
+      /* Add the strings which have the bit set in N.  */
+      for (m = cnt - 2; cnt > 0; --cnt)
+	if ((n & (1 << m)) != 0)
+	  add (m);
+
+      /* Always add the first string.  */
+      add (0);
+    }
+  while (n != 0);
+
+  /* Now we are ready to install the string pointers and length.
+     The first string contains all strings.  */
+  result[0].len = 0;
+  for (n = 0; n < cnt; ++n)
+    result[0].len += temp[n].len;
 
-  result = (char **) malloc (cnt * sizeof (char *));
-  if (result != NULL)
-    for (n = 0; (~((1UL << n) - 1) & important) != 0; ++n)
-      if ((important & (1UL << n)) != 0)
-	result[*sz++] = _dl_hwcap_string (n);
+  I KNOW THIS DOES NOT YET WORK --drepper
 
   return result;
 }