aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-13 11:16:09 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-13 11:16:09 +0000
commitc7497ea31b84eb3261a64a2e1a8e80643c26fd9d (patch)
tree4bd058053b81d7d6b829ef684d6be298f4a5c04f
parent25b463079d963ae4f482db7ced14d14c28b907b8 (diff)
downloadbusybox-w32-c7497ea31b84eb3261a64a2e1a8e80643c26fd9d.tar.gz
busybox-w32-c7497ea31b84eb3261a64a2e1a8e80643c26fd9d.tar.bz2
busybox-w32-c7497ea31b84eb3261a64a2e1a8e80643c26fd9d.zip
build system: introduce FEATURE_ASSUME_UNICODE
ls: use it. also do G trick. with UNICODE off: function old new delta ls_main 843 871 +28 show_color 1 - -1 showdirs 500 497 -3 my_stat 100 97 -3 terminal_width 4 - -4 tabstops 4 - -4 status 122 118 -4 static.dotdir 4 - -4 current_time_t 4 - -4 all_fmt 4 - -4 ------------------------------------------------------------------------------ (add/remove: 0/6 grow/shrink: 1/3 up/down: 28/-31) Total: -3 bytes Also was tested with UNICODE on with glibc.
-rw-r--r--Config.in12
-rw-r--r--coreutils/ls.c149
2 files changed, 99 insertions, 62 deletions
diff --git a/Config.in b/Config.in
index 0a7edf84c..e70caf5a1 100644
--- a/Config.in
+++ b/Config.in
@@ -21,6 +21,18 @@ config DESKTOP
21 Select this only if you plan to use busybox on full-blown 21 Select this only if you plan to use busybox on full-blown
22 desktop machine with common Linux distro, not on an embedded box. 22 desktop machine with common Linux distro, not on an embedded box.
23 23
24config FEATURE_ASSUME_UNICODE
25 bool "Assume that 1:1 char/glyph correspondence is not true"
26 default n
27 help
28 This makes various applets aware that one byte is not
29 one character on screen.
30
31 Busybox aims to eventually work correctly with Unicode displays.
32 Any older encodings are not guaranteed to work.
33 Probably by the time when busybox will be fully Unicode-clean,
34 other encodings will be mainly of historic interest.
35
24choice 36choice
25 prompt "Buffer allocation policy" 37 prompt "Buffer allocation policy"
26 default FEATURE_BUFFERS_USE_MALLOC 38 default FEATURE_BUFFERS_USE_MALLOC
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 985086634..7d33eae8d 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -31,6 +31,10 @@
31 31
32#include "libbb.h" 32#include "libbb.h"
33 33
34#if ENABLE_FEATURE_ASSUME_UNICODE
35#include <wchar.h>
36#endif
37
34/* This is a NOEXEC applet. Be very careful! */ 38/* This is a NOEXEC applet. Be very careful! */
35 39
36 40
@@ -114,18 +118,6 @@ SPLIT_SUBDIR = 2,
114#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\ 118#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\
115 "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) 119 "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)])
116 120
117/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
118#if ENABLE_FEATURE_LS_COLOR
119static smallint show_color;
120/* long option entry used only for --color, which has no short option
121 * equivalent */
122static const char ls_color_opt[] ALIGN1 =
123 "color\0" Optional_argument "\xff" /* no short equivalent */
124 ;
125#else
126enum { show_color = 0 };
127#endif
128
129/* 121/*
130 * a directory entry and its stat info are stored here 122 * a directory entry and its stat info are stored here
131 */ 123 */
@@ -137,25 +129,68 @@ struct dnode { /* the basic node */
137 USE_SELINUX(security_context_t sid;) 129 USE_SELINUX(security_context_t sid;)
138 struct dnode *next; /* point at the next node */ 130 struct dnode *next; /* point at the next node */
139}; 131};
140typedef struct dnode dnode_t;
141 132
142static struct dnode **list_dir(const char *); 133static struct dnode **list_dir(const char *);
143static struct dnode **dnalloc(int); 134static struct dnode **dnalloc(int);
144static int list_single(struct dnode *); 135static int list_single(const struct dnode *);
145 136
146static unsigned all_fmt;
147 137
138struct globals {
139#if ENABLE_FEATURE_LS_COLOR
140 smallint show_color;
141#endif
142 smallint exit_failure;
143 unsigned all_fmt;
144#if ENABLE_FEATURE_AUTOWIDTH
145 unsigned tabstops; // = COLUMN_GAP;
146 unsigned terminal_width; // = TERMINAL_WIDTH;
147#endif
148#if ENABLE_FEATURE_LS_TIMESTAMPS
149 /* Do time() just once. Saves one syscall per file for "ls -l" */
150 time_t current_time_t;
151#endif
152};
153#define G (*(struct globals*)&bb_common_bufsiz1)
154#if ENABLE_FEATURE_LS_COLOR
155#define show_color (G.show_color )
156#else
157enum { show_color = 0 };
158#endif
159#define exit_failure (G.exit_failure )
160#define all_fmt (G.all_fmt )
148#if ENABLE_FEATURE_AUTOWIDTH 161#if ENABLE_FEATURE_AUTOWIDTH
149static unsigned tabstops = COLUMN_GAP; 162#define tabstops (G.tabstops )
150static unsigned terminal_width = TERMINAL_WIDTH; 163#define terminal_width (G.terminal_width)
151#else 164#else
152enum { 165enum {
153 tabstops = COLUMN_GAP, 166 tabstops = COLUMN_GAP,
154 terminal_width = TERMINAL_WIDTH, 167 terminal_width = TERMINAL_WIDTH,
155}; 168};
156#endif 169#endif
170#define current_time_t (G.current_time_t)
171/* memset: we have to zero it out because of NOEXEC */
172#define INIT_G() { \
173 memset(&G, 0, sizeof(G)); \
174 tabstops = COLUMN_GAP; \
175 terminal_width = TERMINAL_WIDTH; \
176 USE_FEATURE_LS_TIMESTAMPS(time(&current_time_t);) \
177}
178
179
180#if ENABLE_FEATURE_ASSUME_UNICODE
181/* libbb candidate */
182static size_t mbstrlen(const char *string)
183{
184 size_t width = mbsrtowcs(NULL /*dest*/, &string,
185 MAXINT(size_t) /*len*/, NULL /*state*/);
186 if (width == (size_t)-1)
187 return strlen(string);
188 return width;
189}
190#else
191#define mbstrlen(string) strlen(string)
192#endif
157 193
158static int status = EXIT_SUCCESS;
159 194
160static struct dnode *my_stat(const char *fullname, const char *name, int force_follow) 195static struct dnode *my_stat(const char *fullname, const char *name, int force_follow)
161{ 196{
@@ -171,7 +206,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
171#endif 206#endif
172 if (stat(fullname, &dstat)) { 207 if (stat(fullname, &dstat)) {
173 bb_simple_perror_msg(fullname); 208 bb_simple_perror_msg(fullname);
174 status = EXIT_FAILURE; 209 exit_failure = 1;
175 return 0; 210 return 0;
176 } 211 }
177 } else { 212 } else {
@@ -182,7 +217,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
182#endif 217#endif
183 if (lstat(fullname, &dstat)) { 218 if (lstat(fullname, &dstat)) {
184 bb_simple_perror_msg(fullname); 219 bb_simple_perror_msg(fullname);
185 status = EXIT_FAILURE; 220 exit_failure = 1;
186 return 0; 221 return 0;
187 } 222 }
188 } 223 }
@@ -395,7 +430,7 @@ static void showfiles(struct dnode **dn, int nfiles)
395 } else { 430 } else {
396 /* find the longest file name, use that as the column width */ 431 /* find the longest file name, use that as the column width */
397 for (i = 0; i < nfiles; i++) { 432 for (i = 0; i < nfiles; i++) {
398 int len = strlen(dn[i]->name); 433 int len = mbstrlen(dn[i]->name);
399 if (column_width < len) 434 if (column_width < len)
400 column_width = len; 435 column_width = len;
401 } 436 }
@@ -494,7 +529,7 @@ static struct dnode **list_dir(const char *path)
494 nfiles = 0; 529 nfiles = 0;
495 dir = warn_opendir(path); 530 dir = warn_opendir(path);
496 if (dir == NULL) { 531 if (dir == NULL) {
497 status = EXIT_FAILURE; 532 exit_failure = 1;
498 return NULL; /* could not open the dir */ 533 return NULL; /* could not open the dir */
499 } 534 }
500 while ((entry = readdir(dir)) != NULL) { 535 while ((entry = readdir(dir)) != NULL) {
@@ -538,13 +573,7 @@ static struct dnode **list_dir(const char *path)
538} 573}
539 574
540 575
541#if ENABLE_FEATURE_LS_TIMESTAMPS 576static int list_single(const struct dnode *dn)
542/* Do time() just once. Saves one syscall per file for "ls -l" */
543/* Initialized in main() */
544static time_t current_time_t;
545#endif
546
547static int list_single(struct dnode *dn)
548{ 577{
549 int i, column = 0; 578 int i, column = 0;
550 579
@@ -658,7 +687,12 @@ static int list_single(struct dnode *dn)
658 fgcolor(info.st_mode)); 687 fgcolor(info.st_mode));
659 } 688 }
660#endif 689#endif
690#if ENABLE_FEATURE_ASSUME_UNICODE
691 printf("%s", dn->name);
692 column += mbstrlen(dn->name);
693#else
661 column += printf("%s", dn->name); 694 column += printf("%s", dn->name);
695#endif
662 if (show_color) { 696 if (show_color) {
663 printf("\033[0m"); 697 printf("\033[0m");
664 } 698 }
@@ -701,6 +735,7 @@ static int list_single(struct dnode *dn)
701 return column; 735 return column;
702} 736}
703 737
738
704/* "[-]Cadil1", POSIX mandated options, busybox always supports */ 739/* "[-]Cadil1", POSIX mandated options, busybox always supports */
705/* "[-]gnsx", POSIX non-mandated options, busybox always supports */ 740/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
706/* "[-]Ak" GNU options, busybox always supports */ 741/* "[-]Ak" GNU options, busybox always supports */
@@ -779,11 +814,18 @@ static const unsigned opt_flags[] = {
779}; 814};
780 815
781 816
782/* THIS IS A "SAFE" APPLET, main() MAY BE CALLED INTERNALLY FROM SHELL */ 817/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
783/* BE CAREFUL! */ 818#if ENABLE_FEATURE_LS_COLOR
819/* long option entry used only for --color, which has no short option
820 * equivalent */
821static const char ls_color_opt[] ALIGN1 =
822 "color\0" Optional_argument "\xff" /* no short equivalent */
823 ;
824#endif
825
784 826
785int ls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 827int ls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
786int ls_main(int argc, char **argv) 828int ls_main(int argc ATTRIBUTE_UNUSED, char **argv)
787{ 829{
788 struct dnode **dnd; 830 struct dnode **dnd;
789 struct dnode **dnf; 831 struct dnode **dnf;
@@ -791,18 +833,13 @@ int ls_main(int argc, char **argv)
791 struct dnode *dn; 833 struct dnode *dn;
792 struct dnode *cur; 834 struct dnode *cur;
793 unsigned opt; 835 unsigned opt;
794 int nfiles = 0; 836 int nfiles;
795 int dnfiles; 837 int dnfiles;
796 int dndirs; 838 int dndirs;
797 int oi;
798 int ac;
799 int i; 839 int i;
800 char **av;
801 USE_FEATURE_LS_COLOR(char *color_opt;) 840 USE_FEATURE_LS_COLOR(char *color_opt;)
802 841
803#if ENABLE_FEATURE_LS_TIMESTAMPS 842 INIT_G();
804 time(&current_time_t);
805#endif
806 843
807 all_fmt = LIST_SHORT | 844 all_fmt = LIST_SHORT |
808 (ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD)); 845 (ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD));
@@ -883,39 +920,27 @@ int ls_main(int argc, char **argv)
883 if (!(all_fmt & STYLE_MASK)) 920 if (!(all_fmt & STYLE_MASK))
884 all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); 921 all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE);
885 922
886 /* 923 argv += optind;
887 * when there are no cmd line args we have to supply a default "." arg. 924 if (!argv[0])
888 * we will create a second argv array, "av" that will hold either 925 *--argv = (char*)".";
889 * our created "." arg, or the real cmd line args. The av array
890 * just holds the pointers- we don't move the date the pointers
891 * point to.
892 */
893 ac = argc - optind; /* how many cmd line args are left */
894 if (ac < 1) {
895 static const char *const dotdir[] = { "." };
896
897 av = (char **) dotdir;
898 ac = 1;
899 } else {
900 av = argv + optind;
901 }
902 926
903 /* now, everything is in the av array */ 927 if (argv[1])
904 if (ac > 1) 928 all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */
905 all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */
906 929
907 /* stuff the command line file names into a dnode array */ 930 /* stuff the command line file names into a dnode array */
908 dn = NULL; 931 dn = NULL;
909 for (oi = 0; oi < ac; oi++) { 932 nfiles = 0;
933 do {
910 /* ls w/o -l follows links on command line */ 934 /* ls w/o -l follows links on command line */
911 cur = my_stat(av[oi], av[oi], !(all_fmt & STYLE_LONG)); 935 cur = my_stat(*argv, *argv, !(all_fmt & STYLE_LONG));
936 argv++;
912 if (!cur) 937 if (!cur)
913 continue; 938 continue;
914 cur->allocated = 0; 939 cur->allocated = 0;
915 cur->next = dn; 940 cur->next = dn;
916 dn = cur; 941 dn = cur;
917 nfiles++; 942 nfiles++;
918 } 943 } while (*argv);
919 944
920 /* now that we know how many files there are 945 /* now that we know how many files there are
921 * allocate memory for an array to hold dnode pointers 946 * allocate memory for an array to hold dnode pointers
@@ -950,5 +975,5 @@ int ls_main(int argc, char **argv)
950 } 975 }
951 if (ENABLE_FEATURE_CLEAN_UP) 976 if (ENABLE_FEATURE_CLEAN_UP)
952 dfree(dnp, nfiles); 977 dfree(dnp, nfiles);
953 return status; 978 return (exit_failure == 0);
954} 979}