X-Git-Url: https://git.saurik.com/apple/shell_cmds.git/blobdiff_plain/ddb4a88b2f582f98073e02a797c5299d71d9527e..b5fe885ee63a0f46dc66d5ba8af23cad26f23e04:/find/function.c diff --git a/find/function.c b/find/function.c index a7cbd26..a673a02 100644 --- a/find/function.c +++ b/find/function.c @@ -13,10 +13,6 @@ * 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. @@ -41,7 +37,7 @@ static const char sccsid[] = "@(#)function.c 8.10 (Berkeley) 5/4/95"; #endif /* not lint */ #include -__FBSDID("$FreeBSD: src/usr.bin/find/function.c,v 1.60 2008/02/24 00:01:06 imp Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/find/function.c,v 1.71 2011/06/13 05:22:07 avatar Exp $"); #include #include @@ -50,7 +46,6 @@ __FBSDID("$FreeBSD: src/usr.bin/find/function.c,v 1.60 2008/02/24 00:01:06 imp E #include #include #include -#include #include #include @@ -67,16 +62,17 @@ __FBSDID("$FreeBSD: src/usr.bin/find/function.c,v 1.60 2008/02/24 00:01:06 imp E #include #include -#include "find.h" - #ifdef __APPLE__ #include +#include #include #include #else #define COMPAT_MODE(func, mode) 1 #endif +#include "find.h" + static PLAN *palloc(OPTION *); static long long find_parsenum(PLAN *, const char *, char *, char *); static long long find_parsetime(PLAN *, const char *, char *); @@ -85,6 +81,7 @@ static char *nextarg(OPTION *, char ***); extern char **environ; static PLAN *lastexecplus = NULL; +int execplus_error; #define COMPARE(a, b) do { \ switch (plan->flags & F_ELG_MASK) { \ @@ -371,56 +368,115 @@ c_mXXdepth(OPTION *option, char ***argvp) return new; } -#ifndef __APPLE__ /* * -acl function -- * * Show files with EXTENDED ACL attributes. */ +#ifdef __APPLE__ int f_acl(PLAN *plan __unused, FTSENT *entry) { - int match, entries; + acl_t facl; + int match; acl_entry_t ae; + + match = 0; + if ((facl = acl_get_link_np(entry->fts_accpath, ACL_TYPE_EXTENDED)) != NULL) { + if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 0) { + match = 1; + } + acl_free(facl); + } + return match; +} +#else /* !__APPLE__ */ +int +f_acl(PLAN *plan __unused, FTSENT *entry) +{ acl_t facl; + acl_type_t acl_type; + int acl_supported = 0, ret, trivial; if (S_ISLNK(entry->fts_statp->st_mode)) return 0; - if ((match = pathconf(entry->fts_accpath, _PC_ACL_EXTENDED)) <= 0) { - if (match < 0 && errno != EINVAL) - warn("%s", entry->fts_accpath); - else - return 0; + ret = pathconf(entry->fts_accpath, _PC_ACL_NFS4); + if (ret > 0) { + acl_supported = 1; + acl_type = ACL_TYPE_NFS4; + } else if (ret < 0 && errno != EINVAL) { + warn("%s", entry->fts_accpath); + return (0); } - match = 0; - if ((facl = acl_get_file(entry->fts_accpath,ACL_TYPE_ACCESS)) != NULL) { - if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) { - /* - * POSIX.1e requires that ACLs of type ACL_TYPE_ACCESS - * must have at least three entries (owner, group, - * other). - */ - entries = 1; - while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1) { - if (++entries > 3) { - match = 1; - break; - } - } + if (acl_supported == 0) { + ret = pathconf(entry->fts_accpath, _PC_ACL_EXTENDED); + if (ret > 0) { + acl_supported = 1; + acl_type = ACL_TYPE_ACCESS; + } else if (ret < 0 && errno != EINVAL) { + warn("%s", entry->fts_accpath); + return (0); } - acl_free(facl); - } else + } + if (acl_supported == 0) + return (0); + + facl = acl_get_file(entry->fts_accpath, acl_type); + if (facl == NULL) { warn("%s", entry->fts_accpath); - return match; + return (0); + } + ret = acl_is_trivial_np(facl, &trivial); + acl_free(facl); + if (ret) { + warn("%s", entry->fts_accpath); + acl_free(facl); + return (0); + } + if (trivial) + return (0); + return (1); } +#endif /* __APPLE__ */ PLAN * c_acl(OPTION *option, char ***argvp __unused) { +#ifndef __APPLE__ ftsoptions &= ~FTS_NOSTAT; +#endif /* !__APPLE__ */ return (palloc(option)); } -#endif /* !__APPLE__ */ + +#ifdef __APPLE__ +int +f_xattr(PLAN *plan __unused, FTSENT *entry) +{ + ssize_t xattr; + int match; + + match = 0; + xattr = listxattr(entry->fts_accpath, NULL, 0, XATTR_NOFOLLOW); + if (xattr > 0) { + match = 1; + } + return match; +} + +int +f_xattrname(PLAN *plan, FTSENT *entry) +{ + ssize_t xattr; + int match; + + match = 0; + xattr = getxattr(entry->fts_accpath, plan->c_data, NULL, 0, 0, XATTR_NOFOLLOW); + if (xattr > 0) { + match = 1; + } + return match; +} +#endif /* __APPLE__ */ /* * -delete functions -- @@ -437,11 +493,13 @@ f_delete(PLAN *plan __unused, FTSENT *entry) /* sanity check */ if (isdepth == 0 || /* depth off */ - (ftsoptions & FTS_NOSTAT) || /* not stat()ing */ - !(ftsoptions & FTS_PHYSICAL) || /* physical off */ - (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */ + (ftsoptions & FTS_NOSTAT)) /* not stat()ing */ errx(1, "-delete: insecure options got turned on"); + if (!(ftsoptions & FTS_PHYSICAL) || /* physical off */ + (ftsoptions & FTS_LOGICAL)) /* or finally, logical on */ + errx(1, "-delete: forbidden when symlinks are followed"); + /* Potentially unsafe - do not accept relative paths whatsoever */ if (strchr(entry->fts_accpath, '/') != NULL) errx(1, "-delete: %s: relative path potentially not safe", @@ -451,7 +509,7 @@ f_delete(PLAN *plan __unused, FTSENT *entry) if ((entry->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) && !(entry->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && geteuid() == 0) - chflags(entry->fts_accpath, + lchflags(entry->fts_accpath, entry->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)); /* rmdir directories, unlink everything else */ @@ -472,8 +530,6 @@ c_delete(OPTION *option, char ***argvp __unused) { ftsoptions &= ~FTS_NOSTAT; /* no optimise */ - ftsoptions |= FTS_PHYSICAL; /* disable -follow */ - ftsoptions &= ~FTS_LOGICAL; /* disable -follow */ isoutput = 1; /* possible output */ isdepth = 1; /* -depth implied */ @@ -560,7 +616,7 @@ f_empty(PLAN *plan __unused, FTSENT *entry) empty = 1; dir = opendir(entry->fts_accpath); if (dir == NULL) - err(1, "%s", entry->fts_accpath); + return 0; for (dp = readdir(dir); dp; dp = readdir(dir)) if (dp->d_name[0] != '.' || (dp->d_name[1] != '\0' && @@ -664,8 +720,10 @@ doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv)) plan->e_psize = plan->e_pbsize; } pid = waitpid(pid, &status, 0); - if (plan->flags & F_EXECPLUS && WIFEXITED(status) && WEXITSTATUS(status)) - _exit(WEXITSTATUS(status)); + if (plan->flags & F_EXECPLUS && WIFEXITED(status) && WEXITSTATUS(status) && !execplus_error) { + /* Test 140 (8907531, 10656525) */ + execplus_error = WEXITSTATUS(status); + } return (pid != -1 && WIFEXITED(status) && !WEXITSTATUS(status)); } @@ -772,7 +830,7 @@ done: *argvp = argv + 1; /* Finish any pending -exec ... {} + functions. */ void -finish_execplus() +finish_execplus(void) { PLAN *p; @@ -853,7 +911,8 @@ f_fstype(PLAN *plan, FTSENT *entry) static dev_t curdev; /* need a guaranteed illegal dev value */ static int first = 1; struct statfs sb; - static int val_type, val_flags; + static int val_flags; + static char fstype[sizeof(sb.f_fstypename)]; char *p, save[2] = {0,0}; if ((plan->flags & F_MTMASK) == F_MTUNKNOWN) @@ -895,13 +954,13 @@ f_fstype(PLAN *plan, FTSENT *entry) * always copy both of them. */ val_flags = sb.f_flags; - val_type = sb.f_type; + strlcpy(fstype, sb.f_fstypename, sizeof(fstype)); } switch (plan->flags & F_MTMASK) { case F_MTFLAG: return val_flags & plan->mt_data; case F_MTTYPE: - return val_type == plan->mt_data; + return (strncmp(fstype, plan->c_data, sizeof(fstype)) == 0); default: abort(); } @@ -912,22 +971,11 @@ c_fstype(OPTION *option, char ***argvp) { char *fsname; PLAN *new; - struct vfsconf vfc; fsname = nextarg(option, argvp); ftsoptions &= ~FTS_NOSTAT; new = palloc(option); - - /* - * Check first for a filesystem name. - */ - if (getvfsbyname(fsname, &vfc) == 0) { - new->flags |= F_MTTYPE; - new->mt_data = vfc.vfc_typenum; - return new; - } - switch (*fsname) { case 'l': if (!strcmp(fsname, "local")) { @@ -945,12 +993,8 @@ c_fstype(OPTION *option, char ***argvp) break; } - /* - * We need to make filesystem checks for filesystems - * that exists but aren't in the kernel work. - */ - fprintf(stderr, "Warning: Unknown filesystem type %s\n", fsname); - new->flags |= F_MTUNKNOWN; + new->flags |= F_MTTYPE; + new->c_data = fsname; return new; } @@ -1101,11 +1145,24 @@ f_name(PLAN *plan, FTSENT *entry) { char fn[PATH_MAX]; const char *name; + ssize_t len; if (plan->flags & F_LINK) { - name = fn; - if (readlink(entry->fts_path, fn, sizeof(fn)) == -1) + /* + * The below test both avoids obviously useless readlink() + * calls and ensures that symlinks with existent target do + * not match if symlinks are being followed. + * Assumption: fts will stat all symlinks that are to be + * followed and will return the stat information. + */ + if (entry->fts_info != FTS_NSOK && entry->fts_info != FTS_SL && + entry->fts_info != FTS_SLNONE) return 0; + len = readlink(entry->fts_accpath, fn, sizeof(fn) - 1); + if (len == -1) + return 0; + fn[len] = '\0'; + name = fn; } else if (entry->fts_namelen == 0) { name = basename(entry->fts_path); } else @@ -1159,7 +1216,7 @@ c_newer(OPTION *option, char ***argvp) new = palloc(option); /* compare against what */ if (option->flags & F_TIME2_T) { - new->t_data = get_date(fn_or_tspec, (struct timeb *) 0); + new->t_data = get_date(fn_or_tspec); if (new->t_data == (time_t) -1) errx(1, "Can't parse date/time: %s", fn_or_tspec); } else { @@ -1169,6 +1226,8 @@ c_newer(OPTION *option, char ***argvp) new->t_data = sb.st_ctime; else if (option->flags & F_TIME2_A) new->t_data = sb.st_atime; + else if (option->flags & F_TIME2_B) + new->t_data = sb.st_birthtime; else new->t_data = sb.st_mtime; }