+ /* --- Tests and actions --- */
+ else if (parm == PARM_print) {
+ need_print = 0;
+ /* GNU find ignores '!' here: "find ! -print" */
+ USE_FEATURE_FIND_NOT( invert_flag = 0; )
+ (void) ALLOC_ACTION(print);
+ }
+#if ENABLE_FEATURE_FIND_PRINT0
+ else if (parm == PARM_print0) {
+ need_print = 0;
+ USE_FEATURE_FIND_NOT( invert_flag = 0; )
+ (void) ALLOC_ACTION(print0);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_DEPTH
+ else if (parm == PARM_depth) {
+ recurse_flags |= ACTION_DEPTHFIRST;
+ }
+#endif
+#if ENABLE_FEATURE_FIND_PRUNE
+ else if (parm == PARM_prune) {
+ USE_FEATURE_FIND_NOT( invert_flag = 0; )
+ (void) ALLOC_ACTION(prune);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_DELETE
+ else if (parm == PARM_delete) {
+ need_print = 0;
+ recurse_flags |= ACTION_DEPTHFIRST;
+ (void) ALLOC_ACTION(delete);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_EXEC
+ else if (parm == PARM_exec) {
+ int i;
+ action_exec *ap;
+ need_print = 0;
+ USE_FEATURE_FIND_NOT( invert_flag = 0; )
+ ap = ALLOC_ACTION(exec);
+ ap->exec_argv = ++argv; /* first arg after -exec */
+ ap->exec_argc = 0;
+ while (1) {
+ if (!*argv) /* did not see ';' until end */
+ bb_error_msg_and_die("-exec CMD must end by ';'");
+ if (LONE_CHAR(argv[0], ';'))
+ break;
+ argv++;
+ ap->exec_argc++;
+ }
+ if (ap->exec_argc == 0)
+ bb_error_msg_and_die(bb_msg_requires_arg, arg);
+ ap->subst_count = xmalloc(ap->exec_argc * sizeof(int));
+ i = ap->exec_argc;
+ while (i--)
+ ap->subst_count[i] = count_subst(ap->exec_argv[i]);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_PAREN
+ else if (parm == PARM_char_brace) {
+ action_paren *ap;
+ char **endarg;
+ unsigned nested = 1;
+
+ endarg = argv;
+ while (1) {
+ if (!*++endarg)
+ bb_error_msg_and_die("unpaired '('");
+ if (LONE_CHAR(*endarg, '('))
+ nested++;
+ else if (LONE_CHAR(*endarg, ')') && !--nested) {
+ *endarg = NULL;
+ break;
+ }
+ }
+ ap = ALLOC_ACTION(paren);
+ ap->subexpr = parse_params(argv + 1);
+ *endarg = (char*) ")"; /* restore NULLed parameter */
+ argv = endarg;
+ }
+#endif
+ else if (parm == PARM_name || parm == PARM_iname) {
+ action_name *ap;
+ ap = ALLOC_ACTION(name);
+ ap->pattern = arg1;
+ ap->iname = (parm == PARM_iname);
+ }
+#if ENABLE_FEATURE_FIND_PATH
+ else if (parm == PARM_path) {
+ action_path *ap;
+ ap = ALLOC_ACTION(path);
+ ap->pattern = arg1;
+ }
+#endif
+#if ENABLE_FEATURE_FIND_REGEX
+ else if (parm == PARM_regex) {
+ action_regex *ap;
+ ap = ALLOC_ACTION(regex);
+ xregcomp(&ap->compiled_pattern, arg1, 0 /*cflags*/);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_TYPE
+ else if (parm == PARM_type) {
+ action_type *ap;
+ ap = ALLOC_ACTION(type);
+ ap->type_mask = find_type(arg1);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_PERM
+/* -perm mode File's permission bits are exactly mode (octal or symbolic).
+ * Symbolic modes use mode 0 as a point of departure.
+ * -perm -mode All of the permission bits mode are set for the file.
+ * -perm +mode Any of the permission bits mode are set for the file.
+ */
+ else if (parm == PARM_perm) {
+ action_perm *ap;
+ ap = ALLOC_ACTION(perm);
+ ap->perm_char = arg1[0];
+ arg1 = plus_minus_num(arg1);
+ ap->perm_mask = 0;
+ if (!bb_parse_mode(arg1, &ap->perm_mask))
+ bb_error_msg_and_die("invalid mode: %s", arg1);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_MTIME
+ else if (parm == PARM_mtime) {
+ action_mtime *ap;
+ ap = ALLOC_ACTION(mtime);
+ ap->mtime_char = arg1[0];
+ ap->mtime_days = xatoul(plus_minus_num(arg1));
+ }
+#endif
+#if ENABLE_FEATURE_FIND_MMIN
+ else if (parm == PARM_mmin) {
+ action_mmin *ap;
+ ap = ALLOC_ACTION(mmin);
+ ap->mmin_char = arg1[0];
+ ap->mmin_mins = xatoul(plus_minus_num(arg1));
+ }
+#endif
+#if ENABLE_FEATURE_FIND_NEWER
+ else if (parm == PARM_newer) {
+ struct stat stat_newer;
+ action_newer *ap;
+ ap = ALLOC_ACTION(newer);
+ xstat(arg1, &stat_newer);
+ ap->newer_mtime = stat_newer.st_mtime;
+ }
+#endif
+#if ENABLE_FEATURE_FIND_INUM
+ else if (parm == PARM_inum) {
+ action_inum *ap;
+ ap = ALLOC_ACTION(inum);
+ ap->inode_num = xatoul(arg1);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_USER
+ else if (parm == PARM_user) {
+ action_user *ap;
+ ap = ALLOC_ACTION(user);
+ ap->uid = bb_strtou(arg1, NULL, 10);
+ if (errno)
+ ap->uid = xuname2uid(arg1);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_GROUP
+ else if (parm == PARM_group) {
+ action_group *ap;
+ ap = ALLOC_ACTION(group);
+ ap->gid = bb_strtou(arg1, NULL, 10);
+ if (errno)
+ ap->gid = xgroup2gid(arg1);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_SIZE
+ else if (parm == PARM_size) {
+/* -size n[bckw]: file uses n units of space
+ * b (default): units are 512-byte blocks
+ * c: 1 byte
+ * k: kilobytes
+ * w: 2-byte words
+ */
+#if ENABLE_LFS
+#define XATOU_SFX xatoull_sfx
+#else
+#define XATOU_SFX xatoul_sfx
+#endif
+ static const struct suffix_mult find_suffixes[] = {
+ { "c", 1 },
+ { "w", 2 },
+ { "", 512 },
+ { "b", 512 },
+ { "k", 1024 },
+ { }
+ };
+ action_size *ap;
+ ap = ALLOC_ACTION(size);
+ ap->size_char = arg1[0];
+ ap->size = XATOU_SFX(plus_minus_num(arg1), find_suffixes);
+ }
+#endif
+#if ENABLE_FEATURE_FIND_CONTEXT
+ else if (parm == PARM_context) {
+ action_context *ap;
+ ap = ALLOC_ACTION(context);
+ ap->context = NULL;
+ /* SELinux headers erroneously declare non-const parameter */
+ if (selinux_raw_to_trans_context((char*)arg1, &ap->context))
+ bb_simple_perror_msg(arg1);
+ }
+#endif
+ else {
+ bb_error_msg("unrecognized: %s", arg);
+ bb_show_usage();
+ }
+ argv++;
+ }
+ return appp;
+#undef ALLOC_ACTION