open_path (const char *name, size_t namelen, int preloaded,
	   struct r_search_path_elem **dirs,
	   char **realname)
{
  char *buf;
  int fd = -1;
  const char *current_what = NULL;

  if (dirs == NULL || *dirs == NULL)
    {
      __set_errno (ENOENT);
      return -1;
    }

  buf = alloca (max_dirnamelen + max_capstrlen + namelen);
  do
    {
      struct r_search_path_elem *this_dir = *dirs;
      size_t buflen = 0;
      size_t cnt;
      char *edp;

      /* If we are debugging the search for libraries print the path
	 now if it hasn't happened now.  */
      if (_dl_debug_libs && current_what != this_dir->what)
	{
	  current_what = this_dir->what;
	  print_search_path (dirs, current_what, this_dir->where);
	}

      edp = (char *) __mempcpy (buf, this_dir->dirname, this_dir->dirnamelen);
      for (cnt = 0; fd == -1 && cnt < ncapstr; ++cnt)
	{
	  /* Skip this directory if we know it does not exist.  */
	  if (this_dir->status[cnt] == nonexisting)
	    continue;

	  buflen =
	    ((char *) __mempcpy (__mempcpy (edp,
					    capstr[cnt].str, capstr[cnt].len),
				 name, namelen)
	     - buf);

	  /* Print name we try if this is wanted.  */
	  if (_dl_debug_libs)
	    _dl_debug_message (1, "  trying file=", buf, "\n", NULL);

	  fd = __open (buf, O_RDONLY);
	  if (this_dir->status[cnt] == unknown)
	    {
	      if (fd != -1)
		this_dir->status[cnt] = existing;
	      else
		{
		  /* We failed to open machine dependent library.  Let's
		     test whether there is any directory at all.  */
		  struct stat st;

		  buf[buflen - namelen - 1] = '\0';

		  if (__xstat (_STAT_VER, buf, &st) != 0
		      || ! S_ISDIR (st.st_mode))
		    /* The directory does not exist or it is no directory.  */
		    this_dir->status[cnt] = nonexisting;
		  else
		    this_dir->status[cnt] = existing;
		}
	    }

	  if (fd != -1 && preloaded && __libc_enable_secure)
	    {
	      /* This is an extra security effort to make sure nobody can
		 preload broken shared objects which are in the trusted
		 directories and so exploit the bugs.  */
	      struct stat st;

	      if (__fxstat (_STAT_VER, fd, &st) != 0
		  || (st.st_mode & S_ISUID) == 0)
		{
		  /* The shared object cannot be tested for being SUID
		     or this bit is not set.  In this case we must not
		     use this object.  */
		  __close (fd);
		  fd = -1;
		  /* We simply ignore the file, signal this by setting
		     the error value which would have been set by `open'.  */
		  errno = ENOENT;
		}
	    }
	}

      if (fd != -1)
	{
	  *realname = malloc (buflen);
	  if (*realname != NULL)
	    {
	      memcpy (*realname, buf, buflen);
	      return fd;
	    }
	  else
	    {
	      /* No memory for the name, we certainly won't be able
		 to load and link it.  */
	      __close (fd);
	      return -1;
	    }
	}
      if (errno != ENOENT && errno != EACCES)
	/* The file exists and is readable, but something went wrong.  */
	return -1;
    }
  while (*++dirs != NULL);

  return -1;
}
open_path (const char *name, size_t namelen, int preloaded,
	   struct r_search_path_elem **dirs,
	   char **realname)
{
  char *buf;
  int fd = -1;
  const char *current_what = NULL;

  if (dirs == NULL || *dirs == NULL)
    {
      __set_errno (ENOENT);
      return -1;
    }

  buf = alloca (max_dirnamelen + max_capstrlen + namelen);
  do
    {
      struct r_search_path_elem *this_dir = *dirs;
      size_t buflen = 0;
      size_t cnt;
      char *edp;

       
      if (_dl_debug_libs && current_what != this_dir->what)
	{
	  current_what = this_dir->what;
	  print_search_path (dirs, current_what, this_dir->where);
	}

      edp = (char *) __mempcpy (buf, this_dir->dirname, this_dir->dirnamelen);
      for (cnt = 0; fd == -1 && cnt < ncapstr; ++cnt)
	{
	   
	  if (this_dir->status[cnt] == nonexisting)
	    continue;

	  buflen =
	    ((char *) __mempcpy (__mempcpy (edp,
					    capstr[cnt].str, capstr[cnt].len),
				 name, namelen)
	     - buf);

	   
	  if (_dl_debug_libs)
	    _dl_debug_message (1, "  trying file=", buf, "\n", NULL);

	  fd = __open (buf, O_RDONLY);
	  if (this_dir->status[cnt] == unknown)
	    {
	      if (fd != -1)
		this_dir->status[cnt] = existing;
	      else
		{
		   
		  struct stat st;

		  buf[buflen - namelen - 1] = '\0';

		  if (__xstat (_STAT_VER, buf, &st) != 0
		      || ! S_ISDIR (st.st_mode))
		     
		    this_dir->status[cnt] = nonexisting;
		  else
		    this_dir->status[cnt] = existing;
		}
	    }

	  if (fd != -1 && preloaded && __libc_enable_secure)
	    {
	       
	      struct stat st;

	      if (__fxstat (_STAT_VER, fd, &st) != 0
		  || (st.st_mode & S_ISUID) == 0)
		{
		   
		  __close (fd);
		  fd = -1;
		   
		  errno = ENOENT;
		}
	    }
	}

      if (fd != -1)
	{
	  *realname = malloc (buflen);
	  if (*realname != NULL)
	    {
	      memcpy (*realname, buf, buflen);
	      return fd;
	    }
	  else
	    {
	       
	      __close (fd);
	      return -1;
	    }
	}
      if (errno != ENOENT && errno != EACCES)
	 
	return -1;
    }
  while (*++dirs != NULL);

  return -1;
}