changeset 6611:e4456c51dde7

Sync from the stable (b5) branch of coreutils: (fts_children): Don't let close() clobber errno from failed fchdir(). (fts_stat): When following a symlink-to-directory, don't necessarily interpret stat-fails+lstat-succeeds as indicating a dangling symlink. That can also happen at least for ELOOP. The fix: return FTS_SLNONE only when the stat errno is ENOENT. FYI, this bug predates the inclusion of fts.c in coreutils. (fts_open): Put new maxarglen declaration and uses in their own block, so pre-c99 compilers don't object. Avoid the double-free (first in fts_read, second in fts_close) that would occur when an `active' directory is made inaccessible (e.g., via chmod a-x) during a traversal. (fts_read): After a failed fchdir, update sp->fts_cur before returning. Reproduce this failure by mkdir -p a/b; cd a; chmod a-x . b Reported by Stavros Passas.
author Jim Meyering <jim@meyering.net>
date Wed, 25 Jan 2006 16:45:04 +0000
parents 4033ab84f3a0
children d4440c93eb50
files lib/fts.c
diffstat 1 files changed, 13 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -203,7 +203,10 @@
 internal_function
 diropen (char const *dir)
 {
-  return open (dir, O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
+  int fd = open (dir, O_RDONLY | O_DIRECTORY);
+  if (fd < 0)
+    fd = open (dir, O_WRONLY | O_DIRECTORY);
+  return fd;
 }
 
 FTS *
@@ -241,9 +244,11 @@
 #ifndef MAXPATHLEN
 # define MAXPATHLEN 1024
 #endif
-	size_t maxarglen = fts_maxarglen(argv);
-	if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
-		goto mem1;
+	{
+	  size_t maxarglen = fts_maxarglen(argv);
+	  if (! fts_palloc(sp, MAX(maxarglen, MAXPATHLEN)))
+		  goto mem1;
+	}
 
 	/* Allocate/initialize root's parent. */
 	if ((parent = fts_alloc(sp, "", 0)) == NULL)
@@ -693,7 +698,9 @@
 		return (sp->fts_child = NULL);
 	sp->fts_child = fts_build(sp, instr);
 	if (fchdir(fd)) {
+		int saved_errno = errno;
 		(void)close(fd);
+		__set_errno (saved_errno);
 		return (NULL);
 	}
 	(void)close(fd);
@@ -1066,7 +1073,8 @@
 	if (ISSET(FTS_LOGICAL) || follow) {
 		if (stat(p->fts_accpath, sbp)) {
 			saved_errno = errno;
-			if (!lstat(p->fts_accpath, sbp)) {
+			if (errno == ENOENT
+			    && lstat(p->fts_accpath, sbp) == 0) {
 				__set_errno (0);
 				return (FTS_SLNONE);
 			}