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:
Eric Andersen 2001-02-14 07:15:30 +00:00
parent 6fd8c664c1
commit fc83c4c353
3 changed files with 153 additions and 132 deletions

View File

@ -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)

View File

@ -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
View File

@ -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