GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: ls.c,v 1.46 2016/03/28 11:25:35 chl Exp $ */ |
||
2 |
/* $NetBSD: ls.c,v 1.18 1996/07/09 09:16:29 mycroft Exp $ */ |
||
3 |
|||
4 |
/* |
||
5 |
* Copyright (c) 1989, 1993, 1994 |
||
6 |
* The Regents of the University of California. All rights reserved. |
||
7 |
* |
||
8 |
* This code is derived from software contributed to Berkeley by |
||
9 |
* Michael Fischbein. |
||
10 |
* |
||
11 |
* Redistribution and use in source and binary forms, with or without |
||
12 |
* modification, are permitted provided that the following conditions |
||
13 |
* are met: |
||
14 |
* 1. Redistributions of source code must retain the above copyright |
||
15 |
* notice, this list of conditions and the following disclaimer. |
||
16 |
* 2. Redistributions in binary form must reproduce the above copyright |
||
17 |
* notice, this list of conditions and the following disclaimer in the |
||
18 |
* documentation and/or other materials provided with the distribution. |
||
19 |
* 3. Neither the name of the University nor the names of its contributors |
||
20 |
* may be used to endorse or promote products derived from this software |
||
21 |
* without specific prior written permission. |
||
22 |
* |
||
23 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
||
24 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
25 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
26 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
||
27 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
||
28 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
||
29 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
||
30 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
||
31 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
||
32 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
||
33 |
* SUCH DAMAGE. |
||
34 |
*/ |
||
35 |
|||
36 |
#include <sys/types.h> |
||
37 |
#include <sys/stat.h> |
||
38 |
#include <sys/ioctl.h> |
||
39 |
|||
40 |
#include <dirent.h> |
||
41 |
#include <err.h> |
||
42 |
#include <errno.h> |
||
43 |
#include <fts.h> |
||
44 |
#include <grp.h> |
||
45 |
#include <pwd.h> |
||
46 |
#include <stdio.h> |
||
47 |
#include <stdlib.h> |
||
48 |
#include <string.h> |
||
49 |
#include <unistd.h> |
||
50 |
#include <limits.h> |
||
51 |
#include <locale.h> |
||
52 |
#include <util.h> |
||
53 |
|||
54 |
#include "ls.h" |
||
55 |
#include "extern.h" |
||
56 |
|||
57 |
static void display(FTSENT *, FTSENT *); |
||
58 |
static int mastercmp(const FTSENT **, const FTSENT **); |
||
59 |
static void traverse(int, char **, int); |
||
60 |
|||
61 |
static void (*printfcn)(DISPLAY *); |
||
62 |
static int (*sortfcn)(const FTSENT *, const FTSENT *); |
||
63 |
|||
64 |
#define BY_NAME 0 |
||
65 |
#define BY_SIZE 1 |
||
66 |
#define BY_TIME 2 |
||
67 |
|||
68 |
long blocksize; /* block size units */ |
||
69 |
int termwidth; /* default terminal width */ |
||
70 |
int sortkey = BY_NAME; |
||
71 |
|||
72 |
/* flags */ |
||
73 |
int f_accesstime; /* use time of last access */ |
||
74 |
int f_column; /* columnated format */ |
||
75 |
int f_columnacross; /* columnated format, sorted across */ |
||
76 |
int f_flags; /* show flags associated with a file */ |
||
77 |
int f_grouponly; /* long listing format without owner */ |
||
78 |
int f_humanval; /* show human-readable file sizes */ |
||
79 |
int f_inode; /* print inode */ |
||
80 |
int f_listdir; /* list actual directory, not contents */ |
||
81 |
int f_listdot; /* list files beginning with . */ |
||
82 |
int f_longform; /* long listing format */ |
||
83 |
int f_nonprint; /* show unprintables as ? */ |
||
84 |
int f_nosort; /* don't sort output */ |
||
85 |
int f_numericonly; /* don't expand uid to symbolic name */ |
||
86 |
int f_recursive; /* ls subdirectories also */ |
||
87 |
int f_reversesort; /* reverse whatever sort is used */ |
||
88 |
int f_sectime; /* print the real time for all files */ |
||
89 |
int f_singlecol; /* use single column output */ |
||
90 |
int f_size; /* list size in short listing */ |
||
91 |
int f_statustime; /* use time of last mode change */ |
||
92 |
int f_stream; /* stream format */ |
||
93 |
int f_type; /* add type character for non-regular files */ |
||
94 |
int f_typedir; /* add type character for directories */ |
||
95 |
|||
96 |
int rval; |
||
97 |
|||
98 |
int |
||
99 |
ls_main(int argc, char *argv[]) |
||
100 |
100 |
{ |
|
101 |
static char dot[] = ".", *dotav[] = { dot, NULL }; |
||
102 |
struct winsize win; |
||
103 |
int ch, fts_options, notused; |
||
104 |
100 |
int kflag = 0; |
|
105 |
char *p; |
||
106 |
|||
107 |
#ifndef SMALL |
||
108 |
100 |
setlocale(LC_CTYPE, ""); |
|
109 |
#endif |
||
110 |
|||
111 |
/* Terminal defaults to -Cq, non-terminal defaults to -1. */ |
||
112 |
✓✓ | 100 |
if (isatty(STDOUT_FILENO)) { |
113 |
7 |
f_column = f_nonprint = 1; |
|
114 |
} else { |
||
115 |
93 |
f_singlecol = 1; |
|
116 |
} |
||
117 |
|||
118 |
100 |
termwidth = 0; |
|
119 |
✗✓ | 100 |
if ((p = getenv("COLUMNS")) != NULL) |
120 |
termwidth = strtonum(p, 1, INT_MAX, NULL); |
||
121 |
✓✗✓✓ ✓✗ |
100 |
if (termwidth == 0 && ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && |
122 |
win.ws_col > 0) |
||
123 |
7 |
termwidth = win.ws_col; |
|
124 |
✓✓ | 100 |
if (termwidth == 0) |
125 |
93 |
termwidth = 80; |
|
126 |
|||
127 |
✗✓ | 100 |
if (pledge("stdio rpath getpw wpath cpath", NULL) == -1) |
128 |
err(1, "pledge"); |
||
129 |
|||
130 |
/* Root is -A automatically. */ |
||
131 |
✓✗ | 100 |
if (!getuid()) |
132 |
100 |
f_listdot = 1; |
|
133 |
|||
134 |
100 |
fts_options = FTS_PHYSICAL; |
|
135 |
✓✓ | 209 |
while ((ch = getopt(argc, argv, "1ACFHLRSTacdfghiklmnopqrstux")) != -1) { |
136 |
✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗ |
9 |
switch (ch) { |
137 |
/* |
||
138 |
* The -1, -C and -l, -m, -n and -x options all override each |
||
139 |
* other so shell aliasing works right. |
||
140 |
*/ |
||
141 |
case '1': |
||
142 |
1 |
f_singlecol = 1; |
|
143 |
1 |
f_column = f_columnacross = f_longform = 0; |
|
144 |
1 |
f_numericonly = f_stream = 0; |
|
145 |
1 |
break; |
|
146 |
case 'C': |
||
147 |
f_column = 1; |
||
148 |
f_columnacross = f_longform = f_numericonly = 0; |
||
149 |
f_singlecol = f_stream = 0; |
||
150 |
break; |
||
151 |
case 'g': |
||
152 |
f_longform = 1; |
||
153 |
if (f_grouponly != -1) |
||
154 |
f_grouponly = 1; |
||
155 |
f_column = f_columnacross = f_singlecol = f_stream = 0; |
||
156 |
break; |
||
157 |
case 'l': |
||
158 |
f_longform = 1; |
||
159 |
f_grouponly = -1; /* -l always overrides -g */ |
||
160 |
f_column = f_columnacross = f_singlecol = f_stream = 0; |
||
161 |
break; |
||
162 |
case 'm': |
||
163 |
f_stream = 1; |
||
164 |
f_column = f_columnacross = f_longform = 0; |
||
165 |
f_numericonly = f_singlecol = 0; |
||
166 |
break; |
||
167 |
case 'x': |
||
168 |
f_columnacross = 1; |
||
169 |
f_column = f_longform = f_numericonly = 0; |
||
170 |
f_singlecol = f_stream = 0; |
||
171 |
break; |
||
172 |
case 'n': |
||
173 |
f_longform = 1; |
||
174 |
f_numericonly = 1; |
||
175 |
f_column = f_columnacross = f_singlecol = f_stream = 0; |
||
176 |
break; |
||
177 |
/* The -c and -u options override each other. */ |
||
178 |
case 'c': |
||
179 |
f_statustime = 1; |
||
180 |
f_accesstime = 0; |
||
181 |
break; |
||
182 |
case 'u': |
||
183 |
f_accesstime = 1; |
||
184 |
f_statustime = 0; |
||
185 |
break; |
||
186 |
case 'F': |
||
187 |
f_type = 1; |
||
188 |
break; |
||
189 |
case 'H': |
||
190 |
fts_options |= FTS_COMFOLLOW; |
||
191 |
break; |
||
192 |
case 'L': |
||
193 |
fts_options &= ~FTS_PHYSICAL; |
||
194 |
fts_options |= FTS_LOGICAL; |
||
195 |
break; |
||
196 |
case 'R': |
||
197 |
f_recursive = 1; |
||
198 |
break; |
||
199 |
case 'f': |
||
200 |
f_nosort = 1; |
||
201 |
/* FALLTHROUGH */ |
||
202 |
case 'a': |
||
203 |
fts_options |= FTS_SEEDOT; |
||
204 |
/* FALLTHROUGH */ |
||
205 |
case 'A': |
||
206 |
f_listdot = 1; |
||
207 |
break; |
||
208 |
/* The -d option turns off the -R option. */ |
||
209 |
case 'd': |
||
210 |
4 |
f_listdir = 1; |
|
211 |
4 |
f_recursive = 0; |
|
212 |
4 |
break; |
|
213 |
case 'h': |
||
214 |
f_humanval = 1; |
||
215 |
break; |
||
216 |
case 'i': |
||
217 |
4 |
f_inode = 1; |
|
218 |
4 |
break; |
|
219 |
case 'k': |
||
220 |
blocksize = 1024; |
||
221 |
kflag = 1; |
||
222 |
break; |
||
223 |
case 'o': |
||
224 |
f_flags = 1; |
||
225 |
break; |
||
226 |
case 'p': |
||
227 |
f_typedir = 1; |
||
228 |
break; |
||
229 |
case 'q': |
||
230 |
f_nonprint = 1; |
||
231 |
break; |
||
232 |
case 'r': |
||
233 |
f_reversesort = 1; |
||
234 |
break; |
||
235 |
case 'S': |
||
236 |
sortkey = BY_SIZE; |
||
237 |
break; |
||
238 |
case 's': |
||
239 |
f_size = 1; |
||
240 |
break; |
||
241 |
case 'T': |
||
242 |
f_sectime = 1; |
||
243 |
break; |
||
244 |
case 't': |
||
245 |
sortkey = BY_TIME; |
||
246 |
break; |
||
247 |
default: |
||
248 |
usage(); |
||
249 |
} |
||
250 |
} |
||
251 |
100 |
argc -= optind; |
|
252 |
100 |
argv += optind; |
|
253 |
|||
254 |
/* |
||
255 |
* If both -g and -l options, let -l take precedence. |
||
256 |
* This preserves compatibility with the historic BSD ls -lg. |
||
257 |
*/ |
||
258 |
✗✓ | 100 |
if (f_grouponly == -1) |
259 |
f_grouponly = 0; |
||
260 |
|||
261 |
/* |
||
262 |
* If not -F, -i, -l, -p, -S, -s or -t options, don't require stat |
||
263 |
* information. |
||
264 |
*/ |
||
265 |
✓✗✓✓ ✓✗✓✗ ✓✗✓✗ |
100 |
if (!f_longform && !f_inode && !f_size && !f_type && !f_typedir && |
266 |
sortkey == BY_NAME) |
||
267 |
96 |
fts_options |= FTS_NOSTAT; |
|
268 |
|||
269 |
/* |
||
270 |
* If not -F, -d or -l options, follow any symbolic links listed on |
||
271 |
* the command line. |
||
272 |
*/ |
||
273 |
✓✗✓✓ ✓✗ |
100 |
if (!f_longform && !f_listdir && !f_type) |
274 |
96 |
fts_options |= FTS_COMFOLLOW; |
|
275 |
|||
276 |
/* If -l or -s, figure out block size. */ |
||
277 |
✓✗✗✓ |
100 |
if (f_longform || f_size) { |
278 |
if (!kflag) |
||
279 |
(void)getbsize(¬used, &blocksize); |
||
280 |
blocksize /= 512; |
||
281 |
} |
||
282 |
|||
283 |
/* Select a sort function. */ |
||
284 |
✗✓ | 100 |
if (f_reversesort) { |
285 |
switch (sortkey) { |
||
286 |
case BY_NAME: |
||
287 |
sortfcn = revnamecmp; |
||
288 |
break; |
||
289 |
case BY_SIZE: |
||
290 |
sortfcn = revsizecmp; |
||
291 |
break; |
||
292 |
case BY_TIME: |
||
293 |
if (f_accesstime) |
||
294 |
sortfcn = revacccmp; |
||
295 |
else if (f_statustime) |
||
296 |
sortfcn = revstatcmp; |
||
297 |
else /* Use modification time. */ |
||
298 |
sortfcn = revmodcmp; |
||
299 |
break; |
||
300 |
} |
||
301 |
} else { |
||
302 |
✓✗✗✗ |
100 |
switch (sortkey) { |
303 |
case BY_NAME: |
||
304 |
100 |
sortfcn = namecmp; |
|
305 |
100 |
break; |
|
306 |
case BY_SIZE: |
||
307 |
sortfcn = sizecmp; |
||
308 |
break; |
||
309 |
case BY_TIME: |
||
310 |
if (f_accesstime) |
||
311 |
sortfcn = acccmp; |
||
312 |
else if (f_statustime) |
||
313 |
sortfcn = statcmp; |
||
314 |
else /* Use modification time. */ |
||
315 |
sortfcn = modcmp; |
||
316 |
break; |
||
317 |
} |
||
318 |
} |
||
319 |
|||
320 |
/* Select a print function. */ |
||
321 |
✓✓ | 100 |
if (f_singlecol) |
322 |
94 |
printfcn = printscol; |
|
323 |
✗✓ | 6 |
else if (f_columnacross) |
324 |
printfcn = printacol; |
||
325 |
✗✓ | 6 |
else if (f_longform) |
326 |
printfcn = printlong; |
||
327 |
✗✓ | 6 |
else if (f_stream) |
328 |
printfcn = printstream; |
||
329 |
else |
||
330 |
6 |
printfcn = printcol; |
|
331 |
|||
332 |
✓✓ | 100 |
if (argc) |
333 |
5 |
traverse(argc, argv, fts_options); |
|
334 |
else |
||
335 |
95 |
traverse(1, dotav, fts_options); |
|
336 |
100 |
return (rval); |
|
337 |
} |
||
338 |
|||
339 |
static int output; /* If anything output. */ |
||
340 |
|||
341 |
/* |
||
342 |
* Traverse() walks the logical directory structure specified by the argv list |
||
343 |
* in the order specified by the mastercmp() comparison function. During the |
||
344 |
* traversal it passes linked lists of structures to display() which represent |
||
345 |
* a superset (may be exact set) of the files to be displayed. |
||
346 |
*/ |
||
347 |
static void |
||
348 |
traverse(int argc, char *argv[], int options) |
||
349 |
100 |
{ |
|
350 |
FTS *ftsp; |
||
351 |
FTSENT *p, *chp; |
||
352 |
int ch_options, saved_errno; |
||
353 |
|||
354 |
✓✗✗✓ |
100 |
if ((ftsp = |
355 |
fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) |
||
356 |
err(1, NULL); |
||
357 |
|||
358 |
100 |
display(NULL, fts_children(ftsp, 0)); |
|
359 |
✓✓ | 100 |
if (f_listdir) |
360 |
4 |
return; |
|
361 |
|||
362 |
/* |
||
363 |
* If not recursing down this tree and don't need stat info, just get |
||
364 |
* the names. |
||
365 |
*/ |
||
366 |
✓✗✓✗ |
96 |
ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; |
367 |
|||
368 |
✓✓ | 384 |
while ((p = fts_read(ftsp)) != NULL) |
369 |
✓✗✗✓ |
192 |
switch (p->fts_info) { |
370 |
case FTS_D: |
||
371 |
✓✓✗✓ ✗✗ |
96 |
if (p->fts_name[0] == '.' && |
372 |
p->fts_level != FTS_ROOTLEVEL && !f_listdot) |
||
373 |
break; |
||
374 |
|||
375 |
/* |
||
376 |
* If already output something, put out a newline as |
||
377 |
* a separator. If multiple arguments, precede each |
||
378 |
* directory with its name. |
||
379 |
*/ |
||
380 |
✗✓ | 96 |
if (output) |
381 |
(void)printf("\n%s:\n", p->fts_path); |
||
382 |
✗✓ | 96 |
else if (argc > 1) { |
383 |
(void)printf("%s:\n", p->fts_path); |
||
384 |
output = 1; |
||
385 |
} |
||
386 |
|||
387 |
96 |
chp = fts_children(ftsp, ch_options); |
|
388 |
96 |
saved_errno = errno; |
|
389 |
96 |
display(p, chp); |
|
390 |
|||
391 |
/* |
||
392 |
* On fts_children() returning error do recurse to see |
||
393 |
* the error. |
||
394 |
*/ |
||
395 |
✓✗✓✗ |
96 |
if (!f_recursive && !(chp == NULL && saved_errno != 0)) |
396 |
96 |
(void)fts_set(ftsp, p, FTS_SKIP); |
|
397 |
break; |
||
398 |
case FTS_DC: |
||
399 |
warnx("%s: directory causes a cycle", p->fts_name); |
||
400 |
break; |
||
401 |
case FTS_DNR: |
||
402 |
case FTS_ERR: |
||
403 |
warnx("%s: %s", p->fts_name[0] == '\0' ? p->fts_path : |
||
404 |
p->fts_name, strerror(p->fts_errno)); |
||
405 |
rval = 1; |
||
406 |
break; |
||
407 |
} |
||
408 |
✗✓ | 96 |
if (errno) |
409 |
err(1, "fts_read"); |
||
410 |
|||
411 |
96 |
fts_close(ftsp); |
|
412 |
} |
||
413 |
|||
414 |
/* |
||
415 |
* Display() takes a linked list of FTSENT structures and passes the list |
||
416 |
* along with any other necessary information to the print function. P |
||
417 |
* points to the parent directory of the display list. |
||
418 |
*/ |
||
419 |
static void |
||
420 |
display(FTSENT *p, FTSENT *list) |
||
421 |
196 |
{ |
|
422 |
struct stat *sp; |
||
423 |
DISPLAY d; |
||
424 |
FTSENT *cur; |
||
425 |
NAMES *np; |
||
426 |
off_t maxsize; |
||
427 |
u_long maxlen, maxnlink; |
||
428 |
unsigned long long btotal, maxblock; |
||
429 |
ino_t maxinode; |
||
430 |
int bcfile, flen, glen, ulen, maxflags, maxgroup, maxuser; |
||
431 |
int entries, needstats; |
||
432 |
int width; |
||
433 |
char *user, *group, buf[21]; /* 64 bits == 20 digits */ |
||
434 |
char nuser[12], ngroup[12]; |
||
435 |
196 |
char *flags = NULL; |
|
436 |
|||
437 |
/* |
||
438 |
* If list is NULL there are two possibilities: that the parent |
||
439 |
* directory p has no children, or that fts_children() returned an |
||
440 |
* error. We ignore the error case since it will be replicated |
||
441 |
* on the next call to fts_read() on the post-order visit to the |
||
442 |
* directory p, and will be signalled in traverse(). |
||
443 |
*/ |
||
444 |
✗✓ | 196 |
if (list == NULL) |
445 |
return; |
||
446 |
|||
447 |
✓✓✓✗ ✗✓ |
196 |
needstats = f_inode || f_longform || f_size; |
448 |
196 |
flen = 0; |
|
449 |
196 |
btotal = maxblock = maxinode = maxlen = maxnlink = 0; |
|
450 |
196 |
bcfile = 0; |
|
451 |
196 |
maxuser = maxgroup = maxflags = 0; |
|
452 |
196 |
maxsize = 0; |
|
453 |
✓✓ | 3094 |
for (cur = list, entries = 0; cur != NULL; cur = cur->fts_link) { |
454 |
✗✓ | 2898 |
if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { |
455 |
warnx("%s: %s", |
||
456 |
cur->fts_name, strerror(cur->fts_errno)); |
||
457 |
cur->fts_number = NO_PRINT; |
||
458 |
rval = 1; |
||
459 |
continue; |
||
460 |
} |
||
461 |
|||
462 |
/* |
||
463 |
* P is NULL if list is the argv list, to which different rules |
||
464 |
* apply. |
||
465 |
*/ |
||
466 |
✓✓ | 2898 |
if (p == NULL) { |
467 |
/* Directories will be displayed later. */ |
||
468 |
✓✗✓✓ |
100 |
if (cur->fts_info == FTS_D && !f_listdir) { |
469 |
96 |
cur->fts_number = NO_PRINT; |
|
470 |
96 |
continue; |
|
471 |
} |
||
472 |
} else { |
||
473 |
/* Only display dot file if -a/-A set. */ |
||
474 |
✓✓✗✓ |
2798 |
if (cur->fts_name[0] == '.' && !f_listdot) { |
475 |
cur->fts_number = NO_PRINT; |
||
476 |
continue; |
||
477 |
} |
||
478 |
} |
||
479 |
✓✓ | 2802 |
if ((width = mbsprint(cur->fts_name, 0)) > maxlen) |
480 |
387 |
maxlen = width; |
|
481 |
✓✓ | 2802 |
if (needstats) { |
482 |
4 |
sp = cur->fts_statp; |
|
483 |
✓✗ | 4 |
if (sp->st_blocks > maxblock) |
484 |
4 |
maxblock = sp->st_blocks; |
|
485 |
✓✗ | 4 |
if (sp->st_ino > maxinode) |
486 |
4 |
maxinode = sp->st_ino; |
|
487 |
✓✗ | 4 |
if (sp->st_nlink > maxnlink) |
488 |
4 |
maxnlink = sp->st_nlink; |
|
489 |
✓✗ | 4 |
if (sp->st_size > maxsize) |
490 |
4 |
maxsize = sp->st_size; |
|
491 |
|||
492 |
4 |
btotal += sp->st_blocks; |
|
493 |
✗✓ | 4 |
if (f_longform) { |
494 |
if (f_numericonly) { |
||
495 |
snprintf(nuser, 12, "%u", sp->st_uid); |
||
496 |
snprintf(ngroup, 12, "%u", sp->st_gid); |
||
497 |
user = nuser; |
||
498 |
group = ngroup; |
||
499 |
} else { |
||
500 |
user = user_from_uid(sp->st_uid, 0); |
||
501 |
group = group_from_gid(sp->st_gid, 0); |
||
502 |
} |
||
503 |
if ((ulen = strlen(user)) > maxuser) |
||
504 |
maxuser = ulen; |
||
505 |
if ((glen = strlen(group)) > maxgroup) |
||
506 |
maxgroup = glen; |
||
507 |
if (f_flags) { |
||
508 |
flags = fflagstostr(sp->st_flags); |
||
509 |
if (*flags == '\0') |
||
510 |
flags = "-"; |
||
511 |
if ((flen = strlen(flags)) > maxflags) |
||
512 |
maxflags = flen; |
||
513 |
} else |
||
514 |
flen = 0; |
||
515 |
|||
516 |
if ((np = malloc(sizeof(NAMES) + |
||
517 |
ulen + 1 + glen + 1 + flen + 1)) == NULL) |
||
518 |
err(1, NULL); |
||
519 |
|||
520 |
np->user = &np->data[0]; |
||
521 |
(void)strlcpy(np->user, user, ulen + 1); |
||
522 |
np->group = &np->data[ulen + 1]; |
||
523 |
(void)strlcpy(np->group, group, glen + 1); |
||
524 |
|||
525 |
if (S_ISCHR(sp->st_mode) || |
||
526 |
S_ISBLK(sp->st_mode)) |
||
527 |
bcfile = 1; |
||
528 |
|||
529 |
if (f_flags) { |
||
530 |
np->flags = &np->data[ulen + 1 + glen + 1]; |
||
531 |
(void)strlcpy(np->flags, flags, flen + 1); |
||
532 |
if (*flags != '-') |
||
533 |
free(flags); |
||
534 |
} |
||
535 |
cur->fts_pointer = np; |
||
536 |
} |
||
537 |
} |
||
538 |
2802 |
++entries; |
|
539 |
} |
||
540 |
|||
541 |
✓✓ | 196 |
if (!entries) |
542 |
96 |
return; |
|
543 |
|||
544 |
100 |
d.list = list; |
|
545 |
100 |
d.entries = entries; |
|
546 |
100 |
d.maxlen = maxlen; |
|
547 |
✓✓ | 100 |
if (needstats) { |
548 |
4 |
d.bcfile = bcfile; |
|
549 |
4 |
d.btotal = btotal; |
|
550 |
4 |
(void)snprintf(buf, sizeof(buf), "%llu", maxblock); |
|
551 |
4 |
d.s_block = strlen(buf); |
|
552 |
4 |
d.s_flags = maxflags; |
|
553 |
4 |
d.s_group = maxgroup; |
|
554 |
4 |
(void)snprintf(buf, sizeof(buf), "%llu", |
|
555 |
(unsigned long long)maxinode); |
||
556 |
4 |
d.s_inode = strlen(buf); |
|
557 |
4 |
(void)snprintf(buf, sizeof(buf), "%lu", maxnlink); |
|
558 |
4 |
d.s_nlink = strlen(buf); |
|
559 |
✓✗ | 4 |
if (!f_humanval) { |
560 |
4 |
(void)snprintf(buf, sizeof(buf), "%lld", |
|
561 |
(long long) maxsize); |
||
562 |
4 |
d.s_size = strlen(buf); |
|
563 |
} else |
||
564 |
d.s_size = FMT_SCALED_STRSIZE-2; /* no - or '\0' */ |
||
565 |
4 |
d.s_user = maxuser; |
|
566 |
} |
||
567 |
|||
568 |
100 |
printfcn(&d); |
|
569 |
100 |
output = 1; |
|
570 |
|||
571 |
✗✓ | 100 |
if (f_longform) |
572 |
for (cur = list; cur != NULL; cur = cur->fts_link) |
||
573 |
free(cur->fts_pointer); |
||
574 |
} |
||
575 |
|||
576 |
/* |
||
577 |
* Ordering for mastercmp: |
||
578 |
* If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories |
||
579 |
* as larger than directories. Within either group, use the sort function. |
||
580 |
* All other levels use the sort function. Error entries remain unsorted. |
||
581 |
*/ |
||
582 |
static int |
||
583 |
mastercmp(const FTSENT **a, const FTSENT **b) |
||
584 |
23702 |
{ |
|
585 |
int a_info, b_info; |
||
586 |
|||
587 |
23702 |
a_info = (*a)->fts_info; |
|
588 |
✗✓ | 23702 |
if (a_info == FTS_ERR) |
589 |
return (0); |
||
590 |
23702 |
b_info = (*b)->fts_info; |
|
591 |
✗✓ | 23702 |
if (b_info == FTS_ERR) |
592 |
return (0); |
||
593 |
|||
594 |
✗✓ | 23702 |
if (a_info == FTS_NS || b_info == FTS_NS) { |
595 |
if (b_info != FTS_NS) |
||
596 |
return (1); |
||
597 |
else if (a_info != FTS_NS) |
||
598 |
return (-1); |
||
599 |
else |
||
600 |
return (namecmp(*a, *b)); |
||
601 |
} |
||
602 |
|||
603 |
✗✓✗✗ ✗✗ |
23702 |
if (a_info != b_info && |
604 |
(*a)->fts_level == FTS_ROOTLEVEL && !f_listdir) { |
||
605 |
if (a_info == FTS_D) |
||
606 |
return (1); |
||
607 |
if (b_info == FTS_D) |
||
608 |
return (-1); |
||
609 |
} |
||
610 |
23702 |
return (sortfcn(*a, *b)); |
|
611 |
} |
Generated by: GCOVR (Version 3.3) |