Mercurial > hg > toybox
comparison toys/ls.c @ 571:1a06fcaa1775
Make -d work in ls.
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 24 Apr 2012 20:44:09 -0500 |
parents | 83702597fd31 |
children | c42ed3601b35 |
comparison
equal
deleted
inserted
replaced
570:83702597fd31 | 571:1a06fcaa1775 |
---|---|
134 | 134 |
135 static int filter(struct dirtree *new) | 135 static int filter(struct dirtree *new) |
136 { | 136 { |
137 int flags = toys.optflags; | 137 int flags = toys.optflags; |
138 | 138 |
139 // TODO should -1f print here to handle enormous dirs without runing | 139 // TODO should -1f print here to handle enormous dirs without runing |
140 // out of mem? | 140 // out of mem? |
141 | 141 |
142 if (flags & FLAG_a) return DIRTREE_NORECURSE; | 142 if (flags & FLAG_a) return DIRTREE_NORECURSE; |
143 if (!(flags & FLAG_A) && new->name[0]=='.') | 143 if (!(flags & FLAG_A) && new->name[0]=='.') |
144 return DIRTREE_NOSAVE|DIRTREE_NORECURSE; | 144 return DIRTREE_NOSAVE|DIRTREE_NORECURSE; |
145 | 145 |
152 static void listfiles(struct dirtree *indir) | 152 static void listfiles(struct dirtree *indir) |
153 { | 153 { |
154 struct dirtree *dt, **sort = 0; | 154 struct dirtree *dt, **sort = 0; |
155 unsigned long dtlen = 0, ul = 0; | 155 unsigned long dtlen = 0, ul = 0; |
156 unsigned width, flags = toys.optflags, totals[6], len[6]; | 156 unsigned width, flags = toys.optflags, totals[6], len[6]; |
157 int showdirs = 1; | 157 |
158 | 158 // There are two "top of tree" variants: |
159 // Figure out if we should show directories and current directory name | 159 // ls arg1 arg2 arg3 |
160 if (indir == TT.files) | 160 // detect: !indir->parent |
161 showdirs = (flags & (FLAG_d|FLAG_R)) || indir->parent; | 161 // behavior: don't display dirs, never show dirname/total, option -H |
162 if (indir != TT.files || (indir->parent && (flags & FLAG_R))) { | 162 // ls onedir (or just "ls" which implies "." as first arg). |
163 // detect: indir == TT.files | |
164 // behavior: only show dirname/total with -R | |
165 | |
166 // Show current directory name if showing one directory with -d or | |
167 // not top of tree and -R | |
168 if (!(indir == TT.files || (flags & FLAG_d)) | |
169 || (indir->parent && (flags & FLAG_R))) | |
170 { | |
163 char *path = dirtree_path(indir, 0); | 171 char *path = dirtree_path(indir, 0); |
164 | 172 |
165 if (TT.again++) xputc('\n'); | 173 if (TT.again++) xputc('\n'); |
166 xprintf("%s:\n", path); | 174 xprintf("%s:\n", path); |
167 free(path); | 175 free(path); |
179 sort = xmalloc(dtlen * sizeof(void *)); | 187 sort = xmalloc(dtlen * sizeof(void *)); |
180 dtlen = 0; | 188 dtlen = 0; |
181 continue; | 189 continue; |
182 } | 190 } |
183 | 191 |
192 if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare); | |
193 | |
194 // Find largest entry in each field | |
195 | |
196 memset(totals, 0, 6*sizeof(unsigned)); | |
197 for (ul = 0; ul<dtlen; ul++) { | |
198 entrylen(sort[ul], len); | |
199 if (flags & FLAG_l) { | |
200 for (width=0; width<6; width++) | |
201 if (len[width] > totals[width]) totals[width] = len[width]; | |
202 //TODO } else if (flags & FLAG_C) { | |
203 } else if (*len > *totals) *totals = *len; | |
204 } | |
205 | |
184 // This is wrong, should be blocks used not file count. | 206 // This is wrong, should be blocks used not file count. |
185 if (indir->parent && (flags & FLAG_l)) xprintf("total %lu\n", dtlen); | 207 if (indir->parent && (flags & FLAG_l)) xprintf("total %lu\n", dtlen); |
186 | |
187 if (!(flags & FLAG_f)) qsort(sort, dtlen, sizeof(void *), (void *)compare); | |
188 | |
189 // Find largest entry in each field for everything but -1 | |
190 | |
191 memset(totals, 0, 6*sizeof(unsigned)); | |
192 if ((flags & (FLAG_1|FLAG_l)) != FLAG_1) { | |
193 for (ul = 0; ul<dtlen; ul++) { | |
194 entrylen(sort[ul], len); | |
195 if (flags & FLAG_l) { | |
196 for (width=0; width<6; width++) | |
197 if (len[width] > totals[width]) totals[width] = len[width]; | |
198 //TODO } else if (flags & FLAG_C) { | |
199 } else if (*len > *totals) *totals = *len; | |
200 } | |
201 } | |
202 | 208 |
203 // Loop through again to produce output. | 209 // Loop through again to produce output. |
204 width = 0; | 210 width = 0; |
205 memset(toybuf, ' ', 256); | 211 memset(toybuf, ' ', 256); |
206 for (ul = 0; ul<dtlen; ul++) { | 212 for (ul = 0; ul<dtlen; ul++) { |
207 struct stat *st = &(sort[ul]->st); | 213 struct stat *st = &(sort[ul]->st); |
208 mode_t mode = st->st_mode; | 214 mode_t mode = st->st_mode; |
209 char et = endtype(st); | 215 char et = endtype(st); |
210 | 216 |
211 if (S_ISDIR(mode) && !showdirs) continue; | 217 // Skip directories at the top of the tree when -d isn't set |
218 if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue; | |
219 | |
220 // Do we need to wrap at right edge of screen? | |
212 entrylen(sort[ul], len); | 221 entrylen(sort[ul], len); |
213 | |
214 if (ul) { | 222 if (ul) { |
215 if (toys.optflags & FLAG_m) xputc(','); | 223 if (toys.optflags & FLAG_m) xputc(','); |
216 if ((flags & FLAG_1) || width+1+*len > TT.width) { | 224 if ((flags & FLAG_1) || width+1+*len > TT.width) { |
217 xputc('\n'); | 225 xputc('\n'); |
218 width = 0; | 226 width = 0; |
267 if (et) xputc(et); | 275 if (et) xputc(et); |
268 } | 276 } |
269 | 277 |
270 if (width) xputc('\n'); | 278 if (width) xputc('\n'); |
271 | 279 |
280 // Free directory entries, recursing first if necessary. | |
281 | |
272 for (ul = 0; ul<dtlen; free(sort[ul++])) { | 282 for (ul = 0; ul<dtlen; free(sort[ul++])) { |
273 // TODO follow symlinks when? | 283 // TODO follow symlinks when? |
274 if (!S_ISDIR(sort[ul]->st.st_mode) || dirtree_isdotdot(sort[ul])) | 284 if ((flags & FLAG_d) || !S_ISDIR(sort[ul]->st.st_mode) |
275 continue; | 285 || dirtree_isdotdot(sort[ul])) continue; |
286 | |
287 // Recurse into dirs if at top of the tree or given -R | |
276 if (!indir->parent || (flags & FLAG_R)) { | 288 if (!indir->parent || (flags & FLAG_R)) { |
277 int fd = openat(indir->data, sort[ul]->name, 0); | 289 int fd = openat(indir->data, sort[ul]->name, 0); |
278 | 290 |
279 sort[ul]->data = dup(fd); | 291 sort[ul]->data = dup(fd); |
280 dirtree_recurse(sort[ul], filter); | 292 dirtree_recurse(sort[ul], filter); |
295 if (!isatty(1) || (toys.optflags&FLAG_l)) toys.optflags |= FLAG_1; | 307 if (!isatty(1) || (toys.optflags&FLAG_l)) toys.optflags |= FLAG_1; |
296 else { | 308 else { |
297 TT.width = 80; | 309 TT.width = 80; |
298 terminal_size(&TT.width, NULL); | 310 terminal_size(&TT.width, NULL); |
299 } | 311 } |
312 // The optflags parsing infrastructure should really do this for us, | |
313 // but currently it has "switch off when this is set", so "-dR" and "-Rd" | |
314 // behave differently | |
315 if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; | |
300 | 316 |
301 // Iterate through command line arguments, collecting directories and files. | 317 // Iterate through command line arguments, collecting directories and files. |
302 // Non-absolute paths are relative to current directory. | 318 // Non-absolute paths are relative to current directory. |
303 TT.files = dirtree_add_node(0, 0); | 319 TT.files = dirtree_add_node(0, 0); |
304 for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { | 320 for (s = *toys.optargs ? toys.optargs : noargs; *s; s++) { |