find: make -size match GNU find
No binary (build failed)
—
(log yok)
| @@ -30,7 +30,7 @@ config FEATURE_FIND_MTIME | |
| files, in days. | |
| config FEATURE_FIND_MMIN | |
| - | bool "Enable modified time matching (-min) option" |
| + | bool "Enable modified time matching (-mmin) option" |
| default y | |
| depends on FIND | |
| help | |
| @@ -45,6 +45,14 @@ | |
| * (no output) | |
| */ | |
| + | /* Testing script |
| + | * ./busybox find "$@" | tee /tmp/bb_find |
| + | * echo ================== |
| + | * /path/to/gnu/find "$@" | tee /tmp/std_find |
| + | * echo ================== |
| + | * diff -u /tmp/std_find /tmp/bb_find && echo Identical |
| + | */ |
| + | |
| #include <fnmatch.h> | |
| #include "libbb.h" | |
| #if ENABLE_FEATURE_FIND_REGEX | |
| @@ -82,7 +90,7 @@ USE_FEATURE_FIND_EXEC( ACTS(exec, char **exec_argv; unsigned *subst_count; int | |
| USE_FEATURE_FIND_USER( ACTS(user, uid_t uid;)) | |
| USE_FEATURE_FIND_GROUP( ACTS(group, gid_t gid;)) | |
| USE_FEATURE_FIND_PAREN( ACTS(paren, action ***subexpr;)) | |
| - | USE_FEATURE_FIND_SIZE( ACTS(size, off_t size;)) |
| + | USE_FEATURE_FIND_SIZE( ACTS(size, char size_char; off_t size;)) |
| USE_FEATURE_FIND_PRUNE( ACTS(prune)) | |
| USE_FEATURE_FIND_DELETE(ACTS(delete)) | |
| @@ -314,6 +322,10 @@ ACTF(paren) | |
| #if ENABLE_FEATURE_FIND_SIZE | |
| ACTF(size) | |
| { | |
| + | if (ap->size_char == '+') |
| + | return statbuf->st_size > ap->size; |
| + | if (ap->size_char == '-') |
| + | return statbuf->st_size < ap->size; |
| return statbuf->st_size == ap->size; | |
| } | |
| #endif | |
| @@ -714,11 +726,31 @@ static action*** parse_params(char **argv) | |
| #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 }, |
| + | { "b"+1, 512 }, |
| + | { "b", 512 }, |
| + | { "k", 1024 }, |
| + | { NULL, 0 } |
| + | }; |
| action_size *ap; | |
| if (!*++argv) | |
| bb_error_msg_and_die(bb_msg_requires_arg, arg); | |
| ap = ALLOC_ACTION(size); | |
| - | ap->size = XATOOFF(arg1); |
| + | ap->size_char = arg1[0]; |
| + | ap->size = XATOU_SFX(plus_minus_num(arg1), find_suffixes); |
| } | |
| #endif | |
| #if ENABLE_FEATURE_FIND_PRUNE | |
| @@ -948,15 +948,15 @@ | |
| USE_FEATURE_FIND_MAXDEPTH( \ | |
| "\n -maxdepth N Descend at most N levels. -maxdepth 0 applies" \ | |
| "\n tests/actions to command line arguments only") \ | |
| - | "\n -name PATTERN File name (leading directories removed) matches PATTERN" \ |
| - | "\n -print Print (default and assumed)" \ |
| - | USE_FEATURE_FIND_PRINT0( \ |
| - | "\n -print0 Delimit output with null characters rather than" \ |
| - | "\n newlines") \ |
| + | "\n -name PATTERN File name (w/o directory name) matches PATTERN" \ |
| + | USE_FEATURE_FIND_PATH( \ |
| + | "\n -path PATTERN Path matches PATTERN") \ |
| + | USE_FEATURE_FIND_REGEX( \ |
| + | "\n -regex PATTERN Path matches regex PATTERN") \ |
| USE_FEATURE_FIND_TYPE( \ | |
| - | "\n -type X Filetype matches X (where X is one of: f,d,l,b,c,...)") \ |
| + | "\n -type X File type is X (X is one of: f,d,l,b,c,...)") \ |
| USE_FEATURE_FIND_PERM( \ | |
| - | "\n -perm PERMS Permissions match any of (+NNN), all of (-NNN)," \ |
| + | "\n -perm NNN Permissions match any of (+NNN), all of (-NNN)," \ |
| "\n or exactly (NNN)") \ | |
| USE_FEATURE_FIND_MTIME( \ | |
| "\n -mtime DAYS Modified time is greater than (+N), less than (-N)," \ | |
| @@ -968,23 +968,26 @@ | |
| "\n -newer FILE Modified time is more recent than FILE's") \ | |
| USE_FEATURE_FIND_INUM( \ | |
| "\n -inum N File has inode number N") \ | |
| - | USE_FEATURE_FIND_EXEC( \ |
| - | "\n -exec CMD Execute CMD with all instances of {} replaced by the" \ |
| - | "\n files matching EXPRESSION") \ |
| USE_FEATURE_FIND_USER( \ | |
| "\n -user NAME File is owned by user NAME (numeric user ID allowed)") \ | |
| USE_FEATURE_FIND_GROUP( \ | |
| "\n -group NAME File belongs to group NAME (numeric group ID allowed)") \ | |
| USE_FEATURE_FIND_DEPTH( \ | |
| - | "\n -depth Process directory after traversing it") \ |
| + | "\n -depth Process directory name after traversing it") \ |
| USE_FEATURE_FIND_SIZE( \ | |
| - | "\n -size N File size is N") \ |
| + | "\n -size N[bck] File size is N (c:bytes,k:kbytes,b:512 bytes(def.))." \ |
| + | "\n +/-N: file size is bigger/smaller than N") \ |
| + | "\n -print Print (default and assumed)" \ |
| + | USE_FEATURE_FIND_PRINT0( \ |
| + | "\n -print0 Delimit output with null characters rather than" \ |
| + | "\n newlines") \ |
| + | USE_FEATURE_FIND_EXEC( \ |
| + | "\n -exec CMD ARG ; Execute CMD with all instances of {} replaced by the" \ |
| + | "\n matching files") \ |
| USE_FEATURE_FIND_PRUNE( \ | |
| "\n -prune Stop traversing current subtree") \ | |
| USE_FEATURE_FIND_DELETE( \ | |
| "\n -delete Delete files, turns on -depth option") \ | |
| - | USE_FEATURE_FIND_PATH( \ |
| - | "\n -path Path matches PATTERN") \ |
| USE_FEATURE_FIND_PAREN( \ | |
| "\n (EXPR) Group an expression") \ | |
| @@ -49,9 +49,8 @@ unsigned type xstrtou(_range_sfx)(const char *numstr, int base, | |
| if (strcmp(suffixes->suffix, e) == 0) { | |
| if (XSTR_UTYPE_MAX / suffixes->mult < r) | |
| goto range; /* overflow! */ | |
| - | ++e; |
| r *= suffixes->mult; | |
| - | break; |
| + | goto chk_range; |
| } | |
| ++suffixes; | |
| } | |
| @@ -61,6 +60,7 @@ unsigned type xstrtou(_range_sfx)(const char *numstr, int base, | |
| It would be easy enough to allow though if desired. */ | |
| if (*e) | |
| goto inval; | |
| + | chk_range: |
| /* Finally, check for range limits. */ | |
| if (r >= lower && r <= upper) | |
| return r; | |