| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 2 | /* | 
 | 3 |  * Mini find implementation for busybox | 
 | 4 |  * | 
| Eric Andersen | c499601 | 1999-10-20 22:08:37 +0000 | [diff] [blame] | 5 |  * | 
| Eric Andersen | 8ec10a9 | 2001-01-27 09:33:39 +0000 | [diff] [blame] | 6 |  * Copyright (C) 1999,2000,2001 by Lineo, inc. | 
| Eric Andersen | c499601 | 1999-10-20 22:08:37 +0000 | [diff] [blame] | 7 |  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 8 |  * Reworked by David Douthitt <n9ubh@callsign.net> and | 
 | 9 |  *  Matt Kraai <kraai@alumni.carnegiemellon.edu>. | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 10 |  * | 
 | 11 |  * This program is free software; you can redistribute it and/or modify | 
 | 12 |  * it under the terms of the GNU General Public License as published by | 
 | 13 |  * the Free Software Foundation; either version 2 of the License, or | 
 | 14 |  * (at your option) any later version. | 
 | 15 |  * | 
 | 16 |  * This program is distributed in the hope that it will be useful, | 
 | 17 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 18 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 
 | 19 |  * General Public License for more details. | 
 | 20 |  * | 
 | 21 |  * You should have received a copy of the GNU General Public License | 
 | 22 |  * along with this program; if not, write to the Free Software | 
 | 23 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 
 | 24 |  * | 
 | 25 |  */ | 
 | 26 |  | 
 | 27 | #include <stdio.h> | 
 | 28 | #include <unistd.h> | 
 | 29 | #include <dirent.h> | 
| Eric Andersen | ed3ef50 | 2001-01-27 08:24:39 +0000 | [diff] [blame] | 30 | #include <string.h> | 
 | 31 | #include <stdlib.h> | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 32 | #include <fnmatch.h> | 
 | 33 | #include <time.h> | 
 | 34 | #include <ctype.h> | 
| Eric Andersen | cbe31da | 2001-02-20 06:14:08 +0000 | [diff] [blame] | 35 | #include "busybox.h" | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 36 |  | 
 | 37 |  | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 38 | static char *pattern; | 
 | 39 |  | 
 | 40 | #ifdef BB_FEATURE_FIND_TYPE | 
 | 41 | static int type_mask = 0; | 
 | 42 | #endif | 
 | 43 |  | 
 | 44 | #ifdef BB_FEATURE_FIND_PERM | 
 | 45 | static char perm_char = 0; | 
 | 46 | static int perm_mask = 0; | 
 | 47 | #endif | 
 | 48 |  | 
 | 49 | #ifdef BB_FEATURE_FIND_MTIME | 
 | 50 | static char mtime_char; | 
 | 51 | static int mtime_days; | 
 | 52 | #endif | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 53 |  | 
| Erik Andersen | 3364d78 | 2000-03-28 00:58:14 +0000 | [diff] [blame] | 54 | static int fileAction(const char *fileName, struct stat *statbuf, void* junk) | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 55 | { | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 56 | 	if (pattern != NULL) { | 
 | 57 | 		const char *tmp = strrchr(fileName, '/'); | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 58 |  | 
 | 59 | 		if (tmp == NULL) | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 60 | 			tmp = fileName; | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 61 | 		else | 
 | 62 | 			tmp++; | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 63 | 		if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0)) | 
 | 64 | 			goto no_match; | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 65 | 	} | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 66 | #ifdef BB_FEATURE_FIND_TYPE | 
 | 67 | 	if (type_mask != 0) { | 
 | 68 | 		if (!((statbuf->st_mode & S_IFMT) == type_mask)) | 
 | 69 | 			goto no_match; | 
 | 70 | 	} | 
 | 71 | #endif | 
 | 72 | #ifdef BB_FEATURE_FIND_PERM | 
 | 73 | 	if (perm_mask != 0) { | 
 | 74 | 		if (!((isdigit(perm_char) && (statbuf->st_mode & 07777) == perm_mask) || | 
 | 75 | 			 (perm_char == '-' && (statbuf->st_mode & perm_mask) == perm_mask) || | 
 | 76 | 			 (perm_char == '+' && (statbuf->st_mode & perm_mask) != 0))) | 
 | 77 | 			goto no_match; | 
 | 78 | 	} | 
 | 79 | #endif | 
 | 80 | #ifdef BB_FEATURE_FIND_MTIME | 
 | 81 | 	if (mtime_days != 0) { | 
 | 82 | 		time_t file_age = time(NULL) - statbuf->st_mtime; | 
 | 83 | 		time_t mtime_secs = mtime_days * 24 * 60 * 60; | 
 | 84 | 		if (!((isdigit(mtime_char) && mtime_secs >= file_age && | 
 | 85 | 						mtime_secs < file_age + 24 * 60 * 60) || | 
 | 86 | 				(mtime_char == '+' && mtime_secs >= file_age) ||  | 
 | 87 | 				(mtime_char == '-' && mtime_secs < file_age))) | 
 | 88 | 			goto no_match; | 
 | 89 | 	} | 
 | 90 | #endif | 
 | 91 | 	puts(fileName); | 
 | 92 | no_match: | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 93 | 	return (TRUE); | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 94 | } | 
 | 95 |  | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 96 | #ifdef BB_FEATURE_FIND_TYPE | 
 | 97 | static int find_type(char *type) | 
 | 98 | { | 
 | 99 | 	int mask = 0; | 
 | 100 |  | 
 | 101 | 	switch (type[0]) { | 
 | 102 | 		case 'b': | 
 | 103 | 			mask = S_IFBLK; | 
 | 104 | 			break; | 
 | 105 | 		case 'c': | 
 | 106 | 			mask = S_IFCHR; | 
 | 107 | 			break; | 
 | 108 | 		case 'd': | 
 | 109 | 			mask = S_IFDIR; | 
 | 110 | 			break; | 
 | 111 | 		case 'p': | 
 | 112 | 			mask = S_IFIFO; | 
 | 113 | 			break; | 
 | 114 | 		case 'f': | 
 | 115 | 			mask = S_IFREG; | 
 | 116 | 			break; | 
 | 117 | 		case 'l': | 
 | 118 | 			mask = S_IFLNK; | 
 | 119 | 			break; | 
 | 120 | 		case 's': | 
 | 121 | 			mask = S_IFSOCK; | 
 | 122 | 			break; | 
 | 123 | 	} | 
 | 124 |  | 
 | 125 | 	if (mask == 0 || type[1] != '\0') | 
 | 126 | 		error_msg_and_die("invalid argument `%s' to `-type'", type); | 
 | 127 |  | 
 | 128 | 	return mask; | 
 | 129 | } | 
 | 130 | #endif | 
 | 131 |  | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 132 | int find_main(int argc, char **argv) | 
 | 133 | { | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 134 | 	int dereference = FALSE; | 
 | 135 | 	int i, firstopt, status = EXIT_SUCCESS; | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 136 |  | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 137 | 	for (firstopt = 1; firstopt < argc; firstopt++) { | 
 | 138 | 		if (argv[firstopt][0] == '-') | 
 | 139 | 			break; | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 140 | 	} | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 141 |  | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 142 | 	/* Parse any options */ | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 143 | 	for (i = firstopt; i < argc; i++) { | 
 | 144 | 		if (strcmp(argv[i], "-follow") == 0) | 
 | 145 | 			dereference = TRUE; | 
| Mark Whitley | e0a7f91 | 2001-03-28 22:04:42 +0000 | [diff] [blame] | 146 | 		else if (strcmp(argv[i], "-print") == 0) { | 
 | 147 | 			; | 
 | 148 | 			} | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 149 | 		else if (strcmp(argv[i], "-name") == 0) { | 
 | 150 | 			if (++i == argc) | 
 | 151 | 				error_msg_and_die("option `-name' requires an argument"); | 
 | 152 | 			pattern = argv[i]; | 
 | 153 | #ifdef BB_FEATURE_FIND_TYPE | 
 | 154 | 		} else if (strcmp(argv[i], "-type") == 0) { | 
 | 155 | 			if (++i == argc) | 
 | 156 | 				error_msg_and_die("option `-type' requires an argument"); | 
 | 157 | 			type_mask = find_type(argv[i]); | 
 | 158 | #endif | 
 | 159 | #ifdef BB_FEATURE_FIND_PERM | 
 | 160 | 		} else if (strcmp(argv[i], "-perm") == 0) { | 
 | 161 | 			char *end; | 
 | 162 | 			if (++i == argc) | 
 | 163 | 				error_msg_and_die("option `-perm' requires an argument"); | 
 | 164 | 			perm_mask = strtol(argv[i], &end, 8); | 
 | 165 | 			if (end[0] != '\0') | 
 | 166 | 				error_msg_and_die("invalid argument `%s' to `-perm'", argv[i]); | 
 | 167 | 			if (perm_mask > 07777) | 
 | 168 | 				error_msg_and_die("invalid argument `%s' to `-perm'", argv[i]); | 
 | 169 | 			if ((perm_char = argv[i][0]) == '-') | 
 | 170 | 				perm_mask = -perm_mask; | 
 | 171 | #endif | 
 | 172 | #ifdef BB_FEATURE_FIND_MTIME | 
 | 173 | 		} else if (strcmp(argv[i], "-mtime") == 0) { | 
 | 174 | 			char *end; | 
 | 175 | 			if (++i == argc) | 
 | 176 | 				error_msg_and_die("option `-mtime' requires an argument"); | 
 | 177 | 			mtime_days = strtol(argv[i], &end, 10); | 
 | 178 | 			if (end[0] != '\0') | 
 | 179 | 				error_msg_and_die("invalid argument `%s' to `-mtime'", argv[i]); | 
 | 180 | 			if ((mtime_char = argv[i][0]) == '-') | 
 | 181 | 				mtime_days = -mtime_days; | 
 | 182 | #endif | 
 | 183 | 		} else | 
| Eric Andersen | 67991cf | 2001-02-14 21:23:06 +0000 | [diff] [blame] | 184 | 			show_usage(); | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 185 | 	} | 
 | 186 |  | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 187 | 	if (firstopt == 1) { | 
 | 188 | 		if (recursive_action(".", TRUE, dereference, FALSE, fileAction, | 
 | 189 | 					fileAction, NULL) == FALSE) | 
 | 190 | 			status = EXIT_FAILURE; | 
 | 191 | 	} else { | 
 | 192 | 		for (i = 1; i < firstopt; i++) { | 
 | 193 | 			if (recursive_action(argv[i], TRUE, dereference, FALSE, fileAction, | 
 | 194 | 						fileAction, NULL) == FALSE) | 
 | 195 | 				status = EXIT_FAILURE; | 
 | 196 | 		} | 
| Erik Andersen | e49d5ec | 2000-02-08 19:58:47 +0000 | [diff] [blame] | 197 | 	} | 
 | 198 |  | 
| Matt Kraai | 096370d | 2001-02-07 03:52:38 +0000 | [diff] [blame] | 199 | 	return status; | 
| Eric Andersen | 17d49ef | 1999-10-06 20:25:32 +0000 | [diff] [blame] | 200 | } |