diff options
| author | Connor Lane Smith <cls@lubutu.com> | 2011-11-27 23:35:09 +0100 | 
|---|---|---|
| committer | Connor Lane Smith <cls@lubutu.com> | 2011-11-27 23:35:09 +0100 | 
| commit | 8cc28cb4265b0c088ea909e58f42342b2214722e (patch) | |
| tree | f456155017ed610333dcabd036702f0a363843bb | |
| parent | bb4424df072332243890714b055e978a5c70adf3 (diff) | |
simplify stest
| -rwxr-xr-x | dmenu_run | 6 | ||||
| -rw-r--r-- | stest.1 | 15 | ||||
| -rw-r--r-- | stest.c | 94 | 
3 files changed, 53 insertions, 62 deletions
@@ -5,10 +5,8 @@ if [ ! -d "`dirname "$CACHE"`" ]; then  fi  (  	IFS=: -	if ls -d $PATH | stest -q -n "$CACHE"; then -		for dir in $PATH; do -			ls $dir | stest -C $dir -fx -		done | sort -u > "$CACHE" +	if stest -dqr -n "$CACHE" $PATH; then +		stest -flx $PATH | sort -u > "$CACHE"  	fi  )  cmd=`dmenu "$@" < "$CACHE"` && exec sh -c "$cmd" @@ -3,9 +3,7 @@  stest \- filter a list of files by properties  .SH SYNOPSIS  .B stest -.RB [ -bcdefghpqrsuwx ] -.RB [ -C -.IR dir ] +.RB [ -abcdefghlpqrsuwx ]  .RB [ -n  .IR file ]  .RB [ -o @@ -15,13 +13,11 @@ stest \- filter a list of files by properties  .B stest  takes a list of files and filters by the files' properties, analogous to  .IR test (1). -Files which pass all tests are printed to stdout. If no files are given as -arguments, stest will read a list of files from stdin, one path per line. +Files which pass all tests are printed to stdout.  .SH OPTIONS  .TP -.BI \-C " dir" -Tests files relative to directory -.IR dir . +.B \-a +Test hidden files.  .TP  .B \-b  Test that files are block specials. @@ -44,6 +40,9 @@ Test that files have their set-group-ID flag set.  .B \-h  Test that files are symbolic links.  .TP +.B \-l +Test the contents of a directory given as an argument. +.TP  .BI \-n " file"  Test that files are newer than  .IR file . @@ -1,4 +1,5 @@  /* See LICENSE file for copyright and license details. */ +#include <dirent.h>  #include <stdbool.h>  #include <stdio.h>  #include <stdlib.h> @@ -6,80 +7,73 @@  #include <unistd.h>  #include <sys/stat.h> -#define OPER(x)  (oper[(x)-'a']) +#define FLAG(x)  (flag[(x)-'a']) -static bool test(const char *); +static void test(const char *, const char *); -static bool quiet = false; -static bool oper[26]; +static bool match = false; +static bool flag[26];  static struct stat old, new;  int  main(int argc, char *argv[]) { -	char buf[BUFSIZ], *p; -	bool match = false; +	struct dirent *d; +	char buf[BUFSIZ]; +	DIR *dir;  	int opt; -	while((opt = getopt(argc, argv, "C:bcdefghn:o:pqrsuwx")) != -1) +	while((opt = getopt(argc, argv, "abcdefghln:o:pqrsuwx")) != -1)  		switch(opt) { -		case 'C': /* tests relative to directory */ -			if(chdir(optarg) == -1) { -				perror(optarg); -				exit(2); -			} -			break;  		case 'n': /* newer than file */  		case 'o': /* older than file */ -			if(!(OPER(opt) = stat(optarg, (opt == 'n' ? &new : &old)) == 0)) +			if(!(FLAG(opt) = !stat(optarg, (opt == 'n' ? &new : &old))))  				perror(optarg);  			break; -		case 'q': /* quiet (no output, just status) */ -			quiet = true; -			break;  		default:  /* miscellaneous operators */ -			OPER(opt) = true; +			FLAG(opt) = true;  			break;  		case '?': /* error: unknown flag */ -			fprintf(stderr, "usage: %s [-bcdefghpqrsuwx] [-C dir] [-n file] [-o file] [file...]\n", argv[0]); +			fprintf(stderr, "usage: %s [-abcdefghlpqrsuwx] [-n file] [-o file] [file...]\n", argv[0]);  			exit(2);  		} -	if(optind == argc) -		while(fgets(buf, sizeof buf, stdin)) { -			if(*(p = &buf[strlen(buf)-1]) == '\n') -				*p = '\0'; -			match |= test(buf); +	for(; optind < argc; optind++) +		if(FLAG('l') && (dir = opendir(argv[optind]))) { +			/* test directory contents */ +			while((d = readdir(dir))) +				if(snprintf(buf, sizeof buf, "%s/%s", argv[optind], d->d_name) < sizeof buf) +					test(buf, d->d_name); +			closedir(dir);  		} -	else -		while(optind < argc) -			match |= test(argv[optind++]); +		else +			test(argv[optind], argv[optind]);  	return match ? 0 : 1;  } -bool -test(const char *path) { -	struct stat st; +void +test(const char *path, const char *name) { +	struct stat st, ln; -	if((!OPER('b') || (stat(path, &st) == 0 && S_ISBLK(st.st_mode)))        /* block special     */ -	&& (!OPER('c') || (stat(path, &st) == 0 && S_ISCHR(st.st_mode)))        /* character special */ -	&& (!OPER('d') || (stat(path, &st) == 0 && S_ISDIR(st.st_mode)))        /* directory         */ -	&& (!OPER('e') || (access(path, F_OK) == 0))                            /* exists            */ -	&& (!OPER('f') || (stat(path, &st) == 0 && S_ISREG(st.st_mode)))        /* regular file      */ -	&& (!OPER('g') || (stat(path, &st) == 0 && (st.st_mode & S_ISGID)))     /* set-group-id flag */ -	&& (!OPER('h') || (lstat(path, &st) == 0 && S_ISLNK(st.st_mode)))       /* symbolic link     */ -	&& (!OPER('n') || (stat(path, &st) == 0 && st.st_mtime > new.st_mtime)) /* newer than file   */ -	&& (!OPER('o') || (stat(path, &st) == 0 && st.st_mtime < old.st_mtime)) /* older than file   */ -	&& (!OPER('p') || (stat(path, &st) == 0 && S_ISFIFO(st.st_mode)))       /* named pipe        */ -	&& (!OPER('r') || (access(path, R_OK) == 0))                            /* readable          */ -	&& (!OPER('s') || (stat(path, &st) == 0 && st.st_size > 0))             /* not empty         */ -	&& (!OPER('u') || (stat(path, &st) == 0 && (st.st_mode & S_ISUID)))     /* set-user-id flag  */ -	&& (!OPER('w') || (access(path, W_OK) == 0))                            /* writable          */ -	&& (!OPER('x') || (access(path, X_OK) == 0))) {                         /* executable        */ -		if(quiet) +	if(!stat(path, &st) && !lstat(path, &ln) +	&& ( FLAG('a') || name[0] != '.')                             /* hidden            */ +	&& (!FLAG('b') || S_ISBLK(st.st_mode))                        /* block special     */ +	&& (!FLAG('c') || S_ISCHR(st.st_mode))                        /* character special */ +	&& (!FLAG('d') || S_ISDIR(st.st_mode))                        /* directory         */ +	&& (!FLAG('e') || access(path, F_OK) == 0)                    /* exists            */ +	&& (!FLAG('f') || S_ISREG(st.st_mode))                        /* regular file      */ +	&& (!FLAG('g') || st.st_mode & S_ISGID)                       /* set-group-id flag */ +	&& (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link     */ +	&& (!FLAG('n') || st.st_mtime > new.st_mtime)                 /* newer than file   */ +	&& (!FLAG('o') || st.st_mtime < old.st_mtime)                 /* older than file   */ +	&& (!FLAG('p') || S_ISFIFO(st.st_mode))                       /* named pipe        */ +	&& (!FLAG('r') || access(path, R_OK) == 0)                    /* readable          */ +	&& (!FLAG('s') || st.st_size > 0)                             /* not empty         */ +	&& (!FLAG('u') || st.st_mode & S_ISUID)                       /* set-user-id flag  */ +	&& (!FLAG('w') || access(path, W_OK) == 0)                    /* writable          */ +	&& (!FLAG('x') || access(path, X_OK) == 0)) {                 /* executable        */ +		if(FLAG('q'))  			exit(0); -		puts(path); -		return true; +		match = true; +		puts(name);  	} -	else -		return false;  }  |