comparison toys/ls.c @ 459:1dbe91079950

Second drop of ls from Andre, adds -l.
author Rob Landley <rob@landley.net>
date Mon, 13 Feb 2012 21:27:50 -0600
parents 9786a697d5aa
children d10b58563cff
comparison
equal deleted inserted replaced
458:9786a697d5aa 459:1dbe91079950
2 * 2 *
3 * ls.c - list files 3 * ls.c - list files
4 * 4 *
5 * Copyright 2012 Andre Renaud <andre@bluewatersys.com> 5 * Copyright 2012 Andre Renaud <andre@bluewatersys.com>
6 * 6 *
7 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.htm 7 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
8 8
9 USE_LS(NEWTOY(ls, "F1a", TOYFLAG_USR|TOYFLAG_BIN)) 9 USE_LS(NEWTOY(ls, "lF1a", TOYFLAG_BIN))
10 10
11 config LS 11 config LS
12 bool "ls" 12 bool "ls"
13 default y 13 default y
14 help 14 help
15 usage: ls [-F] [-a] [-1] [directory...] 15 usage: ls [-l] [-F] [-a] [-1] [directory...]
16 list files 16 list files
17 17
18 -F append a character as a file type indicator 18 -F append a character as a file type indicator
19 -a list all files 19 -a list all files
20 -1 list one file per line 20 -1 list one file per line
21 -l show full details for each file
21 */ 22 */
22 23
23 #include "toys.h" 24 #include "toys.h"
24 25
25 #define FLAG_a 1 26 #define FLAG_a 1
26 #define FLAG_1 2 27 #define FLAG_1 2
27 #define FLAG_F 4 28 #define FLAG_F 4
29 #define FLAG_l 8
28 30
29 static int dir_filter(const struct dirent *d) 31 static int dir_filter(const struct dirent *d)
30 { 32 {
31 /* Skip over the . & .. entries unless -a is given */ 33 /* Skip over the . & .. entries unless -a is given */
32 if (!(toys.optflags & FLAG_a)) 34 if (!(toys.optflags & FLAG_a))
39 { 41 {
40 struct dirent **entries; 42 struct dirent **entries;
41 int nentries; 43 int nentries;
42 int i; 44 int i;
43 int maxwidth = -1; 45 int maxwidth = -1;
44 int ncolumns; 46 int ncolumns = 1;
45 47
46 if (strcmp(name, "-") == 0) 48 if (!name || strcmp(name, "-") == 0)
47 name = "."; 49 name = ".";
48 50
51 /* Get all the files in this directory */
49 nentries = scandir(name, &entries, dir_filter, alphasort); 52 nentries = scandir(name, &entries, dir_filter, alphasort);
50 if (nentries < 0) 53 if (nentries < 0)
51 perror_exit("ls: cannot access %s'", name); 54 perror_exit("ls: cannot access %s'", name);
52 55
53 56
69 if (toys.optflags & FLAG_F) 72 if (toys.optflags & FLAG_F)
70 maxwidth++; 73 maxwidth++;
71 74
72 columns_str = getenv("COLUMNS"); 75 columns_str = getenv("COLUMNS");
73 columns = columns_str ? atoi(columns_str) : 80; 76 columns = columns_str ? atoi(columns_str) : 80;
74 ncolumns = columns / maxwidth; 77 ncolumns = maxwidth ? columns / maxwidth : 1;
75 } 78 }
76 79
77 for (i = 0; i < nentries; i++) { 80 for (i = 0; i < nentries; i++) {
78 struct dirent *ent = entries[i]; 81 struct dirent *ent = entries[i];
79 int len = strlen(ent->d_name); 82 int len = strlen(ent->d_name);
83 struct stat st;
84 int stat_valid = 0;
80 85
81 printf("%s", ent->d_name); 86 /* Provide the ls -l long output */
87 if (toys.optflags & FLAG_l) {
88 char type;
89 char timestamp[64];
90 struct tm mtime;
91
92 if (lstat(ent->d_name, &st))
93 perror_exit("Can't stat %s", ent->d_name);
94 stat_valid = 1;
95 if (S_ISDIR(st.st_mode))
96 type = 'd';
97 else if (S_ISCHR(st.st_mode))
98 type = 'c';
99 else if (S_ISBLK(st.st_mode))
100 type = 'b';
101 else if (S_ISLNK(st.st_mode))
102 type = 'l';
103 else
104 type = '-';
105
106 xprintf("%c%c%c%c%c%c%c%c%c%c ", type,
107 (st.st_mode & S_IRUSR) ? 'r' : '-',
108 (st.st_mode & S_IWUSR) ? 'w' : '-',
109 (st.st_mode & S_IXUSR) ? 'x' : '-',
110 (st.st_mode & S_IRGRP) ? 'r' : '-',
111 (st.st_mode & S_IWGRP) ? 'w' : '-',
112 (st.st_mode & S_IXGRP) ? 'x' : '-',
113 (st.st_mode & S_IROTH) ? 'r' : '-',
114 (st.st_mode & S_IWOTH) ? 'w' : '-',
115 (st.st_mode & S_IXOTH) ? 'x' : '-');
116
117 xprintf("%2d ", st.st_nlink);
118 /* FIXME: We're never looking up uid/gid numbers */
119 xprintf("%4d ", st.st_uid);
120 xprintf("%4d ", st.st_gid);
121 if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))
122 xprintf("%3d, %3d ", major(st.st_rdev), minor(st.st_rdev));
123 else
124 xprintf("%8ld ", st.st_size);
125
126 localtime_r(&st.st_mtime, &mtime);
127
128 strftime(timestamp, sizeof(timestamp), "%b %e %H:%M", &mtime);
129 xprintf("%s ", timestamp);
130 }
131
132 xprintf("%s", ent->d_name);
133
134 /* Append the file-type indicator character */
82 if (toys.optflags & FLAG_F) { 135 if (toys.optflags & FLAG_F) {
83 struct stat st; 136 if (!stat_valid) {
84 if (stat(ent->d_name, &st)) 137 if (lstat(ent->d_name, &st))
85 perror_exit("Can't stat %s", ent->d_name); 138 perror_exit("Can't stat %s", ent->d_name);
139 stat_valid = 1;
140 }
86 if (S_ISDIR(st.st_mode)) { 141 if (S_ISDIR(st.st_mode)) {
87 printf("/"); 142 xprintf("/");
88 len++; 143 len++;
89 } 144 } else if (S_ISREG(st.st_mode) &&
90 if (S_ISREG(st.st_mode) &&
91 (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { 145 (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
92 printf("*"); 146 xprintf("*");
147 len++;
148 } else if (S_ISLNK(st.st_mode)) {
149 xprintf("@");
93 len++; 150 len++;
94 } 151 }
95 } 152 }
96 if (toys.optflags & FLAG_1) 153 if (toys.optflags & FLAG_1) {
97 printf("\n"); 154 xprintf("\n");
98 else { 155 } else {
99 if (i % ncolumns == ncolumns - 1) 156 if (i % ncolumns == ncolumns - 1)
100 printf("\n"); 157 xprintf("\n");
101 else 158 else
102 printf("%*s", maxwidth - len, ""); 159 xprintf("%*s", maxwidth - len, "");
103 } 160 }
104 } 161 }
105 /* Make sure we put at a trailing new line in */ 162 /* Make sure we put at a trailing new line in */
106 if (!(toys.optflags & FLAG_1) && (i % ncolumns)) 163 if (!(toys.optflags & FLAG_1) && (i % ncolumns))
107 printf("\n"); 164 xprintf("\n");
108 } 165 }
109 166
110 void ls_main(void) 167 void ls_main(void)
111 { 168 {
169 /* Long output must be one-file per line */
170 if (toys.optflags & FLAG_l)
171 toys.optflags |= FLAG_1;
112 loopfiles(toys.optargs, do_ls); 172 loopfiles(toys.optargs, do_ls);
113 } 173 }