aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/find.c722
1 files changed, 361 insertions, 361 deletions
diff --git a/toys/pending/find.c b/toys/pending/find.c
index d61e48c3..9728090b 100644
--- a/toys/pending/find.c
+++ b/toys/pending/find.c
@@ -9,17 +9,17 @@
USE_FIND(NEWTOY(find, "?", TOYFLAG_USR|TOYFLAG_BIN))
config FIND
- bool "find"
- default n
- help
- usage: find [<dir>] [<options]
-
- -name <pattern> match pattern
- -type [fcdl] match file type
- !, -a, -o not, and , or
- (, ) group expressions
- -mtime [-+]n match file modification time (to within 24 hours)
- \t\t +=greater (older) than, -=less (younger) than
+ bool "find"
+ default n
+ help
+ usage: find [<dir>] [<options]
+
+ -name <pattern> match pattern
+ -type [fcdl] match file type
+ !, -a, -o not, and , or
+ (, ) group expressions
+ -mtime [-+]n match file modification time (to within 24 hours)
+ \t\t +=greater (older) than, -=less (younger) than
*/
/* To Do:
@@ -33,20 +33,20 @@ config FIND
int have_action;
struct filter_node {
- struct filter_node *next;
- int op;
- union {
- char *name_regex;
- struct {
- char time_op;
- time_t time;
- } t;
- mode_t type;
- struct {
- int arg_path_index;
- char **exec_args;
- } e;
- } data;
+ struct filter_node *next;
+ int op;
+ union {
+ char *name_regex;
+ struct {
+ char time_op;
+ time_t time;
+ } t;
+ mode_t type;
+ struct {
+ int arg_path_index;
+ char **exec_args;
+ } e;
+ } data;
};
static struct filter_node *filter_root;
@@ -77,361 +77,361 @@ static struct filter_node *filter_root;
*/
static int do_exec(struct filter_node *filter, struct dirtree *node)
{
- char *path;
- int plen;
- char **arg_array;
- pid_t pid;
- int ccode;
- int status;
-
- arg_array = filter->data.e.exec_args;
- if (filter->data.e.arg_path_index) {
- path = dirtree_path(node, &plen);
- arg_array[filter->data.e.arg_path_index] = path;
- } else {
- path = NULL;
- }
-
- pid = fork();
- if (!pid) {
- /* child */
- xexec(arg_array);
- } else {
- /* parent */
- /* wait for child */
- waitpid(pid, &status, 0);
- ccode = WEXITSTATUS(status);
- }
- free(path);
-
- return ccode;
+ char *path;
+ int plen;
+ char **arg_array;
+ pid_t pid;
+ int ccode;
+ int status;
+
+ arg_array = filter->data.e.exec_args;
+ if (filter->data.e.arg_path_index) {
+ path = dirtree_path(node, &plen);
+ arg_array[filter->data.e.arg_path_index] = path;
+ } else {
+ path = NULL;
+ }
+
+ pid = fork();
+ if (!pid) {
+ /* child */
+ xexec(arg_array);
+ } else {
+ /* parent */
+ /* wait for child */
+ waitpid(pid, &status, 0);
+ ccode = WEXITSTATUS(status);
+ }
+ free(path);
+
+ return ccode;
}
/* prefix evaluator */
/* returns 0 for failure or 1 for success */
static int evaluate(struct filter_node *filter, struct dirtree *node,
- struct filter_node **fnext)
+ struct filter_node **fnext)
{
- int result;
- char *path;
- int plen = 0;
- struct stat st_buf;
- time_t node_time;
- char terminator;
-
- /* if no filters, success */
- if (!filter) {
- *fnext = NULL;
- return 1;
- }
-
- if (filter->op==OP_NOT) {
- return !evaluate(filter->next, node, fnext);
- }
- if (filter->op==OP_OR) {
- return evaluate(filter->next, node, fnext) || evaluate(*fnext, node, fnext);
- }
- if (filter->op==OP_AND) {
- return evaluate(filter->next, node, fnext) && evaluate(*fnext, node, fnext);
- }
- /* we're down to single operations, mark our position */
- *fnext = filter->next;
- if (filter->op==CHECK_NAME) {
- // TODO: Do a regex comparison
- return !strcmp(filter->data.name_regex, node->name);
- }
- if (filter->op==CHECK_MTIME) {
- /* do mtime check */
- path = dirtree_path(node, &plen);
- result = stat(path, &st_buf);
- free(path);
- if (result<0) {
- return 0;
- }
- node_time = st_buf.st_mtime/SECONDS_PER_DAY;
- result = 1;
- switch (filter->data.t.time_op) {
- /* do time compare here */
- case TEST_LT:
- /* FIXTHIS - should result be < or <= ?*/
- if (node_time > filter->data.t.time)
- result = 0;
- break;
- case TEST_GT:
- if (node_time < filter->data.t.time)
- result = 0;
- break;
- case TEST_EQ:
- if (node_time != filter->data.t.time)
- result = 0;
- break;
- default:
- /* how'd I get here? */
- result = 0;
- break;
- }
- return result;
-
- }
- if (filter->op==CHECK_TYPE) {
- path = dirtree_path(node, &plen);
- result = lstat(path, &st_buf);
- free(path);
- if (result<0) {
- return 0;
- }
- return (st_buf.st_mode & S_IFMT) == filter->data.type;
- }
-
-
- if (filter->op==ACTION_PRINT || filter->op==ACTION_PRINT0) {
- if (filter->op==ACTION_PRINT) {
- terminator = '\n';
- } else {
- terminator = 0;
- }
- path = dirtree_path(node, &plen);
- printf("%s%c", path, terminator);
- free(path);
- return 1;
- }
-
- if (filter->op==ACTION_EXEC) {
- return !do_exec(filter, node);
- }
- error_msg("Ran out of operations in filter list!");
- return 1;
+ int result;
+ char *path;
+ int plen = 0;
+ struct stat st_buf;
+ time_t node_time;
+ char terminator;
+
+ /* if no filters, success */
+ if (!filter) {
+ *fnext = NULL;
+ return 1;
+ }
+
+ if (filter->op==OP_NOT) {
+ return !evaluate(filter->next, node, fnext);
+ }
+ if (filter->op==OP_OR) {
+ return evaluate(filter->next, node, fnext) || evaluate(*fnext, node, fnext);
+ }
+ if (filter->op==OP_AND) {
+ return evaluate(filter->next, node, fnext) && evaluate(*fnext, node, fnext);
+ }
+ /* we're down to single operations, mark our position */
+ *fnext = filter->next;
+ if (filter->op==CHECK_NAME) {
+ // TODO: Do a regex comparison
+ return !strcmp(filter->data.name_regex, node->name);
+ }
+ if (filter->op==CHECK_MTIME) {
+ /* do mtime check */
+ path = dirtree_path(node, &plen);
+ result = stat(path, &st_buf);
+ free(path);
+ if (result<0) {
+ return 0;
+ }
+ node_time = st_buf.st_mtime/SECONDS_PER_DAY;
+ result = 1;
+ switch (filter->data.t.time_op) {
+ /* do time compare here */
+ case TEST_LT:
+ /* FIXTHIS - should result be < or <= ?*/
+ if (node_time > filter->data.t.time)
+ result = 0;
+ break;
+ case TEST_GT:
+ if (node_time < filter->data.t.time)
+ result = 0;
+ break;
+ case TEST_EQ:
+ if (node_time != filter->data.t.time)
+ result = 0;
+ break;
+ default:
+ /* how'd I get here? */
+ result = 0;
+ break;
+ }
+ return result;
+
+ }
+ if (filter->op==CHECK_TYPE) {
+ path = dirtree_path(node, &plen);
+ result = lstat(path, &st_buf);
+ free(path);
+ if (result<0) {
+ return 0;
+ }
+ return (st_buf.st_mode & S_IFMT) == filter->data.type;
+ }
+
+
+ if (filter->op==ACTION_PRINT || filter->op==ACTION_PRINT0) {
+ if (filter->op==ACTION_PRINT) {
+ terminator = '\n';
+ } else {
+ terminator = 0;
+ }
+ path = dirtree_path(node, &plen);
+ printf("%s%c", path, terminator);
+ free(path);
+ return 1;
+ }
+
+ if (filter->op==ACTION_EXEC) {
+ return !do_exec(filter, node);
+ }
+ error_msg("Ran out of operations in filter list!");
+ return 1;
}
static int check_node_callback(struct dirtree *node)
{
- char *path;
- int plen = 0;
- int result;
- struct filter_node *junk;
-
- /* only recurse on "." at the root */
- /* so, don't recurse on 1) non-root "." and 2) any ".." */
-
- if (node->name[0] == '.' &&
- ((!node->name[1] && node->parent) ||
- (node->name[1]=='.' && !node->name[2])))
- return 0;
-
- result = evaluate(filter_root, node, &junk);
- if (result & !have_action) {
- /* default action is just print the path */
- path = dirtree_path(node, &plen);
- printf("%s\n", path);
- free(path);
- }
- return DIRTREE_RECURSE;
+ char *path;
+ int plen = 0;
+ int result;
+ struct filter_node *junk;
+
+ /* only recurse on "." at the root */
+ /* so, don't recurse on 1) non-root "." and 2) any ".." */
+
+ if (node->name[0] == '.' &&
+ ((!node->name[1] && node->parent) ||
+ (node->name[1]=='.' && !node->name[2])))
+ return 0;
+
+ result = evaluate(filter_root, node, &junk);
+ if (result & !have_action) {
+ /* default action is just print the path */
+ path = dirtree_path(node, &plen);
+ printf("%s\n", path);
+ free(path);
+ }
+ return DIRTREE_RECURSE;
}
static void build_filter_list(void)
{
- struct filter_node *node_list;
- struct filter_node *op_stack;
- struct filter_node *node, *op_node;
- struct filter_node *next;
-
- char *arg, **arg_array;
- int i, j;
-
- /* part optargs here and build a filter list in prefix format */
-
- node_list = NULL;
- toybuf[0] = 0;
- have_action = 0;
- for(i=0; toys.optargs[i]; i++) {
- node = (struct filter_node *)
- xmalloc(sizeof(struct filter_node));
- node->op = OP_UNKNOWN;
- arg = toys.optargs[i];
- if (!strcmp(arg, "-o")) {
- node->op = OP_OR;
- }
- if (!strcmp(arg, "-a")) {
- node->op = OP_AND;
- }
- if (!strcmp(arg, "!")) {
- node->op = OP_NOT;
- }
- if (!strcmp(arg, "(")) {
- node->op = LPAREN;
- }
- if (!strcmp(arg, ")")) {
- node->op = RPAREN;
- }
-
- if (!strcmp(arg, "-name")) {
- node->op = CHECK_NAME;
- arg = toys.optargs[++i];
- if (!arg) error_exit("Missing argument to -name\n");
- node->data.name_regex = arg;
- }
-
- if (!strcmp(arg, "-mtime")) {
- node->op = CHECK_MTIME;
- arg = toys.optargs[++i];
- if (!arg) error_exit("Missing argument to -mtime\n");
- switch(arg[0]) {
- case '+':
- node->data.t.time_op=TEST_GT;
- arg++;
- break;
- case '-':
- node->data.t.time_op=TEST_LT;
- arg++;
- break;
- default:
- node->data.t.time_op=TEST_EQ;
- break;
- }
- /* convert to days (very crudely) */
- node->data.t.time = atoi(arg)/SECONDS_PER_DAY;
- }
-
- if (!strcmp(arg, "-type")) {
- node->op = CHECK_TYPE;
- arg = toys.optargs[++i];
- if (!arg) error_exit("Missing argument to -type\n");
- switch(arg[0]) {
- case 'f':
- node->data.type = S_IFREG;
- break;
- case 'd':
- node->data.type = S_IFDIR;
- break;
- case 'c':
- node->data.type = S_IFCHR;
- break;
- case 'b':
- node->data.type = S_IFBLK;
- break;
- case 'l':
- node->data.type = S_IFLNK;
- break;
- case 's':
- node->data.type = S_IFSOCK;
- break;
- case 'p':
- /* named pipe */
- node->data.type = S_IFIFO;
- break;
- default:
- error_exit("Unknown file type '%s'\n", arg);
- }
- }
- if (!strcmp(arg, "-print")) {
- node->op = ACTION_PRINT;
- have_action = 1;
- }
- if (!strcmp(arg, "-print0")) {
- node->op = ACTION_PRINT0;
- have_action = 1;
- }
- if (!strcmp(arg, "-exec")) {
- node->op = ACTION_EXEC;
- have_action = 1;
- arg_array = xmalloc(sizeof(char *));
- arg = toys.optargs[++i];
- for (j = 0; arg && strcmp(arg, ";"); j++) {
- /* new method */
- arg_array = xrealloc(arg_array, sizeof(char *) * (j+2));
- arg_array[j] = arg;
- if (!strcmp(arg, "{}")) {
- node->data.e.arg_path_index = j;
- }
-
- arg = toys.optargs[++i];
- }
- if (!arg) error_exit("Missing ';' in exec command\n");
- arg_array[j] = 0;
- node->data.e.exec_args = arg_array;
- }
- if (node->op == OP_UNKNOWN) {
- if (arg[0] == '-') error_exit("Unknown option '%s'\n", arg);
- else {
- /* use toybuf as start directory */
- strcpy(toybuf, arg);
- }
- } else {
- /* push node */
- node->next = node_list;;
- node_list = node;
- }
-
- }
-
- /* now convert from infix to prefix */
- filter_root = NULL;
- op_stack = NULL;
- node = node_list;
- while( node ) {
- next = node->next;
- switch( node->op ) {
- case OP_AND:
- case OP_OR:
- case OP_NOT:
- case RPAREN:
- /* push to opstack */
- node->next = op_stack;
- op_stack = node;
- break;
- case LPAREN:
- free(node);
- /* pop opstack to output (up to rparen) */
- op_node = op_stack;
- while (op_node && op_node->op != RPAREN) {
- /* remove from op_stack */
- op_stack = op_node->next;
- /* push to output */
- op_node->next = filter_root;
- filter_root = op_node;
- /* get next node */
- op_node = op_stack;
- }
- /* rparen should be on op_stack */
- if (!op_stack) error_exit("Missing right paren\n");
- /* remove rparen from op_stack */
- op_stack = op_stack->next;
- free(op_node);
- break;
- default:
- /* push to output */
- node->next = filter_root;
- filter_root = node;
- break;
- }
- node = next;
- }
- /* end of input - push opstack to output */
- /* pop opstack to output till empty */
- op_node = op_stack;
- while (op_node) {
- /*if (op_node->op == RPAREN || op_node->op == LPAREN) {
- error_exit("Error: extra paren found\n");
- }
- */
- op_stack = op_node->next;
- op_node->next = filter_root;
- filter_root = op_node;
- op_node = op_stack;
- }
+ struct filter_node *node_list;
+ struct filter_node *op_stack;
+ struct filter_node *node, *op_node;
+ struct filter_node *next;
+
+ char *arg, **arg_array;
+ int i, j;
+
+ /* part optargs here and build a filter list in prefix format */
+
+ node_list = NULL;
+ toybuf[0] = 0;
+ have_action = 0;
+ for(i=0; toys.optargs[i]; i++) {
+ node = (struct filter_node *)
+ xmalloc(sizeof(struct filter_node));
+ node->op = OP_UNKNOWN;
+ arg = toys.optargs[i];
+ if (!strcmp(arg, "-o")) {
+ node->op = OP_OR;
+ }
+ if (!strcmp(arg, "-a")) {
+ node->op = OP_AND;
+ }
+ if (!strcmp(arg, "!")) {
+ node->op = OP_NOT;
+ }
+ if (!strcmp(arg, "(")) {
+ node->op = LPAREN;
+ }
+ if (!strcmp(arg, ")")) {
+ node->op = RPAREN;
+ }
+
+ if (!strcmp(arg, "-name")) {
+ node->op = CHECK_NAME;
+ arg = toys.optargs[++i];
+ if (!arg) error_exit("Missing argument to -name\n");
+ node->data.name_regex = arg;
+ }
+
+ if (!strcmp(arg, "-mtime")) {
+ node->op = CHECK_MTIME;
+ arg = toys.optargs[++i];
+ if (!arg) error_exit("Missing argument to -mtime\n");
+ switch(arg[0]) {
+ case '+':
+ node->data.t.time_op=TEST_GT;
+ arg++;
+ break;
+ case '-':
+ node->data.t.time_op=TEST_LT;
+ arg++;
+ break;
+ default:
+ node->data.t.time_op=TEST_EQ;
+ break;
+ }
+ /* convert to days (very crudely) */
+ node->data.t.time = atoi(arg)/SECONDS_PER_DAY;
+ }
+
+ if (!strcmp(arg, "-type")) {
+ node->op = CHECK_TYPE;
+ arg = toys.optargs[++i];
+ if (!arg) error_exit("Missing argument to -type\n");
+ switch(arg[0]) {
+ case 'f':
+ node->data.type = S_IFREG;
+ break;
+ case 'd':
+ node->data.type = S_IFDIR;
+ break;
+ case 'c':
+ node->data.type = S_IFCHR;
+ break;
+ case 'b':
+ node->data.type = S_IFBLK;
+ break;
+ case 'l':
+ node->data.type = S_IFLNK;
+ break;
+ case 's':
+ node->data.type = S_IFSOCK;
+ break;
+ case 'p':
+ /* named pipe */
+ node->data.type = S_IFIFO;
+ break;
+ default:
+ error_exit("Unknown file type '%s'\n", arg);
+ }
+ }
+ if (!strcmp(arg, "-print")) {
+ node->op = ACTION_PRINT;
+ have_action = 1;
+ }
+ if (!strcmp(arg, "-print0")) {
+ node->op = ACTION_PRINT0;
+ have_action = 1;
+ }
+ if (!strcmp(arg, "-exec")) {
+ node->op = ACTION_EXEC;
+ have_action = 1;
+ arg_array = xmalloc(sizeof(char *));
+ arg = toys.optargs[++i];
+ for (j = 0; arg && strcmp(arg, ";"); j++) {
+ /* new method */
+ arg_array = xrealloc(arg_array, sizeof(char *) * (j+2));
+ arg_array[j] = arg;
+ if (!strcmp(arg, "{}")) {
+ node->data.e.arg_path_index = j;
+ }
+
+ arg = toys.optargs[++i];
+ }
+ if (!arg) error_exit("Missing ';' in exec command\n");
+ arg_array[j] = 0;
+ node->data.e.exec_args = arg_array;
+ }
+ if (node->op == OP_UNKNOWN) {
+ if (arg[0] == '-') error_exit("Unknown option '%s'\n", arg);
+ else {
+ /* use toybuf as start directory */
+ strcpy(toybuf, arg);
+ }
+ } else {
+ /* push node */
+ node->next = node_list;;
+ node_list = node;
+ }
+
+ }
+
+ /* now convert from infix to prefix */
+ filter_root = NULL;
+ op_stack = NULL;
+ node = node_list;
+ while( node ) {
+ next = node->next;
+ switch( node->op ) {
+ case OP_AND:
+ case OP_OR:
+ case OP_NOT:
+ case RPAREN:
+ /* push to opstack */
+ node->next = op_stack;
+ op_stack = node;
+ break;
+ case LPAREN:
+ free(node);
+ /* pop opstack to output (up to rparen) */
+ op_node = op_stack;
+ while (op_node && op_node->op != RPAREN) {
+ /* remove from op_stack */
+ op_stack = op_node->next;
+ /* push to output */
+ op_node->next = filter_root;
+ filter_root = op_node;
+ /* get next node */
+ op_node = op_stack;
+ }
+ /* rparen should be on op_stack */
+ if (!op_stack) error_exit("Missing right paren\n");
+ /* remove rparen from op_stack */
+ op_stack = op_stack->next;
+ free(op_node);
+ break;
+ default:
+ /* push to output */
+ node->next = filter_root;
+ filter_root = node;
+ break;
+ }
+ node = next;
+ }
+ /* end of input - push opstack to output */
+ /* pop opstack to output till empty */
+ op_node = op_stack;
+ while (op_node) {
+ /*if (op_node->op == RPAREN || op_node->op == LPAREN) {
+ error_exit("Error: extra paren found\n");
+ }
+ */
+ op_stack = op_node->next;
+ op_node->next = filter_root;
+ filter_root = op_node;
+ op_node = op_stack;
+ }
}
void find_main(void)
{
- /* parse filters, if present */
- /* also, fill toybuf with the directory to start in, if present */
- build_filter_list();
+ /* parse filters, if present */
+ /* also, fill toybuf with the directory to start in, if present */
+ build_filter_list();
- /* FIXTHIS - parse actions, if present */
+ /* FIXTHIS - parse actions, if present */
- if (!toybuf[0]) {
- strcpy(toybuf, ".");
- }
- dirtree_read(toybuf, check_node_callback);
+ if (!toybuf[0]) {
+ strcpy(toybuf, ".");
+ }
+ dirtree_read(toybuf, check_node_callback);
}