diff options
author | Eric Andersen <andersen@codepoet.org> | 2001-02-14 07:15:30 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2001-02-14 07:15:30 +0000 |
commit | fc83c4c3535cb5bce344821d382122262a8450f5 (patch) | |
tree | c61695c497186a7e201315b93541846c3a72f201 | |
parent | 6fd8c664c1bcb44429b81444be640ff08cac3702 (diff) | |
download | busybox-w32-fc83c4c3535cb5bce344821d382122262a8450f5.tar.gz busybox-w32-fc83c4c3535cb5bce344821d382122262a8450f5.tar.bz2 busybox-w32-fc83c4c3535cb5bce344821d382122262a8450f5.zip |
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),
-rw-r--r-- | busybox.h | 2 | ||||
-rw-r--r-- | include/busybox.h | 2 | ||||
-rw-r--r-- | utility.c | 285 |
3 files changed, 155 insertions, 134 deletions
@@ -232,7 +232,7 @@ extern int sysinfo (struct sysinfo* info); | |||
232 | #endif | 232 | #endif |
233 | 233 | ||
234 | #ifdef BB_FEATURE_HUMAN_READABLE | 234 | #ifdef BB_FEATURE_HUMAN_READABLE |
235 | char *format(unsigned long val, unsigned long hr); | 235 | const char *format(unsigned long val, unsigned long hr); |
236 | #define KILOBYTE 1024 | 236 | #define KILOBYTE 1024 |
237 | #define MEGABYTE (KILOBYTE*1024) | 237 | #define MEGABYTE (KILOBYTE*1024) |
238 | #define GIGABYTE (MEGABYTE*1024) | 238 | #define GIGABYTE (MEGABYTE*1024) |
diff --git a/include/busybox.h b/include/busybox.h index 2fc0cc7e0..101e65989 100644 --- a/include/busybox.h +++ b/include/busybox.h | |||
@@ -232,7 +232,7 @@ extern int sysinfo (struct sysinfo* info); | |||
232 | #endif | 232 | #endif |
233 | 233 | ||
234 | #ifdef BB_FEATURE_HUMAN_READABLE | 234 | #ifdef BB_FEATURE_HUMAN_READABLE |
235 | char *format(unsigned long val, unsigned long hr); | 235 | const char *format(unsigned long val, unsigned long hr); |
236 | #define KILOBYTE 1024 | 236 | #define KILOBYTE 1024 |
237 | #define MEGABYTE (KILOBYTE*1024) | 237 | #define MEGABYTE (KILOBYTE*1024) |
238 | #define GIGABYTE (MEGABYTE*1024) | 238 | #define GIGABYTE (MEGABYTE*1024) |
@@ -51,6 +51,7 @@ | |||
51 | #include <unistd.h> | 51 | #include <unistd.h> |
52 | #include <ctype.h> | 52 | #include <ctype.h> |
53 | #include <stdlib.h> | 53 | #include <stdlib.h> |
54 | #include <limits.h> | ||
54 | #include <sys/ioctl.h> | 55 | #include <sys/ioctl.h> |
55 | #include <sys/utsname.h> /* for uname(2) */ | 56 | #include <sys/utsname.h> /* for uname(2) */ |
56 | 57 | ||
@@ -77,7 +78,7 @@ const char mtab_file[] = "/proc/mounts"; | |||
77 | 78 | ||
78 | extern void usage(const char *usage) | 79 | extern void usage(const char *usage) |
79 | { | 80 | { |
80 | fprintf(stderr, "%s\n\nUsage: %s\n", full_version, usage); | 81 | fprintf(stderr, "%s\n\nUsage: %s\n\n", full_version, usage); |
81 | exit(EXIT_FAILURE); | 82 | exit(EXIT_FAILURE); |
82 | } | 83 | } |
83 | 84 | ||
@@ -145,16 +146,21 @@ extern void perror_msg_and_die(const char *s, ...) | |||
145 | extern int get_kernel_revision(void) | 146 | extern int get_kernel_revision(void) |
146 | { | 147 | { |
147 | struct utsname name; | 148 | struct utsname name; |
148 | int major = 0, minor = 0, patch = 0; | 149 | char *s; |
150 | int i, r; | ||
149 | 151 | ||
150 | if (uname(&name) == -1) { | 152 | if (uname(&name) == -1) { |
151 | perror_msg("cannot get system information"); | 153 | perror_msg("cannot get system information"); |
152 | return (0); | 154 | return (0); |
153 | } | 155 | } |
154 | major = atoi(strtok(name.release, ".")); | 156 | |
155 | minor = atoi(strtok(NULL, ".")); | 157 | s = name.release; |
156 | patch = atoi(strtok(NULL, ".")); | 158 | r = 0; |
157 | return major * 65536 + minor * 256 + patch; | 159 | for (i=0 ; i<3 ; i++) { |
160 | r = r * 256 + atoi(strtok(s, ".")); | ||
161 | s = NULL; | ||
162 | } | ||
163 | return r; | ||
158 | } | 164 | } |
159 | #endif /* BB_INIT */ | 165 | #endif /* BB_INIT */ |
160 | 166 | ||
@@ -749,102 +755,100 @@ extern int create_path(const char *name, int mode) | |||
749 | || defined (BB_MKFIFO) || defined (BB_MKNOD) || defined (BB_AR) | 755 | || defined (BB_MKFIFO) || defined (BB_MKNOD) || defined (BB_AR) |
750 | /* [ugoa]{+|-|=}[rwxst] */ | 756 | /* [ugoa]{+|-|=}[rwxst] */ |
751 | 757 | ||
752 | |||
753 | |||
754 | extern int parse_mode(const char *s, mode_t * theMode) | 758 | extern int parse_mode(const char *s, mode_t * theMode) |
755 | { | 759 | { |
756 | mode_t andMode = | 760 | static const mode_t group_set[] = { |
761 | S_ISUID | S_IRWXU, /* u */ | ||
762 | S_ISGID | S_IRWXG, /* g */ | ||
763 | S_IRWXO, /* o */ | ||
764 | S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO /* a */ | ||
765 | }; | ||
766 | |||
767 | static const mode_t mode_set[] = { | ||
768 | S_IRUSR | S_IRGRP | S_IROTH, /* r */ | ||
769 | S_IWUSR | S_IWGRP | S_IWOTH, /* w */ | ||
770 | S_IXUSR | S_IXGRP | S_IXOTH, /* x */ | ||
771 | S_ISUID | S_ISGID, /* s */ | ||
772 | S_ISVTX /* t */ | ||
773 | }; | ||
774 | |||
775 | static const char group_string[] = "ugoa"; | ||
776 | static const char mode_string[] = "rwxst"; | ||
777 | |||
778 | const char *p; | ||
757 | 779 | ||
780 | mode_t andMode = | ||
758 | S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | 781 | S_ISVTX | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; |
759 | mode_t orMode = 0; | 782 | mode_t orMode = 0; |
760 | mode_t mode = 0; | 783 | mode_t mode; |
761 | mode_t groups = 0; | 784 | mode_t groups; |
762 | char type; | 785 | char type; |
763 | char c; | 786 | char c; |
764 | 787 | ||
765 | if (s==NULL) | 788 | if (s==NULL) { |
766 | return (FALSE); | 789 | return (FALSE); |
790 | } | ||
767 | 791 | ||
768 | do { | 792 | do { |
769 | for (;;) { | 793 | mode = 0; |
770 | switch (c = *s++) { | 794 | groups = 0; |
771 | case '\0': | 795 | NEXT_GROUP: |
772 | return -1; | 796 | if ((c = *s++) == '\0') { |
773 | case 'u': | 797 | return -1; |
774 | groups |= S_ISUID | S_IRWXU; | 798 | } |
775 | continue; | 799 | for (p=group_string ; *p ; p++) { |
776 | case 'g': | 800 | if (*p == c) { |
777 | groups |= S_ISGID | S_IRWXG; | 801 | groups |= group_set[(int)(p-group_string)]; |
778 | continue; | 802 | goto NEXT_GROUP; |
779 | case 'o': | 803 | } |
780 | groups |= S_IRWXO; | 804 | } |
781 | continue; | 805 | switch (c) { |
782 | case 'a': | ||
783 | groups |= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | ||
784 | continue; | ||
785 | case '+': | ||
786 | case '=': | 806 | case '=': |
807 | case '+': | ||
787 | case '-': | 808 | case '-': |
788 | type = c; | 809 | type = c; |
789 | if (groups == 0) /* The default is "all" */ | 810 | if (groups == 0) { /* The default is "all" */ |
790 | groups |= | 811 | groups |= S_ISUID | S_ISGID | S_ISVTX |
791 | S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; | 812 | | S_IRWXU | S_IRWXG | S_IRWXO; |
813 | } | ||
792 | break; | 814 | break; |
793 | default: | 815 | default: |
794 | if (isdigit(c) && c >= '0' && c <= '7' && | 816 | if ((c < '0') || (c > '7') || (mode | groups)) { |
795 | mode == 0 && groups == 0) { | 817 | return (FALSE); |
818 | } else { | ||
796 | *theMode = strtol(--s, NULL, 8); | 819 | *theMode = strtol(--s, NULL, 8); |
797 | return (TRUE); | 820 | return (TRUE); |
798 | } else | 821 | } |
799 | return (FALSE); | ||
800 | } | ||
801 | break; | ||
802 | } | 822 | } |
803 | 823 | ||
804 | while ((c = *s++) != '\0') { | 824 | NEXT_MODE: |
805 | switch (c) { | 825 | if (((c = *s++) != '\0') && (c != ',')) { |
806 | case ',': | 826 | for (p=mode_string ; *p ; p++) { |
807 | break; | 827 | if (*p == c) { |
808 | case 'r': | 828 | mode |= mode_set[(int)(p-mode_string)]; |
809 | mode |= S_IRUSR | S_IRGRP | S_IROTH; | 829 | goto NEXT_MODE; |
810 | continue; | 830 | } |
811 | case 'w': | ||
812 | mode |= S_IWUSR | S_IWGRP | S_IWOTH; | ||
813 | continue; | ||
814 | case 'x': | ||
815 | mode |= S_IXUSR | S_IXGRP | S_IXOTH; | ||
816 | continue; | ||
817 | case 's': | ||
818 | mode |= S_IXGRP | S_ISUID | S_ISGID; | ||
819 | continue; | ||
820 | case 't': | ||
821 | mode |= 0; | ||
822 | continue; | ||
823 | default: | ||
824 | *theMode &= andMode; | ||
825 | *theMode |= orMode; | ||
826 | return (TRUE); | ||
827 | } | 831 | } |
828 | break; | 832 | break; /* We're done so break out of loop.*/ |
829 | } | 833 | } |
830 | switch (type) { | 834 | switch (type) { |
831 | case '=': | 835 | case '=': |
832 | andMode &= ~(groups); | 836 | andMode &= ~(groups); /* Now fall through. */ |
833 | /* fall through */ | 837 | case '+': |
834 | case '+': | 838 | orMode |= mode & groups; |
835 | orMode |= mode & groups; | 839 | break; |
836 | break; | 840 | case '-': |
837 | case '-': | 841 | andMode &= ~(mode & groups); |
838 | andMode &= ~(mode & groups); | 842 | orMode &= ~(mode & groups); |
839 | orMode &= andMode; | 843 | break; |
840 | break; | ||
841 | } | 844 | } |
842 | } while (c == ','); | 845 | } while (c == ','); |
846 | |||
843 | *theMode &= andMode; | 847 | *theMode &= andMode; |
844 | *theMode |= orMode; | 848 | *theMode |= orMode; |
845 | return (TRUE); | ||
846 | } | ||
847 | 849 | ||
850 | return TRUE; | ||
851 | } | ||
848 | 852 | ||
849 | #endif | 853 | #endif |
850 | /* BB_CHMOD_CHOWN_CHGRP || BB_MKDIR || BB_MKFIFO || BB_MKNOD */ | 854 | /* BB_CHMOD_CHOWN_CHGRP || BB_MKDIR || BB_MKFIFO || BB_MKNOD */ |
@@ -1575,48 +1579,43 @@ extern int print_file_by_name(char *filename) | |||
1575 | #if defined BB_ECHO || defined BB_SH || defined BB_TR | 1579 | #if defined BB_ECHO || defined BB_SH || defined BB_TR |
1576 | char process_escape_sequence(char **ptr) | 1580 | char process_escape_sequence(char **ptr) |
1577 | { | 1581 | { |
1578 | char c; | 1582 | static const char charmap[] = { |
1579 | 1583 | 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0, | |
1580 | switch (c = *(*ptr)++) { | 1584 | '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' }; |
1581 | case 'a': | 1585 | |
1582 | c = '\a'; | 1586 | const char *p; |
1583 | break; | 1587 | char *q; |
1584 | case 'b': | 1588 | int num_digits; |
1585 | c = '\b'; | 1589 | unsigned int n; |
1586 | break; | 1590 | |
1587 | case 'f': | 1591 | n = 0; |
1588 | c = '\f'; | 1592 | q = *ptr; |
1589 | break; | 1593 | |
1590 | case 'n': | 1594 | for ( num_digits = 0 ; num_digits < 3 ; ++num_digits) { |
1591 | c = '\n'; | 1595 | if ((*q < '0') || (*q > '7')) { /* not a digit? */ |
1592 | break; | 1596 | break; |
1593 | case 'r': | 1597 | } |
1594 | c = '\r'; | 1598 | n = n * 8 + (*q++ - '0'); |
1595 | break; | 1599 | } |
1596 | case 't': | 1600 | |
1597 | c = '\t'; | 1601 | if (num_digits == 0) { /* mnemonic escape sequence? */ |
1598 | break; | 1602 | for (p=charmap ; *p ; p++) { |
1599 | case 'v': | 1603 | if (*p == *q) { |
1600 | c = '\v'; | 1604 | q++; |
1601 | break; | 1605 | break; |
1602 | case '\\': | 1606 | } |
1603 | c = '\\'; | 1607 | } |
1604 | break; | 1608 | n = *(p+(sizeof(charmap)/2)); |
1605 | case '0': case '1': case '2': case '3': | 1609 | } |
1606 | case '4': case '5': case '6': case '7': | 1610 | |
1607 | c -= '0'; | 1611 | /* doesn't hurt to fall through to here from mnemonic case */ |
1608 | if ('0' <= **ptr && **ptr <= '7') { | 1612 | if (n > UCHAR_MAX) { /* is octal code too big for a char? */ |
1609 | c = c * 8 + (*(*ptr)++ - '0'); | 1613 | n /= 8; /* adjust value and */ |
1610 | if ('0' <= **ptr && **ptr <= '7') | 1614 | --q; /* back up one char */ |
1611 | c = c * 8 + (*(*ptr)++ - '0'); | 1615 | } |
1612 | } | 1616 | |
1613 | break; | 1617 | *ptr = q; |
1614 | default: | 1618 | return (char) n; |
1615 | (*ptr)--; | ||
1616 | c = '\\'; | ||
1617 | break; | ||
1618 | } | ||
1619 | return c; | ||
1620 | } | 1619 | } |
1621 | #endif | 1620 | #endif |
1622 | 1621 | ||
@@ -1737,23 +1736,45 @@ ssize_t safe_read(int fd, void *buf, size_t count) | |||
1737 | #endif | 1736 | #endif |
1738 | 1737 | ||
1739 | #ifdef BB_FEATURE_HUMAN_READABLE | 1738 | #ifdef BB_FEATURE_HUMAN_READABLE |
1740 | char *format(unsigned long val, unsigned long hr) | 1739 | const char *format(unsigned long val, unsigned long hr) |
1741 | { | 1740 | { |
1742 | static char str[10] = "\0"; | 1741 | static const char strings[] = { '0', 0, 'k', 0, 'M', 0, 'G', 0 }; |
1743 | 1742 | static const char fmt[] = "%lu"; | |
1744 | if(val == 0) | 1743 | static const char fmt_u[] = "%lu.%lu%s"; |
1745 | return("0"); | 1744 | |
1746 | if(hr) | 1745 | static char str[10]; |
1747 | snprintf(str, 9, "%ld", val/hr); | 1746 | |
1748 | else if(val >= GIGABYTE) | 1747 | unsigned long frac __attribute__ ((unused)); /* 'may be uninitialized' warning is ok */ |
1749 | snprintf(str, 9, "%.1LfG", ((long double)(val)/GIGABYTE)); | 1748 | const char *u; |
1750 | else if(val >= MEGABYTE) | 1749 | const char *f; |
1751 | snprintf(str, 9, "%.1LfM", ((long double)(val)/MEGABYTE)); | 1750 | |
1752 | else if(val >= KILOBYTE) | 1751 | #if 1 |
1753 | snprintf(str, 9, "%.1Lfk", ((long double)(val)/KILOBYTE)); | 1752 | if(val == 0) { /* This may be omitted to reduce size */ |
1754 | else | 1753 | return strings; /* at the cost of speed. */ |
1755 | snprintf(str, 9, "%ld", (val)); | 1754 | } |
1756 | return(str); | 1755 | #endif |
1756 | |||
1757 | u = strings; | ||
1758 | f = fmt; | ||
1759 | if (hr) { | ||
1760 | val /= hr; | ||
1761 | } else { | ||
1762 | while ((val >= KILOBYTE) && (*u != 'G')) { | ||
1763 | f = fmt_u; | ||
1764 | u += 2; | ||
1765 | frac = (((val % KILOBYTE) * 10) + (KILOBYTE/2)) / KILOBYTE; | ||
1766 | val /= KILOBYTE; | ||
1767 | if (frac >= 10) { /* We need to round up here. */ | ||
1768 | ++val; | ||
1769 | frac = 0; | ||
1770 | } | ||
1771 | } | ||
1772 | } | ||
1773 | |||
1774 | /* If f==fmt then 'frac' and 'u' are ignored and need not be set. */ | ||
1775 | snprintf(str, sizeof(str), f, val, frac, u); | ||
1776 | |||
1777 | return str; | ||
1757 | } | 1778 | } |
1758 | #endif | 1779 | #endif |
1759 | 1780 | ||