Add find(1) -iname and -mount.
Fix -xdev semantics as clarified by POSIX.
This commit is contained in:
parent
5857cd592b
commit
51027e79f2
1 changed files with 24 additions and 11 deletions
35
utils/find.c
35
utils/find.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2015, 2016, 2021 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2013, 2015, 2016, 2021, 2024 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -118,6 +118,7 @@ struct expr_links
|
|||
struct expr_name
|
||||
{
|
||||
const char* pattern;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct expr_newer
|
||||
|
@ -523,7 +524,8 @@ static int evaluate(const struct expr* expr,
|
|||
st->st_nlink > expr->expr_links.n :
|
||||
st->st_nlink == expr->expr_links.n;
|
||||
else if ( expr->kind == EXPR_NAME )
|
||||
value = fnmatch(expr->expr_name.pattern, name, 0) == 0;
|
||||
value = fnmatch(expr->expr_name.pattern, name,
|
||||
expr->expr_name.flags) == 0;
|
||||
else if ( expr->kind == EXPR_NEWER )
|
||||
{
|
||||
const struct timespec* ts = pick_time(st, expr->expr_newer.t);
|
||||
|
@ -760,6 +762,7 @@ static bool find(const struct expr* expr,
|
|||
bool depth,
|
||||
enum symderef symderef,
|
||||
bool xdev,
|
||||
bool mount,
|
||||
size_t mindepth,
|
||||
size_t maxdepth)
|
||||
{
|
||||
|
@ -779,8 +782,8 @@ static bool find(const struct expr* expr,
|
|||
new_state.relpath = state->relpath + offset;
|
||||
new_state.path = state->path;
|
||||
new_state.type = state->type;
|
||||
bool result =
|
||||
find(expr, &new_state, depth, symderef, xdev, mindepth, maxdepth);
|
||||
bool result = find(expr, &new_state, depth, symderef, xdev, mount,
|
||||
mindepth, maxdepth);
|
||||
if ( new_dirfd != state->dirfd )
|
||||
close(new_dirfd);
|
||||
return result;
|
||||
|
@ -813,7 +816,7 @@ static bool find(const struct expr* expr,
|
|||
goto next;
|
||||
}
|
||||
state->has_stat = true;
|
||||
if ( xdev && state->parent &&
|
||||
if ( (xdev || mount) && state->parent &&
|
||||
state->st.st_dev != state->parent->st.st_dev )
|
||||
goto next;
|
||||
}
|
||||
|
@ -859,8 +862,9 @@ static bool find(const struct expr* expr,
|
|||
symderef = SYMDEREF_NONE;
|
||||
fstat(state->fd, &state->st);
|
||||
state->has_stat = true;
|
||||
if ( xdev && state->parent &&
|
||||
state->st.st_dev != state->parent->st.st_dev )
|
||||
bool is_mount_point =
|
||||
state->parent && state->st.st_dev != state->parent->st.st_dev;
|
||||
if ( mount && is_mount_point )
|
||||
{
|
||||
close(state->fd);
|
||||
goto next;
|
||||
|
@ -888,7 +892,7 @@ static bool find(const struct expr* expr,
|
|||
state->flags &= ~SUCCESS;
|
||||
goto next;
|
||||
}
|
||||
if ( !(state->flags & PRUNED) )
|
||||
if ( !(state->flags & PRUNED) && !(xdev && is_mount_point) )
|
||||
{
|
||||
state->num_entries =
|
||||
list_directory(state->dir, &state->entries);
|
||||
|
@ -980,6 +984,7 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
bool depth = false;
|
||||
bool ere = false;
|
||||
bool mount = false;
|
||||
enum symderef symderef = SYMDEREF_NONE;
|
||||
bool xdev = false;
|
||||
size_t mindepth = 0;
|
||||
|
@ -1280,13 +1285,20 @@ int main(int argc, char* argv[])
|
|||
subexpr->kind = EXPR_TRUE;
|
||||
mindepth = (size_t) value;
|
||||
}
|
||||
else if ( !strcmp(arg, "-name") )
|
||||
else if ( !strcmp(arg, "-mount") )
|
||||
{
|
||||
mount = true;
|
||||
subexpr->kind = EXPR_TRUE;
|
||||
}
|
||||
else if ( !strcmp(arg, "-name") || !strcmp(arg, "-iname") )
|
||||
{
|
||||
if ( i + 1 == argc )
|
||||
errx(1, "missing parameter to %s", arg);
|
||||
const char* param = argv[++i];
|
||||
subexpr->kind = EXPR_NAME;
|
||||
subexpr->expr_name.pattern = param;
|
||||
subexpr->expr_name.flags =
|
||||
!strcmp(arg, "-iname") ? FNM_CASEFOLD : 0;
|
||||
}
|
||||
else if ( !strcmp(arg, "-nogroup") )
|
||||
subexpr->kind = EXPR_NOGROUP;
|
||||
|
@ -1496,7 +1508,8 @@ int main(int argc, char* argv[])
|
|||
state.relpath = ".";
|
||||
state.path = ".";
|
||||
state.type = DT_UNKNOWN;
|
||||
result = find(root, &state, depth, symderef, xdev, mindepth, maxdepth);
|
||||
result = find(root, &state, depth, symderef, xdev, mount, mindepth,
|
||||
maxdepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1512,7 +1525,7 @@ int main(int argc, char* argv[])
|
|||
state.relpath = arg;
|
||||
state.path = arg;
|
||||
state.type = DT_UNKNOWN;
|
||||
if ( !find(root, &state, depth, symderef, xdev, mindepth,
|
||||
if ( !find(root, &state, depth, symderef, xdev, mount, mindepth,
|
||||
maxdepth) )
|
||||
result = false;
|
||||
free(argdup);
|
||||
|
|
Loading…
Reference in a new issue