option.c revision 222390
1151497Sru/*-
2151497Sru * Copyright (c) 1990, 1993, 1994
3151497Sru *	The Regents of the University of California.  All rights reserved.
4151497Sru *
5151497Sru * This code is derived from software contributed to Berkeley by
6151497Sru * Cimarron D. Taylor of the University of California, Berkeley.
7151497Sru *
8151497Sru * Redistribution and use in source and binary forms, with or without
9151497Sru * modification, are permitted provided that the following conditions
10151497Sru * are met:
11151497Sru * 1. Redistributions of source code must retain the above copyright
12151497Sru *    notice, this list of conditions and the following disclaimer.
13151497Sru * 2. Redistributions in binary form must reproduce the above copyright
14151497Sru *    notice, this list of conditions and the following disclaimer in the
15151497Sru *    documentation and/or other materials provided with the distribution.
16151497Sru * 4. Neither the name of the University nor the names of its contributors
17151497Sru *    may be used to endorse or promote products derived from this software
18151497Sru *    without specific prior written permission.
19151497Sru *
20151497Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21151497Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22151497Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23151497Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24151497Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25151497Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26151497Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27151497Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28151497Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29151497Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30151497Sru * SUCH DAMAGE.
31151497Sru */
32151497Sru
33151497Sru#ifndef lint
34151497Sru/*
35151497Srustatic char sccsid[] = "@(#)option.c	8.2 (Berkeley) 4/16/94";
36151497Sru*/
37151497Sru#endif /* not lint */
38151497Sru
39151497Sru#include <sys/cdefs.h>
40151497Sru__FBSDID("$FreeBSD: head/usr.bin/find/option.c 222390 2011-05-27 22:14:49Z jilles $");
41151497Sru
42151497Sru#include <sys/types.h>
43151497Sru#include <sys/stat.h>
44151497Sru
45151497Sru#include <err.h>
46151497Sru#include <fts.h>
47151497Sru#include <regex.h>
48151497Sru#include <stdio.h>
49151497Sru#include <stdlib.h>
50151497Sru#include <string.h>
51151497Sru
52151497Sru#include "find.h"
53151497Sru
54151497Srustatic int typecompare(const void *, const void *);
55151497Sru
56151497Sru/* NB: the following table must be sorted lexically. */
57151497Sru/* Options listed with C++ comments are in gnu find, but not our find */
58151497Srustatic OPTION const options[] = {
59151497Sru	{ "!",		c_simple,	f_not,		0 },
60151497Sru	{ "(",		c_simple,	f_openparen,	0 },
61151497Sru	{ ")",		c_simple,	f_closeparen,	0 },
62151497Sru	{ "-Bmin",	c_Xmin,		f_Xmin,		F_TIME_B },
63151497Sru	{ "-Bnewer",	c_newer,	f_newer,	F_TIME_B },
64151497Sru	{ "-Btime",	c_Xtime,	f_Xtime,	F_TIME_B },
65151497Sru	{ "-a",		c_and,		NULL,		0 },
66151497Sru	{ "-acl",	c_acl,		f_acl,		0 },
67151497Sru	{ "-amin",	c_Xmin,		f_Xmin,		F_TIME_A },
68151497Sru	{ "-and",	c_and,		NULL,		0 },
69151497Sru	{ "-anewer",	c_newer,	f_newer,	F_TIME_A },
70151497Sru	{ "-atime",	c_Xtime,	f_Xtime,	F_TIME_A },
71151497Sru	{ "-cmin",	c_Xmin,		f_Xmin,		F_TIME_C },
72151497Sru	{ "-cnewer",	c_newer,	f_newer,	F_TIME_C },
73151497Sru	{ "-ctime",	c_Xtime,	f_Xtime,	F_TIME_C },
74151497Sru	{ "-d",		c_depth,	f_depth,	0 },
75151497Sru// -daystart
76151497Sru	{ "-delete",	c_delete,	f_delete,	0 },
77151497Sru	{ "-depth",	c_depth,	f_depth,	0 },
78151497Sru	{ "-empty",	c_empty,	f_empty,	0 },
79151497Sru	{ "-exec",	c_exec,		f_exec,		0 },
80151497Sru	{ "-execdir",	c_exec,		f_exec,		F_EXECDIR },
81151497Sru	{ "-false",	c_simple,	f_false,	0 },
82151497Sru	{ "-flags",	c_flags,	f_flags,	0 },
83151497Sru// -fls
84151497Sru	{ "-follow",	c_follow,	f_always_true,	0 },
85151497Sru// -fprint
86151497Sru// -fprint0
87151497Sru// -fprintf
88151497Sru	{ "-fstype",	c_fstype,	f_fstype,	0 },
89151497Sru	{ "-gid",	c_group,	f_group,	0 },
90151497Sru	{ "-group",	c_group,	f_group,	0 },
91151497Sru	{ "-ignore_readdir_race",c_simple, f_always_true,0 },
92151497Sru	{ "-ilname",	c_name,		f_name,		F_LINK | F_IGNCASE },
93151497Sru	{ "-iname",	c_name,		f_name,		F_IGNCASE },
94151497Sru	{ "-inum",	c_inum,		f_inum,		0 },
95151497Sru	{ "-ipath",	c_name,		f_path,		F_IGNCASE },
96151497Sru	{ "-iregex",	c_regex,	f_regex,	F_IGNCASE },
97151497Sru	{ "-iwholename",c_name,		f_path,		F_IGNCASE },
98151497Sru	{ "-links",	c_links,	f_links,	0 },
99151497Sru	{ "-lname",	c_name,		f_name,		F_LINK },
100151497Sru	{ "-ls",	c_ls,		f_ls,		0 },
101151497Sru	{ "-maxdepth",	c_mXXdepth,	f_always_true,	F_MAXDEPTH },
102151497Sru	{ "-mindepth",	c_mXXdepth,	f_always_true,	0 },
103151497Sru	{ "-mmin",	c_Xmin,		f_Xmin,		0 },
104151497Sru	{ "-mnewer",	c_newer,	f_newer,	0 },
105151497Sru	{ "-mount",	c_xdev,		f_always_true,	0 },
106151497Sru	{ "-mtime",	c_Xtime,	f_Xtime,	0 },
107151497Sru	{ "-name",	c_name,		f_name,		0 },
108151497Sru	{ "-newer",	c_newer,	f_newer,	0 },
109151497Sru	{ "-newerBB",	c_newer,	f_newer,	F_TIME_B | F_TIME2_B },
110151497Sru	{ "-newerBa",	c_newer,	f_newer,	F_TIME_B | F_TIME2_A },
111151497Sru	{ "-newerBc",	c_newer,	f_newer,	F_TIME_B | F_TIME2_C },
112151497Sru	{ "-newerBm",	c_newer,	f_newer,	F_TIME_B },
113151497Sru	{ "-newerBt",	c_newer,	f_newer,	F_TIME_B | F_TIME2_T },
114151497Sru	{ "-neweraB",	c_newer,	f_newer,	F_TIME_A | F_TIME2_B },
115151497Sru	{ "-neweraa",	c_newer,	f_newer,	F_TIME_A | F_TIME2_A },
116151497Sru	{ "-newerac",	c_newer,	f_newer,	F_TIME_A | F_TIME2_C },
117151497Sru	{ "-neweram",	c_newer,	f_newer,	F_TIME_A },
118151497Sru	{ "-newerat",	c_newer,	f_newer,	F_TIME_A | F_TIME2_T },
119151497Sru	{ "-newercB",	c_newer,	f_newer,	F_TIME_C | F_TIME2_B },
120151497Sru	{ "-newerca",	c_newer,	f_newer,	F_TIME_C | F_TIME2_A },
121151497Sru	{ "-newercc",	c_newer,	f_newer,	F_TIME_C | F_TIME2_C },
122151497Sru	{ "-newercm",	c_newer,	f_newer,	F_TIME_C },
123151497Sru	{ "-newerct",	c_newer,	f_newer,	F_TIME_C | F_TIME2_T },
124151497Sru	{ "-newermB",	c_newer,	f_newer,	F_TIME2_B },
125151497Sru	{ "-newerma",	c_newer,	f_newer,	F_TIME2_A },
126151497Sru	{ "-newermc",	c_newer,	f_newer,	F_TIME2_C },
127151497Sru	{ "-newermm",	c_newer,	f_newer,	0 },
128151497Sru	{ "-newermt",	c_newer,	f_newer,	F_TIME2_T },
129151497Sru	{ "-nogroup",	c_nogroup,	f_nogroup,	0 },
130151497Sru	{ "-noignore_readdir_race",c_simple, f_always_true,0 },
131151497Sru	{ "-noleaf",	c_simple,	f_always_true,	0 },
132151497Sru	{ "-not",	c_simple,	f_not,		0 },
133151497Sru	{ "-nouser",	c_nouser,	f_nouser,	0 },
134151497Sru	{ "-o",		c_simple,	f_or,		0 },
135151497Sru	{ "-ok",	c_exec,		f_exec,		F_NEEDOK },
136151497Sru	{ "-okdir",	c_exec,		f_exec,		F_NEEDOK | F_EXECDIR },
137151497Sru	{ "-or",	c_simple,	f_or,		0 },
138151497Sru	{ "-path", 	c_name,		f_path,		0 },
139151497Sru	{ "-perm",	c_perm,		f_perm,		0 },
140151497Sru	{ "-print",	c_print,	f_print,	0 },
141151497Sru	{ "-print0",	c_print,	f_print0,	0 },
142151497Sru// -printf
143151497Sru	{ "-prune",	c_simple,	f_prune,	0 },
144151497Sru	{ "-quit",	c_simple,	f_quit,		0 },
145151497Sru	{ "-regex",	c_regex,	f_regex,	0 },
146151497Sru	{ "-samefile",	c_samefile,	f_inum,		0 },
147151497Sru	{ "-size",	c_size,		f_size,		0 },
148151497Sru	{ "-true",	c_simple,	f_always_true,	0 },
149151497Sru	{ "-type",	c_type,		f_type,		0 },
150151497Sru	{ "-uid",	c_user,		f_user,		0 },
151151497Sru	{ "-user",	c_user,		f_user,		0 },
152151497Sru	{ "-wholename",	c_name,		f_path,		0 },
153151497Sru	{ "-xdev",	c_xdev,		f_always_true,	0 },
154151497Sru// -xtype
155151497Sru};
156151497Sru
157151497Sru/*
158151497Sru * find_create --
159151497Sru *	create a node corresponding to a command line argument.
160151497Sru *
161151497Sru * TODO:
162151497Sru *	add create/process function pointers to node, so we can skip
163151497Sru *	this switch stuff.
164151497Sru */
165151497SruPLAN *
166151497Srufind_create(char ***argvp)
167151497Sru{
168151497Sru	OPTION *p;
169151497Sru	PLAN *new;
170151497Sru	char **argv;
171151497Sru
172151497Sru	argv = *argvp;
173151497Sru
174151497Sru	if ((p = lookup_option(*argv)) == NULL)
175151497Sru		errx(1, "%s: unknown primary or operator", *argv);
176151497Sru	++argv;
177151497Sru
178151497Sru	new = (p->create)(p, &argv);
179151497Sru	*argvp = argv;
180151497Sru	return (new);
181151497Sru}
182151497Sru
183151497SruOPTION *
184151497Srulookup_option(const char *name)
185151497Sru{
186151497Sru	OPTION tmp;
187151497Sru
188151497Sru	tmp.name = name;
189151497Sru	return ((OPTION *)bsearch(&tmp, options,
190151497Sru	    sizeof(options)/sizeof(OPTION), sizeof(OPTION), typecompare));
191151497Sru}
192151497Sru
193151497Srustatic int
194151497Srutypecompare(const void *a, const void *b)
195151497Sru{
196151497Sru	return (strcmp(((const OPTION *)a)->name, ((const OPTION *)b)->name));
197151497Sru}
198151497Sru