29 |
* 1. requires lstat (BSD) - how do you do it without? |
* 1. requires lstat (BSD) - how do you do it without? |
30 |
*/ |
*/ |
31 |
|
|
32 |
#include "busybox.h" |
#include "libbb.h" |
33 |
#include <getopt.h> |
|
34 |
|
#if ENABLE_FEATURE_ASSUME_UNICODE |
35 |
|
#include <wchar.h> |
36 |
|
#endif |
37 |
|
|
38 |
|
/* This is a NOEXEC applet. Be very careful! */ |
39 |
|
|
40 |
|
|
41 |
enum { |
enum { |
42 |
|
|
118 |
#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\ |
#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\ |
119 |
"\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) |
"\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) |
120 |
|
|
|
/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */ |
|
|
#if ENABLE_FEATURE_LS_COLOR |
|
|
static int show_color; |
|
|
/* long option entry used only for --color, which has no short option |
|
|
* equivalent */ |
|
|
static const struct option ls_color_opt[] = { |
|
|
{ "color", optional_argument, NULL, 1 }, |
|
|
{ NULL, 0, NULL, 0 } |
|
|
}; |
|
|
#else |
|
|
enum { show_color = 0 }; |
|
|
#endif |
|
|
|
|
121 |
/* |
/* |
122 |
* a directory entry and its stat info are stored here |
* a directory entry and its stat info are stored here |
123 |
*/ |
*/ |
124 |
struct dnode { /* the basic node */ |
struct dnode { /* the basic node */ |
125 |
char *name; /* the dir entry name */ |
const char *name; /* the dir entry name */ |
126 |
char *fullname; /* the dir entry name */ |
const char *fullname; /* the dir entry name */ |
127 |
int allocated; |
int allocated; |
128 |
struct stat dstat; /* the file stat info */ |
struct stat dstat; /* the file stat info */ |
129 |
USE_SELINUX(security_context_t sid;) |
USE_SELINUX(security_context_t sid;) |
130 |
struct dnode *next; /* point at the next node */ |
struct dnode *next; /* point at the next node */ |
131 |
}; |
}; |
|
typedef struct dnode dnode_t; |
|
132 |
|
|
133 |
static struct dnode **list_dir(const char *); |
static struct dnode **list_dir(const char *); |
134 |
static struct dnode **dnalloc(int); |
static struct dnode **dnalloc(int); |
135 |
static int list_single(struct dnode *); |
static int list_single(const struct dnode *); |
136 |
|
|
|
static unsigned all_fmt; |
|
137 |
|
|
138 |
|
struct globals { |
139 |
|
#if ENABLE_FEATURE_LS_COLOR |
140 |
|
smallint show_color; |
141 |
|
#endif |
142 |
|
smallint exit_code; |
143 |
|
unsigned all_fmt; |
144 |
#if ENABLE_FEATURE_AUTOWIDTH |
#if ENABLE_FEATURE_AUTOWIDTH |
145 |
static unsigned tabstops = COLUMN_GAP; |
unsigned tabstops; // = COLUMN_GAP; |
146 |
static unsigned terminal_width = TERMINAL_WIDTH; |
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 |
157 |
|
enum { show_color = 0 }; |
158 |
|
#endif |
159 |
|
#define exit_code (G.exit_code ) |
160 |
|
#define all_fmt (G.all_fmt ) |
161 |
|
#if ENABLE_FEATURE_AUTOWIDTH |
162 |
|
#define tabstops (G.tabstops ) |
163 |
|
#define terminal_width (G.terminal_width) |
164 |
#else |
#else |
165 |
enum { |
enum { |
166 |
tabstops = COLUMN_GAP, |
tabstops = COLUMN_GAP, |
167 |
terminal_width = TERMINAL_WIDTH, |
terminal_width = TERMINAL_WIDTH, |
168 |
}; |
}; |
169 |
#endif |
#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() do { \ |
173 |
|
memset(&G, 0, sizeof(G)); \ |
174 |
|
USE_FEATURE_AUTOWIDTH(tabstops = COLUMN_GAP;) \ |
175 |
|
USE_FEATURE_AUTOWIDTH(terminal_width = TERMINAL_WIDTH;) \ |
176 |
|
USE_FEATURE_LS_TIMESTAMPS(time(¤t_time_t);) \ |
177 |
|
} while (0) |
178 |
|
|
179 |
|
|
180 |
|
#if ENABLE_FEATURE_ASSUME_UNICODE |
181 |
|
/* libbb candidate */ |
182 |
|
static 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 |
193 |
|
|
|
static int status = EXIT_SUCCESS; |
|
194 |
|
|
195 |
static struct dnode *my_stat(char *fullname, char *name) |
static struct dnode *my_stat(const char *fullname, const char *name, int force_follow) |
196 |
{ |
{ |
197 |
struct stat dstat; |
struct stat dstat; |
198 |
struct dnode *cur; |
struct dnode *cur; |
199 |
USE_SELINUX(security_context_t sid = NULL;) |
USE_SELINUX(security_context_t sid = NULL;) |
200 |
|
|
201 |
if (all_fmt & FOLLOW_LINKS) { |
if ((all_fmt & FOLLOW_LINKS) || force_follow) { |
202 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
203 |
if (is_selinux_enabled()) { |
if (is_selinux_enabled()) { |
204 |
getfilecon(fullname, &sid); |
getfilecon(fullname, &sid); |
205 |
} |
} |
206 |
#endif |
#endif |
207 |
if (stat(fullname, &dstat)) { |
if (stat(fullname, &dstat)) { |
208 |
bb_perror_msg("%s", fullname); |
bb_simple_perror_msg(fullname); |
209 |
status = EXIT_FAILURE; |
exit_code = EXIT_FAILURE; |
210 |
return 0; |
return 0; |
211 |
} |
} |
212 |
} else { |
} else { |
213 |
#if ENABLE_SELINUX |
#if ENABLE_SELINUX |
214 |
if (is_selinux_enabled()) { |
if (is_selinux_enabled()) { |
215 |
lgetfilecon(fullname,&sid); |
lgetfilecon(fullname, &sid); |
216 |
} |
} |
217 |
#endif |
#endif |
218 |
if (lstat(fullname, &dstat)) { |
if (lstat(fullname, &dstat)) { |
219 |
bb_perror_msg("%s", fullname); |
bb_simple_perror_msg(fullname); |
220 |
status = EXIT_FAILURE; |
exit_code = EXIT_FAILURE; |
221 |
return 0; |
return 0; |
222 |
} |
} |
223 |
} |
} |
274 |
return 0; |
return 0; |
275 |
dirs = 0; |
dirs = 0; |
276 |
for (i = 0; i < nfiles; i++) { |
for (i = 0; i < nfiles; i++) { |
277 |
char *name; |
const char *name; |
278 |
if (!S_ISDIR(dn[i]->dstat.st_mode)) |
if (!S_ISDIR(dn[i]->dstat.st_mode)) |
279 |
continue; |
continue; |
280 |
name = dn[i]->name; |
name = dn[i]->name; |
321 |
for (i = 0; i < nfiles; i++) { |
for (i = 0; i < nfiles; i++) { |
322 |
struct dnode *cur = dnp[i]; |
struct dnode *cur = dnp[i]; |
323 |
if (cur->allocated) |
if (cur->allocated) |
324 |
free(cur->fullname); /* free the filename */ |
free((char*)cur->fullname); /* free the filename */ |
325 |
free(cur); /* free the dnode */ |
free(cur); /* free the dnode */ |
326 |
} |
} |
327 |
free(dnp); /* free the array holding the dnode pointers */ |
free(dnp); /* free the array holding the dnode pointers */ |
353 |
/* copy the entrys into the file or dir array */ |
/* copy the entrys into the file or dir array */ |
354 |
for (d = i = 0; i < nfiles; i++) { |
for (d = i = 0; i < nfiles; i++) { |
355 |
if (S_ISDIR(dn[i]->dstat.st_mode)) { |
if (S_ISDIR(dn[i]->dstat.st_mode)) { |
356 |
char *name; |
const char *name; |
357 |
if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) |
if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) |
358 |
continue; |
continue; |
359 |
name = dn[i]->name; |
name = dn[i]->name; |
430 |
} else { |
} else { |
431 |
/* find the longest file name, use that as the column width */ |
/* find the longest file name, use that as the column width */ |
432 |
for (i = 0; i < nfiles; i++) { |
for (i = 0; i < nfiles; i++) { |
433 |
int len = strlen(dn[i]->name); |
int len = mbstrlen(dn[i]->name); |
434 |
if (column_width < len) |
if (column_width < len) |
435 |
column_width = len; |
column_width = len; |
436 |
} |
} |
485 |
for (i = 0; i < ndirs; i++) { |
for (i = 0; i < ndirs; i++) { |
486 |
if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { |
if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { |
487 |
if (!first) |
if (!first) |
488 |
puts(""); |
bb_putchar('\n'); |
489 |
first = 0; |
first = 0; |
490 |
printf("%s:\n", dn[i]->fullname); |
printf("%s:\n", dn[i]->fullname); |
491 |
} |
} |
529 |
nfiles = 0; |
nfiles = 0; |
530 |
dir = warn_opendir(path); |
dir = warn_opendir(path); |
531 |
if (dir == NULL) { |
if (dir == NULL) { |
532 |
status = EXIT_FAILURE; |
exit_code = EXIT_FAILURE; |
533 |
return NULL; /* could not open the dir */ |
return NULL; /* could not open the dir */ |
534 |
} |
} |
535 |
while ((entry = readdir(dir)) != NULL) { |
while ((entry = readdir(dir)) != NULL) { |
537 |
|
|
538 |
/* are we going to list the file- it may be . or .. or a hidden file */ |
/* are we going to list the file- it may be . or .. or a hidden file */ |
539 |
if (entry->d_name[0] == '.') { |
if (entry->d_name[0] == '.') { |
540 |
if ((entry->d_name[1] == 0 || ( |
if ((!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2])) |
541 |
entry->d_name[1] == '.' |
&& !(all_fmt & DISP_DOT) |
542 |
&& entry->d_name[2] == 0)) |
) { |
|
&& !(all_fmt & DISP_DOT)) |
|
543 |
continue; |
continue; |
544 |
|
} |
545 |
if (!(all_fmt & DISP_HIDDEN)) |
if (!(all_fmt & DISP_HIDDEN)) |
546 |
continue; |
continue; |
547 |
} |
} |
548 |
fullname = concat_path_file(path, entry->d_name); |
fullname = concat_path_file(path, entry->d_name); |
549 |
cur = my_stat(fullname, strrchr(fullname, '/') + 1); |
cur = my_stat(fullname, bb_basename(fullname), 0); |
550 |
if (!cur) { |
if (!cur) { |
551 |
free(fullname); |
free(fullname); |
552 |
continue; |
continue; |
573 |
} |
} |
574 |
|
|
575 |
|
|
576 |
#if ENABLE_FEATURE_LS_TIMESTAMPS |
static int list_single(const struct dnode *dn) |
|
/* Do time() just once. Saves one syscall per file for "ls -l" */ |
|
|
/* Initialized in main() */ |
|
|
static time_t current_time_t; |
|
|
#endif |
|
|
|
|
|
static int list_single(struct dnode *dn) |
|
577 |
{ |
{ |
578 |
int i, column = 0; |
int i, column = 0; |
579 |
|
|
687 |
fgcolor(info.st_mode)); |
fgcolor(info.st_mode)); |
688 |
} |
} |
689 |
#endif |
#endif |
690 |
|
#if ENABLE_FEATURE_ASSUME_UNICODE |
691 |
|
printf("%s", dn->name); |
692 |
|
column += mbstrlen(dn->name); |
693 |
|
#else |
694 |
column += printf("%s", dn->name); |
column += printf("%s", dn->name); |
695 |
|
#endif |
696 |
if (show_color) { |
if (show_color) { |
697 |
printf("\033[0m"); |
printf("\033[0m"); |
698 |
} |
} |
699 |
break; |
break; |
700 |
case LIST_SYMLINK: |
case LIST_SYMLINK: |
701 |
if (S_ISLNK(dn->dstat.st_mode)) { |
if (S_ISLNK(dn->dstat.st_mode)) { |
702 |
char *lpath = xreadlink(dn->fullname); |
char *lpath = xmalloc_readlink_or_warn(dn->fullname); |
703 |
if (!lpath) break; |
if (!lpath) break; |
704 |
printf(" -> "); |
printf(" -> "); |
705 |
#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR |
#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR |
735 |
return column; |
return column; |
736 |
} |
} |
737 |
|
|
738 |
|
|
739 |
/* "[-]Cadil1", POSIX mandated options, busybox always supports */ |
/* "[-]Cadil1", POSIX mandated options, busybox always supports */ |
740 |
/* "[-]gnsx", POSIX non-mandated options, busybox always supports */ |
/* "[-]gnsx", POSIX non-mandated options, busybox always supports */ |
741 |
/* "[-]Ak" GNU options, busybox always supports */ |
/* "[-]Ak" GNU options, busybox always supports */ |
744 |
/* "[-]SXvThw", GNU options, busybox optionally supports */ |
/* "[-]SXvThw", GNU options, busybox optionally supports */ |
745 |
/* "[-]K", SELinux mandated options, busybox optionally supports */ |
/* "[-]K", SELinux mandated options, busybox optionally supports */ |
746 |
/* "[-]e", I think we made this one up */ |
/* "[-]e", I think we made this one up */ |
747 |
static const char ls_options[] = "Cadil1gnsxAk" |
static const char ls_options[] ALIGN1 = |
748 |
|
"Cadil1gnsxAk" |
749 |
USE_FEATURE_LS_TIMESTAMPS("cetu") |
USE_FEATURE_LS_TIMESTAMPS("cetu") |
750 |
USE_FEATURE_LS_SORTFILES("SXrv") |
USE_FEATURE_LS_SORTFILES("SXrv") |
751 |
USE_FEATURE_LS_FILETYPES("Fp") |
USE_FEATURE_LS_FILETYPES("Fp") |
753 |
USE_FEATURE_LS_RECURSIVE("R") |
USE_FEATURE_LS_RECURSIVE("R") |
754 |
USE_FEATURE_HUMAN_READABLE("h") |
USE_FEATURE_HUMAN_READABLE("h") |
755 |
USE_SELINUX("K") |
USE_SELINUX("K") |
756 |
USE_FEATURE_AUTOWIDTH("T:w:"); |
USE_FEATURE_AUTOWIDTH("T:w:") |
757 |
|
USE_SELINUX("Z"); |
758 |
|
|
759 |
enum { |
enum { |
760 |
LIST_MASK_TRIGGER = 0, |
LIST_MASK_TRIGGER = 0, |
807 |
#if ENABLE_FEATURE_AUTOWIDTH |
#if ENABLE_FEATURE_AUTOWIDTH |
808 |
0, 0, /* T, w - ignored */ |
0, 0, /* T, w - ignored */ |
809 |
#endif |
#endif |
810 |
|
#if ENABLE_SELINUX |
811 |
|
LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */ |
812 |
|
#endif |
813 |
(1U<<31) |
(1U<<31) |
814 |
}; |
}; |
815 |
|
|
816 |
|
|
817 |
int ls_main(int argc, char **argv) |
/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */ |
818 |
|
#if ENABLE_FEATURE_LS_COLOR |
819 |
|
/* long option entry used only for --color, which has no short option |
820 |
|
* equivalent */ |
821 |
|
static const char ls_color_opt[] ALIGN1 = |
822 |
|
"color\0" Optional_argument "\xff" /* no short equivalent */ |
823 |
|
; |
824 |
|
#endif |
825 |
|
|
826 |
|
|
827 |
|
int ls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
828 |
|
int ls_main(int argc UNUSED_PARAM, char **argv) |
829 |
{ |
{ |
830 |
struct dnode **dnd; |
struct dnode **dnd; |
831 |
struct dnode **dnf; |
struct dnode **dnf; |
833 |
struct dnode *dn; |
struct dnode *dn; |
834 |
struct dnode *cur; |
struct dnode *cur; |
835 |
unsigned opt; |
unsigned opt; |
836 |
int nfiles = 0; |
int nfiles; |
837 |
int dnfiles; |
int dnfiles; |
838 |
int dndirs; |
int dndirs; |
|
int oi; |
|
|
int ac; |
|
839 |
int i; |
int i; |
840 |
char **av; |
/* need to initialize since --color has _an optional_ argument */ |
841 |
USE_FEATURE_AUTOWIDTH(char *tabstops_str = NULL;) |
USE_FEATURE_LS_COLOR(const char *color_opt = "always";) |
|
USE_FEATURE_AUTOWIDTH(char *terminal_width_str = NULL;) |
|
|
USE_FEATURE_LS_COLOR(char *color_opt;) |
|
842 |
|
|
843 |
setvbuf(stdout, bb_common_bufsiz1, _IOFBF, BUFSIZ); |
INIT_G(); |
|
|
|
|
#if ENABLE_FEATURE_LS_TIMESTAMPS |
|
|
time(¤t_time_t); |
|
|
#endif |
|
844 |
|
|
845 |
all_fmt = LIST_SHORT | |
all_fmt = LIST_SHORT | |
846 |
(ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD)); |
(ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD)); |
847 |
|
|
848 |
#if ENABLE_FEATURE_AUTOWIDTH |
#if ENABLE_FEATURE_AUTOWIDTH |
849 |
/* Obtain the terminal width */ |
/* Obtain the terminal width */ |
850 |
get_terminal_width_height(STDOUT_FILENO, &terminal_width, NULL); |
get_terminal_width_height(STDIN_FILENO, &terminal_width, NULL); |
851 |
/* Go one less... */ |
/* Go one less... */ |
852 |
terminal_width--; |
terminal_width--; |
853 |
#endif |
#endif |
855 |
/* process options */ |
/* process options */ |
856 |
USE_FEATURE_LS_COLOR(applet_long_options = ls_color_opt;) |
USE_FEATURE_LS_COLOR(applet_long_options = ls_color_opt;) |
857 |
#if ENABLE_FEATURE_AUTOWIDTH |
#if ENABLE_FEATURE_AUTOWIDTH |
858 |
opt = getopt32(argc, argv, ls_options, &tabstops_str, &terminal_width_str |
opt_complementary = "T+:w+"; /* -T N, -w N */ |
859 |
|
opt = getopt32(argv, ls_options, &tabstops, &terminal_width |
860 |
USE_FEATURE_LS_COLOR(, &color_opt)); |
USE_FEATURE_LS_COLOR(, &color_opt)); |
|
if (tabstops_str) |
|
|
tabstops = xatou(tabstops_str); |
|
|
if (terminal_width_str) |
|
|
terminal_width = xatou(terminal_width_str); |
|
861 |
#else |
#else |
862 |
opt = getopt32(argc, argv, ls_options USE_FEATURE_LS_COLOR(, &color_opt)); |
opt = getopt32(argv, ls_options USE_FEATURE_LS_COLOR(, &color_opt)); |
863 |
#endif |
#endif |
864 |
for (i = 0; opt_flags[i] != (1U<<31); i++) { |
for (i = 0; opt_flags[i] != (1U<<31); i++) { |
865 |
if (opt & (1 << i)) { |
if (opt & (1 << i)) { |
877 |
all_fmt &= ~TIME_MASK; |
all_fmt &= ~TIME_MASK; |
878 |
if (flags & LIST_CONTEXT) |
if (flags & LIST_CONTEXT) |
879 |
all_fmt |= STYLE_SINGLE; |
all_fmt |= STYLE_SINGLE; |
880 |
if (LS_DISP_HR && opt == 'l') |
/* huh?? opt cannot be 'l' */ |
881 |
all_fmt &= ~LS_DISP_HR; |
//if (LS_DISP_HR && opt == 'l') |
882 |
|
// all_fmt &= ~LS_DISP_HR; |
883 |
all_fmt |= flags; |
all_fmt |= flags; |
884 |
} |
} |
885 |
} |
} |
889 |
if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) { |
if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) { |
890 |
char *p = getenv("LS_COLORS"); |
char *p = getenv("LS_COLORS"); |
891 |
/* LS_COLORS is unset, or (not empty && not "none") ? */ |
/* LS_COLORS is unset, or (not empty && not "none") ? */ |
892 |
if (!p || (p[0] && strcmp(p, "none"))) |
if (!p || (p[0] && strcmp(p, "none") != 0)) |
893 |
show_color = 1; |
show_color = 1; |
894 |
} |
} |
895 |
if (opt & (1 << i)) { /* next flag after short options */ |
if (opt & (1 << i)) { /* next flag after short options */ |
896 |
if (!color_opt || !strcmp("always", color_opt)) |
if (strcmp("always", color_opt) == 0) |
897 |
show_color = 1; |
show_color = 1; |
898 |
else if (color_opt && !strcmp("never", color_opt)) |
else if (strcmp("never", color_opt) == 0) |
899 |
show_color = 0; |
show_color = 0; |
900 |
else if (color_opt && !strcmp("auto", color_opt) && isatty(STDOUT_FILENO)) |
else if (strcmp("auto", color_opt) == 0 && isatty(STDOUT_FILENO)) |
901 |
show_color = 1; |
show_color = 1; |
902 |
} |
} |
903 |
#endif |
#endif |
921 |
if (!(all_fmt & STYLE_MASK)) |
if (!(all_fmt & STYLE_MASK)) |
922 |
all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); |
all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); |
923 |
|
|
924 |
/* |
argv += optind; |
925 |
* when there are no cmd line args we have to supply a default "." arg. |
if (!argv[0]) |
926 |
* we will create a second argv array, "av" that will hold either |
*--argv = (char*)"."; |
|
* our created "." arg, or the real cmd line args. The av array |
|
|
* just holds the pointers- we don't move the date the pointers |
|
|
* point to. |
|
|
*/ |
|
|
ac = argc - optind; /* how many cmd line args are left */ |
|
|
if (ac < 1) { |
|
|
static const char *const dotdir[] = { "." }; |
|
|
|
|
|
av = (char **) dotdir; |
|
|
ac = 1; |
|
|
} else { |
|
|
av = argv + optind; |
|
|
} |
|
927 |
|
|
928 |
/* now, everything is in the av array */ |
if (argv[1]) |
929 |
if (ac > 1) |
all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ |
|
all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ |
|
930 |
|
|
931 |
/* stuff the command line file names into a dnode array */ |
/* stuff the command line file names into a dnode array */ |
932 |
dn = NULL; |
dn = NULL; |
933 |
for (oi = 0; oi < ac; oi++) { |
nfiles = 0; |
934 |
cur = my_stat(av[oi], av[oi]); |
do { |
935 |
|
/* ls w/o -l follows links on command line */ |
936 |
|
cur = my_stat(*argv, *argv, !(all_fmt & STYLE_LONG)); |
937 |
|
argv++; |
938 |
if (!cur) |
if (!cur) |
939 |
continue; |
continue; |
940 |
cur->allocated = 0; |
cur->allocated = 0; |
941 |
cur->next = dn; |
cur->next = dn; |
942 |
dn = cur; |
dn = cur; |
943 |
nfiles++; |
nfiles++; |
944 |
} |
} while (*argv); |
945 |
|
|
946 |
/* now that we know how many files there are |
/* now that we know how many files there are |
947 |
* allocate memory for an array to hold dnode pointers |
* allocate memory for an array to hold dnode pointers |
976 |
} |
} |
977 |
if (ENABLE_FEATURE_CLEAN_UP) |
if (ENABLE_FEATURE_CLEAN_UP) |
978 |
dfree(dnp, nfiles); |
dfree(dnp, nfiles); |
979 |
return status; |
return exit_code; |
980 |
} |
} |