Final fix to make fts(3) spoof-proof.
authormillert <millert@openbsd.org>
Fri, 17 Jan 1997 06:12:53 +0000 (06:12 +0000)
committermillert <millert@openbsd.org>
Fri, 17 Jan 1997 06:12:53 +0000 (06:12 +0000)
lib/libc/gen/fts.c

index 6f95073..d2bf1bc 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: fts.c,v 1.5 1997/01/14 01:02:42 millert Exp $";
+static char rcsid[] = "$OpenBSD: fts.c,v 1.6 1997/01/17 06:12:53 millert Exp $";
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/param.h>
@@ -628,6 +628,8 @@ fts_build(sp, type)
                        cur->fts_flags |= FTS_DONTCHDIR;
                        descend = 0;
                        cderrno = errno;
+                       (void)closedir(dirp);
+                       dirp = NULL;
                } else
                        descend = 1;
        else
@@ -654,85 +656,87 @@ fts_build(sp, type)
 
        /* Read the directory, attaching each entry to the `link' pointer. */
        adjaddr = NULL;
-       for (head = tail = NULL, nitems = 0; dp = readdir(dirp);) {
-               if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
-                       continue;
-
-               if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
-                       goto mem1;
-               if (dp->d_namlen > maxlen) {
-                       if (fts_palloc(sp, (size_t)dp->d_namlen)) {
-                               /*
-                                * No more memory for path or structures.  Save
-                                * errno, free up the current structure and the
-                                * structures already allocated.
-                                */
-mem1:                          saved_errno = errno;
-                               if (p)
-                                       free(p);
-                               fts_lfree(head);
-                               (void)closedir(dirp);
-                               errno = saved_errno;
-                               cur->fts_info = FTS_ERR;
-                               SET(FTS_STOP);
-                               return (NULL);
+       if (dirp) {
+               for (head = tail = NULL, nitems = 0; dp = readdir(dirp);) {
+                       if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+                               continue;
+
+                       if ((p = fts_alloc(sp, dp->d_name, (int)dp->d_namlen)) == NULL)
+                               goto mem1;
+                       if (dp->d_namlen > maxlen) {
+                               if (fts_palloc(sp, (size_t)dp->d_namlen)) {
+                                       /*
+                                        * No more memory for path or structures.  Save
+                                        * errno, free up the current structure and the
+                                        * structures already allocated.
+                                        */
+       mem1:                           saved_errno = errno;
+                                       if (p)
+                                               free(p);
+                                       fts_lfree(head);
+                                       (void)closedir(dirp);
+                                       errno = saved_errno;
+                                       cur->fts_info = FTS_ERR;
+                                       SET(FTS_STOP);
+                                       return (NULL);
+                               }
+                               adjaddr = sp->fts_path;
+                               maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
                        }
-                       adjaddr = sp->fts_path;
-                       maxlen = sp->fts_pathlen - sp->fts_cur->fts_pathlen - 1;
-               }
 
-               p->fts_pathlen = len + dp->d_namlen + 1;
-               p->fts_parent = sp->fts_cur;
-               p->fts_level = level;
+                       p->fts_pathlen = len + dp->d_namlen + 1;
+                       p->fts_parent = sp->fts_cur;
+                       p->fts_level = level;
 
-#ifdef FTS_WHITEOUT
-               if (dp->d_type == DT_WHT)
-                       p->fts_flags |= FTS_ISW;
-#endif
+       #ifdef FTS_WHITEOUT
+                       if (dp->d_type == DT_WHT)
+                               p->fts_flags |= FTS_ISW;
+       #endif
 
-               if (cderrno) {
-                       if (nlinks) {
-                               p->fts_info = FTS_NS;
-                               p->fts_errno = cderrno;
-                       } else
+                       if (cderrno) {
+                               if (nlinks) {
+                                       p->fts_info = FTS_NS;
+                                       p->fts_errno = cderrno;
+                               } else
+                                       p->fts_info = FTS_NSOK;
+                               p->fts_accpath = cur->fts_accpath;
+                       } else if (nlinks == 0
+       #ifdef DT_DIR
+                           || nostat && 
+                           dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN
+       #endif
+                           ) {
+                               p->fts_accpath =
+                                   ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
                                p->fts_info = FTS_NSOK;
-                       p->fts_accpath = cur->fts_accpath;
-               } else if (nlinks == 0
-#ifdef DT_DIR
-                   || nostat && 
-                   dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN
-#endif
-                   ) {
-                       p->fts_accpath =
-                           ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
-                       p->fts_info = FTS_NSOK;
-               } else {
-                       /* Build a file name for fts_stat to stat. */
-                       if (ISSET(FTS_NOCHDIR)) {
-                               p->fts_accpath = p->fts_path;
-                               memmove(cp, p->fts_name, p->fts_namelen + 1);
-                       } else
-                               p->fts_accpath = p->fts_name;
-                       /* Stat it. */
-                       p->fts_info = fts_stat(sp, p, 0);
-
-                       /* Decrement link count if applicable. */
-                       if (nlinks > 0 && (p->fts_info == FTS_D ||
-                           p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
-                               --nlinks;
-               }
+                       } else {
+                               /* Build a file name for fts_stat to stat. */
+                               if (ISSET(FTS_NOCHDIR)) {
+                                       p->fts_accpath = p->fts_path;
+                                       memmove(cp, p->fts_name, p->fts_namelen + 1);
+                               } else
+                                       p->fts_accpath = p->fts_name;
+                               /* Stat it. */
+                               p->fts_info = fts_stat(sp, p, 0);
+
+                               /* Decrement link count if applicable. */
+                               if (nlinks > 0 && (p->fts_info == FTS_D ||
+                                   p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+                                       --nlinks;
+                       }
 
-               /* We walk in directory order so "ls -f" doesn't get upset. */
-               p->fts_link = NULL;
-               if (head == NULL)
-                       head = tail = p;
-               else {
-                       tail->fts_link = p;
-                       tail = p;
+                       /* We walk in directory order so "ls -f" doesn't get upset. */
+                       p->fts_link = NULL;
+                       if (head == NULL)
+                               head = tail = p;
+                       else {
+                               tail->fts_link = p;
+                               tail = p;
+                       }
+                       ++nitems;
                }
-               ++nitems;
+               (void)closedir(dirp);
        }
-       (void)closedir(dirp);
 
        /*
         * If had to realloc the path, adjust the addresses for the rest