This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: PATCH: Handle symlink to directory in ldconfig.


On Mon, May 07, 2001 at 09:24:49PM +0200, Andreas Jaeger wrote:
> "H . J . Lu" <hjl@lucon.org> writes:
> 
> > On Mon, May 07, 2001 at 09:07:40PM +0200, Andreas Jaeger wrote:
> > > 
> > > Two questions:
> > > - wouldn't it be better to cache the needed stat information in struct
> > >   dir_entry?
> > 
> > I don't think speed is critical for ldconfig. On the other hand,
> > it is not a bad idea.
> 
> ldconfig is often run at each boot up - and speeding up the boot
> process is important.
> 
> > > - can we really memcmp to stat bufs?  I don't think so.  We should
> > >   instead compare st_dev and st_ino only.
> > 
> > Sure.
> > 
> > I will see what I can do.
> 
> Thanks,
> Andreas

Here it is. One bonus, now you will get

# ./elf/ldconfig /foo
./elf/ldconfig: Can't stat /foo: No such file or directory


H.J.
----
2001-05-07  H.J. Lu  <hjl@gnu.org>

	* elf/ldconfig.c (dir_entry): Add ino and dev.
	(add_single_dir): Compare ino and dev to check if 2 directory
	paths are the same or not. Free entry->path for duplicates.
	(add_dir): Initialize ino and dev for entry.
	(search_dir): Handle symlink to directory.

--- libc/elf/ldconfig.c.link	Mon Mar 19 10:36:17 2001
+++ libc/elf/ldconfig.c	Mon May  7 12:37:24 2001
@@ -66,6 +66,8 @@ struct dir_entry
 {
   char *path;
   int flag;
+  ino64_t ino;
+  dev_t dev;
   struct dir_entry *next;
 };
 
@@ -270,12 +272,13 @@ add_single_dir (struct dir_entry *entry,
   while (ptr != NULL)
     {
       /* Check for duplicates.  */
-      if (strcmp (ptr->path, entry->path) == 0)
+      if (ptr->ino == entry->ino && ptr->dev == entry->dev)
 	{
 	  if (opt_verbose && verbose)
 	    error (0, 0, _("Path `%s' given more than once"), entry->path);
 	  /* Use the newer information.  */
 	  ptr->flag = entry->flag;
+	  free (entry->path);
 	  free (entry);
 	  break;
 	}
@@ -296,6 +299,7 @@ add_dir (const char *line)
   char *equal_sign;
   struct dir_entry *entry;
   unsigned int i;
+  struct stat64 stat_buf;
 
   entry = xmalloc (sizeof (struct dir_entry));
   entry->next = NULL;
@@ -330,6 +334,17 @@ add_dir (const char *line)
       --i;
     }
 
+  if (stat64 (entry->path, &stat_buf))
+    {
+      error (0, errno, _("Can't stat %s"), entry->path);
+      free (entry->path);
+      free (entry);
+      return;
+    }
+
+  entry->ino = stat_buf.st_ino;
+  entry->dev = stat_buf.st_dev;
+
   add_single_dir (entry, 1);
 }
 
@@ -577,8 +592,8 @@ search_dir (const struct dir_entry *entr
   char *soname;
   struct dlib_entry *dlibs;
   struct dlib_entry *dlib_ptr;
-  struct stat64 stat_buf;
-  int is_link;
+  struct stat64 lstat_buf, stat_buf;
+  int is_link, is_dir;
   uint64_t hwcap = path_hwcap (entry->path);
   unsigned int osversion;
 
@@ -657,16 +672,31 @@ search_dir (const struct dir_entry *entr
 	}
 #ifdef _DIRENT_HAVE_D_TYPE
       if (direntry->d_type != DT_UNKNOWN)
-	stat_buf.st_mode = DTTOIF (direntry->d_type);
+	lstat_buf.st_mode = DTTOIF (direntry->d_type);
       else
 #endif
-	if (lstat64 (real_file_name, &stat_buf))
+	if (lstat64 (real_file_name, &lstat_buf))
 	  {
 	    error (0, errno, _("Can't lstat %s"), file_name);
 	    continue;
 	  }
 
-      if (S_ISDIR (stat_buf.st_mode) && is_hwcap_platform (direntry->d_name))
+      is_link = S_ISLNK (lstat_buf.st_mode);
+      if (is_link)
+        {
+	  /* In case of symlink, we check if the symlink refers to
+	     a directory. */
+	  if (stat64 (real_file_name, &stat_buf))
+	    {
+	      error (0, errno, _("Can't stat %s"), file_name);
+	      continue;
+	    }
+	  is_dir = S_ISDIR (stat_buf.st_mode);
+	}
+      else
+	is_dir = S_ISDIR (lstat_buf.st_mode);
+
+      if (is_dir && is_hwcap_platform (direntry->d_name))
 	{
 	  /* Handle subdirectory later.  */
 	  struct dir_entry *new_entry;
@@ -675,13 +705,22 @@ search_dir (const struct dir_entry *entr
 	  new_entry->path = xstrdup (file_name);
 	  new_entry->flag = entry->flag;
 	  new_entry->next = NULL;
+	  if (is_link)
+	    {
+	      new_entry->ino = stat_buf.st_ino;
+	      new_entry->dev = stat_buf.st_dev;
+	    }
+	  else
+	    {
+	      new_entry->ino = lstat_buf.st_ino;
+	      new_entry->dev = lstat_buf.st_dev;
+	    }
 	  add_single_dir (new_entry, 0);
 	  continue;
 	}
-      else if (!S_ISREG (stat_buf.st_mode) && !S_ISLNK (stat_buf.st_mode))
+      else if (!S_ISREG (lstat_buf.st_mode) && !is_link)
 	continue;
 
-      is_link = S_ISLNK (stat_buf.st_mode);
       if (opt_chroot && is_link)
 	{
 	  real_name = chroot_canon (opt_chroot, file_name);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]