summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2006-01-25 16:45:04 +0000
committerJim Meyering <jim@meyering.net>2006-01-25 16:45:04 +0000
commit9d5fcc62b3ae5309a5be907ca53511d13760e9c1 (patch)
tree655fb3f1af82fac2b9935dd1d4d663c527d62e38 /lib
parent5f15ae5074582b8909cd74b23a79c1a9ae9ecee4 (diff)
downloadgnulib-9d5fcc62b3ae5309a5be907ca53511d13760e9c1.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/fts.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/lib/fts.c b/lib/fts.c
index fb1a72a002..152450f8c8 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -203,7 +203,10 @@ static int
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 @@ fts_open (char * const *argv,
#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 @@ fts_children (register FTS *sp, int instr)
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 @@ fts_stat(FTS *sp, register FTSENT *p, bool follow)
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);
}