Several cleanups from Manuel Novoa III.
get_kernel_revision --  size reduction
        NOTE: may want to combine with get_kernel_version in insmod???
parse_mode -- size reduction, multiple settings with "," now work correctly,
        sticky-bit setting now implemented
process_escape_sequence -- size reduction, octal code to big for char bug fixed
format -- size reduction, val > LONG_MAX and hr = 1 printing bug fixed (was %ld),
			
			
This commit is contained in:
		| @@ -232,7 +232,7 @@ extern int sysinfo (struct sysinfo* info); | ||||
| #endif | ||||
|  | ||||
| #ifdef BB_FEATURE_HUMAN_READABLE | ||||
| char *format(unsigned long val, unsigned long hr); | ||||
| const char *format(unsigned long val, unsigned long hr); | ||||
| #define KILOBYTE 1024 | ||||
| #define MEGABYTE (KILOBYTE*1024) | ||||
| #define GIGABYTE (MEGABYTE*1024) | ||||
|   | ||||
| @@ -232,7 +232,7 @@ extern int sysinfo (struct sysinfo* info); | ||||
| #endif | ||||
|  | ||||
| #ifdef BB_FEATURE_HUMAN_READABLE | ||||
| char *format(unsigned long val, unsigned long hr); | ||||
| const char *format(unsigned long val, unsigned long hr); | ||||
| #define KILOBYTE 1024 | ||||
| #define MEGABYTE (KILOBYTE*1024) | ||||
| #define GIGABYTE (MEGABYTE*1024) | ||||
|   | ||||
							
								
								
									
										281
									
								
								utility.c
									
									
									
									
									
								
							
							
						
						
									
										281
									
								
								utility.c
									
									
									
									
									
								
							| @@ -51,6 +51,7 @@ | ||||
| #include <unistd.h> | ||||
| #include <ctype.h> | ||||
| #include <stdlib.h> | ||||
| #include <limits.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/utsname.h>		/* for uname(2) */ | ||||
|  | ||||
| @@ -77,7 +78,7 @@ const char mtab_file[] = "/proc/mounts"; | ||||
|  | ||||
| extern void usage(const char *usage) | ||||
| { | ||||
| 	fprintf(stderr, "%s\n\nUsage: %s\n", full_version, usage); | ||||
| 	fprintf(stderr, "%s\n\nUsage: %s\n\n", full_version, usage); | ||||
| 	exit(EXIT_FAILURE); | ||||
| } | ||||
|  | ||||
| @@ -145,16 +146,21 @@ extern void perror_msg_and_die(const char *s, ...) | ||||
| extern int get_kernel_revision(void) | ||||
| { | ||||
| 	struct utsname name; | ||||
| 	int major = 0, minor = 0, patch = 0; | ||||
| 	char *s; | ||||
| 	int i, r; | ||||
|  | ||||
| 	if (uname(&name) == -1) { | ||||
| 		perror_msg("cannot get system information"); | ||||
| 		return (0); | ||||
| 	} | ||||
| 	major = atoi(strtok(name.release, ".")); | ||||
| 	minor = atoi(strtok(NULL, ".")); | ||||
| 	patch = atoi(strtok(NULL, ".")); | ||||
| 	return major * 65536 + minor * 256 + patch; | ||||
|  | ||||
| 	s = name.release; | ||||
| 	r = 0; | ||||
| 	for (i=0 ; i<3 ; i++) { | ||||
| 		r = r * 256 + atoi(strtok(s, ".")); | ||||
| 		s = NULL; | ||||
| 	} | ||||
| 	return r; | ||||
| } | ||||
| #endif                                                 /* BB_INIT */ | ||||
|  | ||||
| @@ -749,102 +755,100 @@ extern int create_path(const char *name, int mode) | ||||
|  || defined (BB_MKFIFO) || defined (BB_MKNOD) || defined (BB_AR) | ||||
| /* [ugoa]{+|-|=}[rwxst] */ | ||||
|  | ||||
|  | ||||
|  | ||||
| extern int parse_mode(const char *s, mode_t * theMode) | ||||
| { | ||||
| 	mode_t andMode = | ||||
| 	static const mode_t group_set[] = {  | ||||
| 		S_ISUID | S_IRWXU,		/* u */ | ||||
| 		S_ISGID | S_IRWXG,		/* g */ | ||||
| 		S_IRWXO,				/* o */ | ||||
| 		S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO /* a */ | ||||
| 	}; | ||||
|  | ||||
| 	static const mode_t mode_set[] = { | ||||
| 		S_IRUSR | S_IRGRP | S_IROTH, /* r */ | ||||
| 		S_IWUSR | S_IWGRP | S_IWOTH, /* w */ | ||||
| 		S_IXUSR | S_IXGRP | S_IXOTH, /* x */ | ||||
| 		S_ISUID | S_ISGID,		/* s */ | ||||
| 		S_ISVTX					/* t */ | ||||
| 	}; | ||||
|  | ||||
| 	static const char group_string[] = "ugoa"; | ||||
| 	static const char mode_string[] = "rwxst"; | ||||
|  | ||||
| 	const char *p; | ||||
|  | ||||
| 	mode_t andMode = | ||||
| 		S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | ||||
| 	mode_t orMode = 0; | ||||
| 	mode_t mode = 0; | ||||
| 	mode_t groups = 0; | ||||
| 	mode_t mode; | ||||
| 	mode_t groups; | ||||
| 	char type; | ||||
| 	char c; | ||||
|  | ||||
| 	if (s==NULL) | ||||
| 	if (s==NULL) { | ||||
| 		return (FALSE); | ||||
| 	} | ||||
|  | ||||
| 	do { | ||||
| 		for (;;) { | ||||
| 			switch (c = *s++) { | ||||
| 			case '\0': | ||||
| 				return -1; | ||||
| 			case 'u': | ||||
| 				groups |= S_ISUID | S_IRWXU; | ||||
| 				continue; | ||||
| 			case 'g': | ||||
| 				groups |= S_ISGID | S_IRWXG; | ||||
| 				continue; | ||||
| 			case 'o': | ||||
| 				groups |= S_IRWXO; | ||||
| 				continue; | ||||
| 			case 'a': | ||||
| 				groups |= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | ||||
| 				continue; | ||||
| 			case '+': | ||||
| 		mode = 0; | ||||
| 		groups = 0; | ||||
| 	NEXT_GROUP: | ||||
| 		if ((c = *s++) == '\0') { | ||||
| 			return -1; | ||||
| 		} | ||||
| 		for (p=group_string ; *p ; p++) { | ||||
| 			if (*p == c) { | ||||
| 				groups |= group_set[(int)(p-group_string)]; | ||||
| 				goto NEXT_GROUP; | ||||
| 			} | ||||
| 		} | ||||
| 		switch (c) { | ||||
| 			case '=': | ||||
| 			case '+': | ||||
| 			case '-': | ||||
| 				type = c; | ||||
| 				if (groups == 0)	/* The default is "all" */ | ||||
| 					groups |= | ||||
| 						S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | ||||
| 				if (groups == 0) { /* The default is "all" */ | ||||
| 					groups |= S_ISUID | S_ISGID | S_ISVTX | ||||
| 							| S_IRWXU | S_IRWXG | S_IRWXO; | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				if (isdigit(c) && c >= '0' && c <= '7' && | ||||
| 					mode == 0 && groups == 0) { | ||||
| 				if ((c < '0') || (c > '7') || (mode | groups)) { | ||||
| 					return (FALSE); | ||||
| 				} else { | ||||
| 					*theMode = strtol(--s, NULL, 8); | ||||
| 					return (TRUE); | ||||
| 				} else | ||||
| 					return (FALSE); | ||||
| 			} | ||||
| 			break; | ||||
| 				} | ||||
| 		} | ||||
|  | ||||
| 		while ((c = *s++) != '\0') { | ||||
| 			switch (c) { | ||||
| 			case ',': | ||||
| 				break; | ||||
| 			case 'r': | ||||
| 				mode |= S_IRUSR | S_IRGRP | S_IROTH; | ||||
| 				continue; | ||||
| 			case 'w': | ||||
| 				mode |= S_IWUSR | S_IWGRP | S_IWOTH; | ||||
| 				continue; | ||||
| 			case 'x': | ||||
| 				mode |= S_IXUSR | S_IXGRP | S_IXOTH; | ||||
| 				continue; | ||||
| 			case 's': | ||||
| 				mode |= S_IXGRP | S_ISUID | S_ISGID; | ||||
| 				continue; | ||||
| 			case 't': | ||||
| 				mode |= 0; | ||||
| 				continue; | ||||
| 			default: | ||||
| 				*theMode &= andMode; | ||||
| 				*theMode |= orMode; | ||||
| 				return (TRUE); | ||||
| 	NEXT_MODE: | ||||
| 		if (((c = *s++) != '\0') && (c != ',')) { | ||||
| 			for (p=mode_string ; *p ; p++) { | ||||
| 				if (*p == c) { | ||||
| 					mode |= mode_set[(int)(p-mode_string)]; | ||||
| 					goto NEXT_MODE; | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
| 			break;				/* We're done so break out of loop.*/ | ||||
| 		} | ||||
| 		switch (type) { | ||||
| 		case '=': | ||||
| 			andMode &= ~(groups); | ||||
| 			/* fall through */ | ||||
| 		case '+': | ||||
| 			orMode |= mode & groups; | ||||
| 			break; | ||||
| 		case '-': | ||||
| 			andMode &= ~(mode & groups); | ||||
| 			orMode &= andMode; | ||||
| 			break; | ||||
| 			case '=': | ||||
| 				andMode &= ~(groups); /* Now fall through. */ | ||||
| 			case '+': | ||||
| 				orMode |= mode & groups; | ||||
| 				break; | ||||
| 			case '-': | ||||
| 				andMode &= ~(mode & groups); | ||||
| 				orMode &= ~(mode & groups); | ||||
| 				break; | ||||
| 		} | ||||
| 	} while (c == ','); | ||||
|  | ||||
| 	*theMode &= andMode; | ||||
| 	*theMode |= orMode; | ||||
| 	return (TRUE); | ||||
| } | ||||
|  | ||||
| 	return TRUE; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| /* BB_CHMOD_CHOWN_CHGRP || BB_MKDIR || BB_MKFIFO || BB_MKNOD */ | ||||
| @@ -1575,48 +1579,43 @@ extern int print_file_by_name(char *filename) | ||||
| #if defined BB_ECHO || defined BB_SH || defined BB_TR | ||||
| char process_escape_sequence(char **ptr) | ||||
| { | ||||
| 	char c; | ||||
|        static const char charmap[] = { | ||||
| 		   'a',  'b',  'f',  'n',  'r',  't',  'v',  '\\', 0, | ||||
| 	       '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' }; | ||||
|  | ||||
| 	switch (c = *(*ptr)++) { | ||||
| 	case 'a': | ||||
| 		c = '\a'; | ||||
| 		break; | ||||
| 	case 'b': | ||||
| 		c = '\b'; | ||||
| 		break; | ||||
| 	case 'f': | ||||
| 		c = '\f'; | ||||
| 		break; | ||||
| 	case 'n': | ||||
| 		c = '\n'; | ||||
| 		break; | ||||
| 	case 'r': | ||||
| 		c = '\r'; | ||||
| 		break; | ||||
| 	case 't': | ||||
| 		c = '\t'; | ||||
| 		break; | ||||
| 	case 'v': | ||||
| 		c = '\v'; | ||||
| 		break; | ||||
| 	case '\\': | ||||
| 		c = '\\'; | ||||
| 		break; | ||||
| 	case '0': case '1': case '2': case '3': | ||||
| 	case '4': case '5': case '6': case '7': | ||||
| 		c -= '0'; | ||||
| 		if ('0' <= **ptr && **ptr <= '7') { | ||||
| 			c = c * 8 + (*(*ptr)++ - '0'); | ||||
| 			if ('0' <= **ptr && **ptr <= '7') | ||||
| 				c = c * 8 + (*(*ptr)++ - '0'); | ||||
| 		} | ||||
| 		break; | ||||
| 	default: | ||||
| 		(*ptr)--; | ||||
| 		c = '\\'; | ||||
| 		break; | ||||
| 	} | ||||
| 	return c; | ||||
|        const char *p; | ||||
| 	   char *q; | ||||
|        int num_digits; | ||||
|        unsigned int n; | ||||
|  | ||||
|        n = 0; | ||||
| 	   q = *ptr; | ||||
|  | ||||
|        for ( num_digits = 0 ; num_digits < 3 ; ++num_digits) { | ||||
| 	       if ((*q < '0') || (*q > '7')) { /* not a digit? */ | ||||
| 		       break; | ||||
| 	       } | ||||
| 	       n = n * 8 + (*q++ - '0'); | ||||
|        } | ||||
|  | ||||
|        if (num_digits == 0) {	/* mnemonic escape sequence? */ | ||||
| 		   for (p=charmap ; *p ; p++) { | ||||
| 			   if (*p == *q) { | ||||
| 				   q++; | ||||
| 				   break; | ||||
| 			   } | ||||
| 		   } | ||||
| 		   n = *(p+(sizeof(charmap)/2)); | ||||
| 	   } | ||||
|  | ||||
| 	   /* doesn't hurt to fall through to here from mnemonic case */ | ||||
| 	   if (n > UCHAR_MAX) {	/* is octal code too big for a char? */ | ||||
| 		   n /= 8;			/* adjust value and */ | ||||
| 		   --q;				/* back up one char */ | ||||
| 	   } | ||||
|  | ||||
| 	   *ptr = q; | ||||
| 	   return (char) n; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @@ -1737,23 +1736,45 @@ ssize_t safe_read(int fd, void *buf, size_t count) | ||||
| #endif | ||||
|  | ||||
| #ifdef BB_FEATURE_HUMAN_READABLE | ||||
| char *format(unsigned long val, unsigned long hr) | ||||
| const char *format(unsigned long val, unsigned long hr) | ||||
| { | ||||
| 	static char str[10] = "\0"; | ||||
| 	static const char strings[] = { '0', 0, 'k', 0, 'M', 0, 'G', 0 }; | ||||
| 	static const char fmt[] = "%lu"; | ||||
| 	static const char fmt_u[] = "%lu.%lu%s"; | ||||
|  | ||||
| 	if(val == 0) | ||||
| 		return("0"); | ||||
| 	if(hr) | ||||
| 		snprintf(str, 9, "%ld", val/hr); | ||||
| 	else if(val >= GIGABYTE) | ||||
| 		snprintf(str, 9, "%.1LfG", ((long double)(val)/GIGABYTE)); | ||||
| 	else if(val >= MEGABYTE) | ||||
| 		snprintf(str, 9, "%.1LfM", ((long double)(val)/MEGABYTE)); | ||||
| 	else if(val >= KILOBYTE) | ||||
| 		snprintf(str, 9, "%.1Lfk", ((long double)(val)/KILOBYTE)); | ||||
| 	else | ||||
| 		snprintf(str, 9, "%ld", (val)); | ||||
| 	return(str); | ||||
| 	static char str[10]; | ||||
|  | ||||
| 	unsigned long frac __attribute__ ((unused));	/* 'may be uninitialized' warning is ok */ | ||||
| 	const char *u; | ||||
| 	const char *f; | ||||
|  | ||||
| #if 1 | ||||
| 	if(val == 0) {				/* This may be omitted to reduce size */ | ||||
| 		return strings;			/* at the cost of speed. */ | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	u = strings; | ||||
| 	f = fmt; | ||||
| 	if (hr) { | ||||
| 		val /= hr; | ||||
| 	} else { | ||||
| 		while ((val >= KILOBYTE) && (*u != 'G')) { | ||||
| 			f = fmt_u; | ||||
| 			u += 2; | ||||
| 			frac = (((val % KILOBYTE) * 10) + (KILOBYTE/2)) / KILOBYTE; | ||||
| 			val /= KILOBYTE; | ||||
| 			if (frac >= 10) {	/* We need to round up here. */ | ||||
| 				++val; | ||||
| 				frac = 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* If f==fmt then 'frac' and 'u' are ignored and need not be set. */ | ||||
| 	snprintf(str, sizeof(str), f, val, frac, u); | ||||
|  | ||||
| 	return str; | ||||
| } | ||||
| #endif | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user