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:
parent
6fd8c664c1
commit
fc83c4c353
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user