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 #endif
#ifdef BB_FEATURE_HUMAN_READABLE #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 KILOBYTE 1024
#define MEGABYTE (KILOBYTE*1024) #define MEGABYTE (KILOBYTE*1024)
#define GIGABYTE (MEGABYTE*1024) #define GIGABYTE (MEGABYTE*1024)

View File

@ -232,7 +232,7 @@ extern int sysinfo (struct sysinfo* info);
#endif #endif
#ifdef BB_FEATURE_HUMAN_READABLE #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 KILOBYTE 1024
#define MEGABYTE (KILOBYTE*1024) #define MEGABYTE (KILOBYTE*1024)
#define GIGABYTE (MEGABYTE*1024) #define GIGABYTE (MEGABYTE*1024)

281
utility.c
View File

@ -51,6 +51,7 @@
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/utsname.h> /* for uname(2) */ #include <sys/utsname.h> /* for uname(2) */
@ -77,7 +78,7 @@ const char mtab_file[] = "/proc/mounts";
extern void usage(const char *usage) 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); exit(EXIT_FAILURE);
} }
@ -145,16 +146,21 @@ extern void perror_msg_and_die(const char *s, ...)
extern int get_kernel_revision(void) extern int get_kernel_revision(void)
{ {
struct utsname name; struct utsname name;
int major = 0, minor = 0, patch = 0; char *s;
int i, r;
if (uname(&name) == -1) { if (uname(&name) == -1) {
perror_msg("cannot get system information"); perror_msg("cannot get system information");
return (0); return (0);
} }
major = atoi(strtok(name.release, "."));
minor = atoi(strtok(NULL, ".")); s = name.release;
patch = atoi(strtok(NULL, ".")); r = 0;
return major * 65536 + minor * 256 + patch; for (i=0 ; i<3 ; i++) {
r = r * 256 + atoi(strtok(s, "."));
s = NULL;
}
return r;
} }
#endif /* BB_INIT */ #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) || defined (BB_MKFIFO) || defined (BB_MKNOD) || defined (BB_AR)
/* [ugoa]{+|-|=}[rwxst] */ /* [ugoa]{+|-|=}[rwxst] */
extern int parse_mode(const char *s, mode_t * theMode) 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; S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
mode_t orMode = 0; mode_t orMode = 0;
mode_t mode = 0; mode_t mode;
mode_t groups = 0; mode_t groups;
char type; char type;
char c; char c;
if (s==NULL) if (s==NULL) {
return (FALSE); return (FALSE);
}
do { do {
for (;;) { mode = 0;
switch (c = *s++) { groups = 0;
case '\0': NEXT_GROUP:
return -1; if ((c = *s++) == '\0') {
case 'u': return -1;
groups |= S_ISUID | S_IRWXU; }
continue; for (p=group_string ; *p ; p++) {
case 'g': if (*p == c) {
groups |= S_ISGID | S_IRWXG; groups |= group_set[(int)(p-group_string)];
continue; goto NEXT_GROUP;
case 'o': }
groups |= S_IRWXO; }
continue; switch (c) {
case 'a':
groups |= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
continue;
case '+':
case '=': case '=':
case '+':
case '-': case '-':
type = c; type = c;
if (groups == 0) /* The default is "all" */ if (groups == 0) { /* The default is "all" */
groups |= groups |= S_ISUID | S_ISGID | S_ISVTX
S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | S_IRWXU | S_IRWXG | S_IRWXO;
}
break; break;
default: default:
if (isdigit(c) && c >= '0' && c <= '7' && if ((c < '0') || (c > '7') || (mode | groups)) {
mode == 0 && groups == 0) { return (FALSE);
} else {
*theMode = strtol(--s, NULL, 8); *theMode = strtol(--s, NULL, 8);
return (TRUE); return (TRUE);
} else }
return (FALSE);
}
break;
} }
while ((c = *s++) != '\0') { NEXT_MODE:
switch (c) { if (((c = *s++) != '\0') && (c != ',')) {
case ',': for (p=mode_string ; *p ; p++) {
break; if (*p == c) {
case 'r': mode |= mode_set[(int)(p-mode_string)];
mode |= S_IRUSR | S_IRGRP | S_IROTH; goto NEXT_MODE;
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);
} }
break; break; /* We're done so break out of loop.*/
} }
switch (type) { switch (type) {
case '=': case '=':
andMode &= ~(groups); andMode &= ~(groups); /* Now fall through. */
/* fall through */ case '+':
case '+': orMode |= mode & groups;
orMode |= mode & groups; break;
break; case '-':
case '-': andMode &= ~(mode & groups);
andMode &= ~(mode & groups); orMode &= ~(mode & groups);
orMode &= andMode; break;
break;
} }
} while (c == ','); } while (c == ',');
*theMode &= andMode; *theMode &= andMode;
*theMode |= orMode; *theMode |= orMode;
return (TRUE);
}
return TRUE;
}
#endif #endif
/* BB_CHMOD_CHOWN_CHGRP || BB_MKDIR || BB_MKFIFO || BB_MKNOD */ /* 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 #if defined BB_ECHO || defined BB_SH || defined BB_TR
char process_escape_sequence(char **ptr) 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)++) { const char *p;
case 'a': char *q;
c = '\a'; int num_digits;
break; unsigned int n;
case 'b':
c = '\b'; n = 0;
break; q = *ptr;
case 'f':
c = '\f'; for ( num_digits = 0 ; num_digits < 3 ; ++num_digits) {
break; if ((*q < '0') || (*q > '7')) { /* not a digit? */
case 'n': break;
c = '\n'; }
break; n = n * 8 + (*q++ - '0');
case 'r': }
c = '\r';
break; if (num_digits == 0) { /* mnemonic escape sequence? */
case 't': for (p=charmap ; *p ; p++) {
c = '\t'; if (*p == *q) {
break; q++;
case 'v': break;
c = '\v'; }
break; }
case '\\': n = *(p+(sizeof(charmap)/2));
c = '\\'; }
break;
case '0': case '1': case '2': case '3': /* doesn't hurt to fall through to here from mnemonic case */
case '4': case '5': case '6': case '7': if (n > UCHAR_MAX) { /* is octal code too big for a char? */
c -= '0'; n /= 8; /* adjust value and */
if ('0' <= **ptr && **ptr <= '7') { --q; /* back up one char */
c = c * 8 + (*(*ptr)++ - '0'); }
if ('0' <= **ptr && **ptr <= '7')
c = c * 8 + (*(*ptr)++ - '0'); *ptr = q;
} return (char) n;
break;
default:
(*ptr)--;
c = '\\';
break;
}
return c;
} }
#endif #endif
@ -1737,23 +1736,45 @@ ssize_t safe_read(int fd, void *buf, size_t count)
#endif #endif
#ifdef BB_FEATURE_HUMAN_READABLE #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) static char str[10];
return("0");
if(hr) unsigned long frac __attribute__ ((unused)); /* 'may be uninitialized' warning is ok */
snprintf(str, 9, "%ld", val/hr); const char *u;
else if(val >= GIGABYTE) const char *f;
snprintf(str, 9, "%.1LfG", ((long double)(val)/GIGABYTE));
else if(val >= MEGABYTE) #if 1
snprintf(str, 9, "%.1LfM", ((long double)(val)/MEGABYTE)); if(val == 0) { /* This may be omitted to reduce size */
else if(val >= KILOBYTE) return strings; /* at the cost of speed. */
snprintf(str, 9, "%.1Lfk", ((long double)(val)/KILOBYTE)); }
else #endif
snprintf(str, 9, "%ld", (val));
return(str); 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 #endif