]>
git.saurik.com Git - apple/file_cmds.git/blob - ls/print.c
4962a95dea06f89f3b50f9729983d12f022a881b
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 static char sccsid
[] = "@(#)print.c 8.4 (Berkeley) 4/17/94";
42 #include <sys/cdefs.h>
43 __RCSID("$FreeBSD: src/bin/ls/print.c,v 1.57 2002/08/29 14:29:09 keramida Exp $");
45 #include <sys/param.h>
67 static int printaname(FTSENT
*, u_long
, u_long
);
68 static void printlink(FTSENT
*);
69 static void printtime(time_t);
70 static int printtype(u_int
);
71 static void printsize(size_t, off_t
);
73 static void endcolor(int);
74 static int colortype(mode_t
);
77 #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
79 #define KILO_SZ(n) (n)
80 #define MEGA_SZ(n) ((n) * (n))
81 #define GIGA_SZ(n) ((n) * (n) * (n))
82 #define TERA_SZ(n) ((n) * (n) * (n) * (n))
83 #define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
85 #define KILO_2_SZ (KILO_SZ(1024ULL))
86 #define MEGA_2_SZ (MEGA_SZ(1024ULL))
87 #define GIGA_2_SZ (GIGA_SZ(1024ULL))
88 #define TERA_2_SZ (TERA_SZ(1024ULL))
89 #define PETA_2_SZ (PETA_SZ(1024ULL))
91 static u_int64_t vals_base2
[] = {1, KILO_2_SZ
, MEGA_2_SZ
, GIGA_2_SZ
, TERA_2_SZ
, PETA_2_SZ
};
94 NONE
, KILO
, MEGA
, GIGA
, TERA
, PETA
, UNIT_MAX
96 static unit_t
unit_adjust(off_t
*);
98 static int unitp
[] = {NONE
, KILO
, MEGA
, GIGA
, TERA
, PETA
};
101 /* Most of these are taken from <sys/stat.h> */
102 typedef enum Colors
{
103 C_DIR
, /* directory */
104 C_LNK
, /* symbolic link */
107 C_EXEC
, /* executable */
108 C_BLK
, /* block special */
109 C_CHR
, /* character special */
110 C_SUID
, /* setuid executable */
111 C_SGID
, /* setgid executable */
112 C_WSDIR
, /* directory writeble to others, with sticky
114 C_WDIR
, /* directory writeble to others, without
116 C_NUMCOLORS
/* just a place-holder */
119 static const char *defcolors
= "exfxcxdxbxegedabagacad";
121 /* colors for file types */
125 } colors
[C_NUMCOLORS
];
129 printscol(DISPLAY
*dp
)
133 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
136 (void)printaname(p
, dp
->s_inode
, dp
->s_block
);
142 * print name in current style
145 printname(const char *name
)
147 if (f_octal
|| f_octal_escape
)
148 return prn_octal(name
);
150 return prn_printable(name
);
152 return printf("%s", name
);
156 printlong(DISPLAY
*dp
)
163 int color_printed
= 0;
166 if (dp
->list
->fts_level
!= FTS_ROOTLEVEL
&& (f_longform
|| f_size
))
167 (void)printf("total %qu\n", (u_int64_t
)howmany(dp
->btotal
, blocksize
));
169 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
174 (void)printf("%*lu ", dp
->s_inode
, (u_long
)sp
->st_ino
);
176 (void)printf("%*qu ",
177 dp
->s_block
, (u_int64_t
)howmany(sp
->st_blocks
, blocksize
));
178 strmode(sp
->st_mode
, buf
);
180 (void)printf("%s %*u %-*s %-*s ", buf
, dp
->s_nlink
,
181 sp
->st_nlink
, dp
->s_user
, np
->user
, dp
->s_group
,
184 (void)printf("%-*s ", dp
->s_flags
, np
->flags
);
187 (void)printf("%-*s ", dp
->s_lattr
, np
->lattr
);
188 #endif /* __APPLE__ */
189 if (S_ISCHR(sp
->st_mode
) || S_ISBLK(sp
->st_mode
))
190 if (minor(sp
->st_rdev
) > 255 || minor(sp
->st_rdev
) < 0)
191 (void)printf("%3d, 0x%08x ",
193 (u_int
)minor(sp
->st_rdev
));
195 (void)printf("%3d, %3d ",
196 major(sp
->st_rdev
), minor(sp
->st_rdev
));
198 (void)printf("%*s%*qu ",
199 8 - dp
->s_size
, "", dp
->s_size
, (u_int64_t
)sp
->st_size
);
201 printsize(dp
->s_size
, sp
->st_size
);
203 printtime(sp
->st_atime
);
204 else if (f_statustime
)
205 printtime(sp
->st_ctime
);
207 printtime(sp
->st_mtime
);
210 color_printed
= colortype(sp
->st_mode
);
212 (void)printname(p
->fts_name
);
214 if (f_color
&& color_printed
)
218 (void)printtype(sp
->st_mode
);
219 if (S_ISLNK(sp
->st_mode
))
226 printstream(DISPLAY
*dp
)
229 extern int termwidth
;
232 for (p
= dp
->list
, chcnt
= 0; p
; p
= p
->fts_link
) {
233 if (p
->fts_number
== NO_PRINT
)
235 if (strlen(p
->fts_name
) + chcnt
+
236 (p
->fts_link
? 2 : 0) >= (unsigned)termwidth
) {
240 chcnt
+= printaname(p
, dp
->s_inode
, dp
->s_block
);
251 printcol(DISPLAY
*dp
)
253 extern int termwidth
;
254 static FTSENT
**array
;
255 static int lastentries
= -1;
275 * Have to do random access in the linked list -- build a table
278 if (dp
->entries
> lastentries
) {
279 lastentries
= dp
->entries
;
281 realloc(array
, dp
->entries
* sizeof(FTSENT
*))) == NULL
) {
286 for (p
= dp
->list
, num
= 0; p
; p
= p
->fts_link
)
287 if (p
->fts_number
!= NO_PRINT
)
290 colwidth
= dp
->maxlen
;
292 colwidth
+= dp
->s_inode
+ 1;
294 colwidth
+= dp
->s_block
+ 1;
298 colwidth
= (colwidth
+ tabwidth
) & ~(tabwidth
- 1);
299 if (termwidth
< 2 * colwidth
) {
303 numcols
= termwidth
/ colwidth
;
304 numrows
= num
/ numcols
;
308 if (dp
->list
->fts_level
!= FTS_ROOTLEVEL
&& (f_longform
|| f_size
))
309 (void)printf("total %qu\n", (u_int64_t
)howmany(dp
->btotal
, blocksize
));
312 for (row
= 0; row
< numrows
; ++row
) {
316 for (col
= 0, chcnt
= 0; col
< numcols
; ++col
) {
317 chcnt
+= printaname(array
[base
], dp
->s_inode
,
325 while ((cnt
= ((chcnt
+ tabwidth
) & ~(tabwidth
- 1)))
327 if (f_sortacross
&& col
+ 1 >= numcols
)
329 (void)putchar(f_notabs
? ' ' : '\t');
339 * print [inode] [size] name
340 * return # of characters printed, no trailing characters.
343 printaname(FTSENT
*p
, u_long inodefield
, u_long sizefield
)
348 int color_printed
= 0;
354 chcnt
+= printf("%*lu ", (int)inodefield
, (u_long
)sp
->st_ino
);
356 chcnt
+= printf("%*qu ",
357 (int)sizefield
, (u_int64_t
)howmany(sp
->st_blocks
, blocksize
));
360 color_printed
= colortype(sp
->st_mode
);
362 chcnt
+= printname(p
->fts_name
);
364 if (f_color
&& color_printed
)
368 chcnt
+= printtype(sp
->st_mode
);
373 printtime(time_t ftime
)
378 static int d_first
= -1;
381 d_first
= (*nl_langinfo(D_MD_ORDER
) == 'd');
385 #define SIXMONTHS ((365 / 2) * 86400)
387 /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */
388 format
= d_first
? "%e %b %T %Y " : "%b %e %T %Y ";
389 else if (ftime
+ SIXMONTHS
> now
&& ftime
< now
+ SIXMONTHS
)
390 /* mmm dd hh:mm || dd mmm hh:mm */
391 format
= d_first
? "%e %b %R " : "%b %e %R ";
393 /* mmm dd yyyy || dd mmm yyyy */
394 format
= d_first
? "%e %b %Y " : "%b %e %Y ";
395 strftime(longstring
, sizeof(longstring
), format
, localtime(&ftime
));
396 fputs(longstring
, stdout
);
400 printtype(u_int mode
)
404 if ((mode
& S_IFMT
) == S_IFDIR
) {
411 switch (mode
& S_IFMT
) {
430 if (mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
450 (void)write(STDOUT_FILENO
, &tmp
, 1);
460 tputs(enter_bold
, 1, putch
);
462 if (colors
[c
].num
[0] != -1) {
463 ansiseq
= tgoto(ansi_fgcol
, 0, colors
[c
].num
[0]);
465 tputs(ansiseq
, 1, putch
);
467 if (colors
[c
].num
[1] != -1) {
468 ansiseq
= tgoto(ansi_bgcol
, 0, colors
[c
].num
[1]);
470 tputs(ansiseq
, 1, putch
);
477 tputs(ansi_coloff
, 1, sig
? writech
: putch
);
478 tputs(attrs_off
, 1, sig
? writech
: putch
);
482 colortype(mode_t mode
)
484 switch (mode
& S_IFMT
) {
510 if (mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
513 else if (mode
& S_ISGID
)
523 parsecolors(const char *cs
)
529 short legacy_warn
= 0;
532 cs
= ""; /* LSCOLORS not set */
534 for (i
= 0; i
< C_NUMCOLORS
; i
++) {
538 c
[0] = defcolors
[2 * i
];
539 c
[1] = defcolors
[2 * i
+ 1];
542 c
[1] = cs
[2 * i
+ 1];
544 for (j
= 0; j
< 2; j
++) {
545 /* Legacy colours used 0-7 */
546 if (c
[j
] >= '0' && c
[j
] <= '7') {
547 colors
[i
].num
[j
] = c
[j
] - '0';
550 "warn: LSCOLORS should use "
551 "characters a-h instead of 0-9 ("
552 "see the manual page)\n");
555 } else if (c
[j
] >= 'a' && c
[j
] <= 'h')
556 colors
[i
].num
[j
] = c
[j
] - 'a';
557 else if (c
[j
] >= 'A' && c
[j
] <= 'H') {
558 colors
[i
].num
[j
] = c
[j
] - 'A';
560 } else if (tolower((unsigned char)c
[j
] == 'x'))
561 colors
[i
].num
[j
] = -1;
564 "error: invalid character '%c' in LSCOLORS"
566 colors
[i
].num
[j
] = -1;
577 (void)signal(sig
, SIG_DFL
);
578 (void)kill(getpid(), sig
);
587 char name
[MAXPATHLEN
+ 1];
588 char path
[MAXPATHLEN
+ 1];
590 if (p
->fts_level
== FTS_ROOTLEVEL
)
591 (void)snprintf(name
, sizeof(name
), "%s", p
->fts_name
);
593 (void)snprintf(name
, sizeof(name
),
594 "%s/%s", p
->fts_parent
->fts_accpath
, p
->fts_name
);
595 if ((lnklen
= readlink(name
, path
, sizeof(path
) - 1)) == -1) {
596 (void)fprintf(stderr
, "\nls: %s: %s\n", name
, strerror(errno
));
600 (void)printf(" -> ");
601 (void)printname(path
);
605 printsize(size_t width
, off_t bytes
)
610 unit
= unit_adjust(&bytes
);
613 (void)printf("%*s ", width
, "0B");
615 (void)printf("%*lld%c ", width
- 1, bytes
,
618 (void)printf("%*lld ", width
, bytes
);
622 * Output in "human-readable" format. Uses 3 digits max and puts
623 * unit suffixes at the end. Makes output compact and easy to read,
624 * especially on huge disks.
628 unit_adjust(off_t
*val
)
632 unsigned int unit_sz
;
634 abval
= fabs((double)*val
);
636 unit_sz
= abval
? ilogb(abval
) / 10 : 0;
638 if (unit_sz
>= UNIT_MAX
) {
641 unit
= unitp
[unit_sz
];
642 *val
/= (double)vals_base2
[unit_sz
];