]> git.saurik.com Git - apple/shell_cmds.git/blobdiff - find/find.c
shell_cmds-216.60.1.tar.gz
[apple/shell_cmds.git] / find / find.c
index e5577ea637f435de1d60fee2e5733e0402c6df28..c59a75ab3789bdfb96492b6aacc493c34b15e960 100644 (file)
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
 #if 0
 static char sccsid[] = "@(#)find.c     8.5 (Berkeley) 8/5/94";
 #else
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/find/find.c,v 1.7.6.3 2001/05/06 09:53:22 phk Exp $";
 #endif
 #endif /* not lint */
 
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/find/find.c,v 1.23 2010/12/11 08:32:16 joel Exp $");
+
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -51,13 +48,23 @@ static const char rcsid[] =
 #include <fts.h>
 #include <regex.h>
 #include <stdio.h>
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
+
+#ifdef __APPLE__
+#include <get_compat.h>
 #include <unistd.h>
+#else
+#define COMPAT_MODE(func, mode) 1
+#endif
 
 #include "find.h"
 
-static int     find_compare __P((const FTSENT **s1, const FTSENT **s2));
+#ifdef __APPLE__
+static int find_compare(const FTSENT **s1, const FTSENT **s2);
+#else /* !__APPLE__ */
+static int find_compare(const FTSENT * const *s1, const FTSENT * const *s2);
+#endif /* __APPLE__ */
 
 /*
  * find_compare --
@@ -66,8 +73,11 @@ static int   find_compare __P((const FTSENT **s1, const FTSENT **s2));
  *     order within each directory.
  */
 static int
-find_compare(s1, s2)
-       const FTSENT **s1, **s2;
+#ifdef __APPLE__
+find_compare(const FTSENT **s1, const FTSENT **s2)
+#else /* !__APPLE__ */
+find_compare(const FTSENT * const *s1, const FTSENT * const *s2)
+#endif /* __APPLE__ */
 {
 
        return (strcoll((*s1)->fts_name, (*s2)->fts_name));
@@ -79,8 +89,7 @@ find_compare(s1, s2)
  *     command arguments.
  */
 PLAN *
-find_formplan(argv)
-       char **argv;
+find_formplan(char *argv[])
 {
        PLAN *plan, *tail, *new;
 
@@ -118,23 +127,23 @@ find_formplan(argv)
         */
        if (!isoutput) {
                OPTION *p;
-               char **argv = 0;
+               char **argv1 = 0;
 
                if (plan == NULL) {
-                       p = option("-print");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option("-print");
+                       new = (p->create)(p, &argv1);
                        tail = plan = new;
                } else {
-                       p = option("(");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option("(");
+                       new = (p->create)(p, &argv1);
                        new->next = plan;
                        plan = new;
-                       p = option(")");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option(")");
+                       new = (p->create)(p, &argv1);
                        tail->next = new;
                        tail = new;
-                       p = option("-print");
-                       new = (p->create)(p, &argv);
+                       p = lookup_option("-print");
+                       new = (p->create)(p, &argv1);
                        tail->next = new;
                        tail = new;
                }
@@ -201,16 +210,14 @@ FTS *tree;                        /* pointer to top of FTS hierarchy */
  *     over all FTSENT's returned for the given search paths.
  */
 int
-find_execute(plan, paths)
-       PLAN *plan;             /* search plan */
-       char **paths;           /* array of pathnames to traverse */
+find_execute(PLAN *plan, char *paths[])
 {
-       register FTSENT *entry;
+       FTSENT *entry;
        PLAN *p;
        int rval;
-       char    **myPaths;
-       int     nonSearchableDirFound = 0;
-       int                     pathIndex;
+       char **myPaths;
+       int nonSearchableDirFound = 0;
+       int pathIndex;
        struct stat statInfo;
 
        /* special-case directories specified on command line - explicitly examine
@@ -218,15 +225,28 @@ find_execute(plan, paths)
         * (whether or not it's empty). UNIX conformance... <sigh>
         */
                
+       int strict_symlinks = (ftsoptions & (FTS_COMFOLLOW|FTS_LOGICAL))
+         && COMPAT_MODE("bin/find", "unix2003");
+
        myPaths = addPath(NULL, NULL);
        for (pathIndex = 0; paths[pathIndex] != NULL; ++pathIndex) {
-               /* retrieve mode bits, and examine "searchable" bit of directories */
-               /* exempt root from POSIX conformance */
-               if (getuid() && (stat(paths[pathIndex], &statInfo) == 0) && ((statInfo.st_mode & S_IFMT) == S_IFDIR)) {
-                       if ((statInfo.st_mode & (S_IXUSR + S_IXGRP + S_IXOTH)) != 0) {
+               int stat_ret = stat(paths[pathIndex], &statInfo);
+               int stat_errno = errno;
+               if (strict_symlinks && stat_ret < 0) {
+                   if (stat_errno == ELOOP) {
+                       errx(1, "Symlink loop resolving %s", paths[pathIndex]);
+                   }
+               }
+
+               /* retrieve mode bits, and examine "searchable" bit of 
+                 directories, exempt root from POSIX conformance */
+               if (COMPAT_MODE("bin/find", "unix2003") && getuid() 
+                 && stat_ret == 0 
+                 && ((statInfo.st_mode & S_IFMT) == S_IFDIR)) {
+                       if (access(paths[pathIndex], X_OK) == 0) {
                                myPaths = addPath(myPaths, paths[pathIndex]);
                        } else {
-                               if (errno != ENAMETOOLONG) {    /* if name is too long, just let existing logic handle it */
+                               if (stat_errno != ENAMETOOLONG) {       /* if name is too long, just let existing logic handle it */
                                        warnx("%s: Permission denied", paths[pathIndex]);
                                        nonSearchableDirFound = 1;
                                }
@@ -246,6 +266,11 @@ find_execute(plan, paths)
                err(1, "ftsopen");
 
        for (rval = nonSearchableDirFound; (entry = fts_read(tree)) != NULL;) {
+               if (maxdepth != -1 && entry->fts_level >= maxdepth) {
+                       if (fts_set(tree, entry, FTS_SKIP))
+                               err(1, "%s", entry->fts_path);
+               }
+
                switch (entry->fts_info) {
                case FTS_D:
                        if (isdepth)
@@ -285,16 +310,14 @@ find_execute(plan, paths)
                 * the work specified by the user on the command line.
                 */
                for (p = plan; p && (p->execute)(p, entry); p = p->next);
-
-               if (maxdepth != -1 && entry->fts_level >= maxdepth) {
-                       if (fts_set(tree, entry, FTS_SKIP))
-                       err(1, "%s", entry->fts_path);
-                       continue;
-               }
+       }
+       free (myPaths);
+       finish_execplus();
+       if (execplus_error) {
+               exit(execplus_error);
        }
        if (errno)
                err(1, "fts_read");
-
-       free (myPaths);
+       fts_close(tree);
        return (rval);
 }