Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/gen add fts_safe_changedir() function and use it ev...
details: https://anonhg.NetBSD.org/src/rev/eabbaff288a3
branches: trunk
changeset: 512326:eabbaff288a3
user: christos <christos%NetBSD.org@localhost>
date: Mon Jul 09 21:33:03 2001 +0000
description:
add fts_safe_changedir() function and use it everywhere.
Idea from Todd Miller <millert%openbsd.org@localhost>
diffstat:
lib/libc/gen/__fts13.c | 86 +++++++++++++++++++++++++++++--------------------
1 files changed, 51 insertions(+), 35 deletions(-)
diffs (139 lines):
diff -r e847c1575783 -r eabbaff288a3 lib/libc/gen/__fts13.c
--- a/lib/libc/gen/__fts13.c Mon Jul 09 21:01:31 2001 +0000
+++ b/lib/libc/gen/__fts13.c Mon Jul 09 21:33:03 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: __fts13.c,v 1.34 2001/06/06 14:10:46 christos Exp $ */
+/* $NetBSD: __fts13.c,v 1.35 2001/07/09 21:33:03 christos Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#else
-__RCSID("$NetBSD: __fts13.c,v 1.34 2001/06/06 14:10:46 christos Exp $");
+__RCSID("$NetBSD: __fts13.c,v 1.35 2001/07/09 21:33:03 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -99,6 +99,8 @@
static void fts_padjust __P((FTS *, FTSENT *));
static FTSENT *fts_sort __P((FTS *, FTSENT *, size_t));
static u_short fts_stat __P((FTS *, FTSENT *, int));
+static int fts_safe_changedir __P((const FTS *, const FTSENT *, int,
+ const char *));
#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
@@ -397,7 +399,7 @@
* FTS_STOP or the fts_info field of the node.
*/
if (sp->fts_child) {
- if (CHDIR(sp, p->fts_accpath)) {
+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
p->fts_errno = errno;
p->fts_flags |= FTS_DONTCHDIR;
for (p = sp->fts_child; p; p = p->fts_link)
@@ -495,36 +497,9 @@
}
(void)close(p->fts_symfd);
} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
- !ISSET(FTS_NOCHDIR)) {
- int fd;
- struct STAT sb;
-
- if ((fd = open("..", O_RDONLY)) == -1) {
- SET(FTS_STOP);
- return (NULL);
- }
- if (fstat(fd, &sb) == -1) {
- saved_errno = errno;
- (void)close(fd);
- errno = saved_errno;
- SET(FTS_STOP);
- return (NULL);
- }
- if (sb.st_ino != p->fts_parent->fts_ino ||
- sb.st_dev != p->fts_parent->fts_dev) {
- (void)close(fd);
- errno = ENOENT;
- SET(FTS_STOP);
- return (NULL);
- }
- if (fchdir(fd) == -1) {
- saved_errno = errno;
- (void)close(fd);
- errno = saved_errno;
- SET(FTS_STOP);
- return (NULL);
- }
- (void)close(fd);
+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+ SET(FTS_STOP);
+ return (NULL);
}
p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
return (sp->fts_cur = p);
@@ -722,7 +697,7 @@
*/
cderrno = 0;
if (nlinks || type == BREAD) {
- if (FCHDIR(sp, dirfd(dirp))) {
+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
if (nlinks && type == BREAD)
cur->fts_errno = errno;
cur->fts_flags |= FTS_DONTCHDIR;
@@ -871,7 +846,8 @@
*/
if (descend && (type == BCHILD || !nitems) &&
(cur->fts_level == FTS_ROOTLEVEL ?
- FCHDIR(sp, sp->fts_rfd) : CHDIR(sp, ".."))) {
+ FCHDIR(sp, sp->fts_rfd) :
+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
cur->fts_info = FTS_ERR;
SET(FTS_STOP);
return (NULL);
@@ -1169,3 +1145,43 @@
max = len;
return (max + 1);
}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(sp, p, fd, path)
+ const FTS *sp;
+ const FTSENT *p;
+ int fd;
+ const char *path;
+{
+ int oldfd = fd, ret = -1;
+ struct STAT sb;
+
+ if (ISSET(FTS_NOCHDIR))
+ return 0;
+
+ if (fd < 0 && (fd = open(path, O_RDONLY)) == -1)
+ return -1;
+
+ if (fstat(fd, &sb) == -1)
+ goto bail;
+
+ if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) {
+ errno = ENOENT;
+ goto bail;
+ }
+
+ ret = fchdir(fd);
+
+bail:
+ if (oldfd < 0) {
+ int save_errno = errno;
+ (void)close(fd);
+ errno = save_errno;
+ }
+ return ret;
+}
Home |
Main Index |
Thread Index |
Old Index