summaryrefslogtreecommitdiff
path: root/utility.c
diff options
context:
space:
mode:
authorEric Andersen2001-02-14 07:15:30 +0000
committerEric Andersen2001-02-14 07:15:30 +0000
commitfc83c4c3535cb5bce344821d382122262a8450f5 (patch)
treec61695c497186a7e201315b93541846c3a72f201 /utility.c
parent6fd8c664c1bcb44429b81444be640ff08cac3702 (diff)
downloadbusybox-fc83c4c3535cb5bce344821d382122262a8450f5.zip
busybox-fc83c4c3535cb5bce344821d382122262a8450f5.tar.gz
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),
Diffstat (limited to 'utility.c')
-rw-r--r--utility.c285
1 files changed, 153 insertions, 132 deletions
diff --git a/utility.c b/utility.c
index 9f0bca9..f3c184e 100644
--- a/utility.c
+++ b/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;
-
- 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;
+ static const char charmap[] = {
+ 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0,
+ '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
+
+ 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";
-
- 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 const char strings[] = { '0', 0, 'k', 0, 'M', 0, 'G', 0 };
+ static const char fmt[] = "%lu";
+ static const char fmt_u[] = "%lu.%lu%s";
+
+ 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