]>
git.saurik.com Git - apple/file_cmds.git/blob - ls/print.c
b3dd33954b1968e180cdd865b3cb37d8a75865b4
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>
54 #endif /* __APPLE__ */
69 static int printaname(FTSENT
*, u_long
, u_long
);
70 static void printlink(FTSENT
*);
71 static void printtime(time_t);
72 static int printtype(u_int
);
73 static void printsize(size_t, off_t
);
75 static void endcolor(int);
76 static int colortype(mode_t
);
79 #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
81 #define KILO_SZ(n) (n)
82 #define MEGA_SZ(n) ((n) * (n))
83 #define GIGA_SZ(n) ((n) * (n) * (n))
84 #define TERA_SZ(n) ((n) * (n) * (n) * (n))
85 #define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
87 #define KILO_2_SZ (KILO_SZ(1024ULL))
88 #define MEGA_2_SZ (MEGA_SZ(1024ULL))
89 #define GIGA_2_SZ (GIGA_SZ(1024ULL))
90 #define TERA_2_SZ (TERA_SZ(1024ULL))
91 #define PETA_2_SZ (PETA_SZ(1024ULL))
93 static u_int64_t vals_base2
[] = {1, KILO_2_SZ
, MEGA_2_SZ
, GIGA_2_SZ
, TERA_2_SZ
, PETA_2_SZ
};
96 NONE
, KILO
, MEGA
, GIGA
, TERA
, PETA
, UNIT_MAX
98 static unit_t
unit_adjust(off_t
*);
100 static int unitp
[] = {NONE
, KILO
, MEGA
, GIGA
, TERA
, PETA
};
103 /* Most of these are taken from <sys/stat.h> */
104 typedef enum Colors
{
105 C_DIR
, /* directory */
106 C_LNK
, /* symbolic link */
109 C_EXEC
, /* executable */
110 C_BLK
, /* block special */
111 C_CHR
, /* character special */
112 C_SUID
, /* setuid executable */
113 C_SGID
, /* setgid executable */
114 C_WSDIR
, /* directory writeble to others, with sticky
116 C_WDIR
, /* directory writeble to others, without
118 C_NUMCOLORS
/* just a place-holder */
121 static const char *defcolors
= "exfxcxdxbxegedabagacad";
123 /* colors for file types */
127 } colors
[C_NUMCOLORS
];
131 printscol(DISPLAY
*dp
)
135 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
138 (void)printaname(p
, dp
->s_inode
, dp
->s_block
);
144 * print name in current style
147 printname(const char *name
)
149 if (f_octal
|| f_octal_escape
)
150 return prn_octal(name
);
152 return prn_printable(name
);
154 return printf("%s", name
);
158 printlong(DISPLAY
*dp
)
165 int color_printed
= 0;
168 if (dp
->list
->fts_level
!= FTS_ROOTLEVEL
&& (f_longform
|| f_size
))
169 (void)printf("total %qu\n", (u_int64_t
)howmany(dp
->btotal
, blocksize
));
171 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
176 (void)printf("%*lu ", dp
->s_inode
, (u_long
)sp
->st_ino
);
178 (void)printf("%*qu ",
179 dp
->s_block
, (u_int64_t
)howmany(sp
->st_blocks
, blocksize
));
180 strmode(sp
->st_mode
, buf
);
182 (void)printf("%s %*u %-*s %-*s ", buf
, dp
->s_nlink
,
183 sp
->st_nlink
, dp
->s_user
, np
->user
, dp
->s_group
,
186 (void)printf("%-*s ", dp
->s_flags
, np
->flags
);
189 (void)printf("%-*s ", dp
->s_lattr
, np
->lattr
);
190 #endif /* __APPLE__ */
191 if (S_ISCHR(sp
->st_mode
) || S_ISBLK(sp
->st_mode
))
192 if (minor(sp
->st_rdev
) > 255 || minor(sp
->st_rdev
) < 0)
193 (void)printf("%3d, 0x%08x ",
195 (u_int
)minor(sp
->st_rdev
));
197 (void)printf("%3d, %3d ",
198 major(sp
->st_rdev
), minor(sp
->st_rdev
));
200 (void)printf("%*s%*qu ",
201 8 - dp
->s_size
, "", dp
->s_size
, (u_int64_t
)sp
->st_size
);
203 printsize(dp
->s_size
, sp
->st_size
);
205 printtime(sp
->st_atime
);
206 else if (f_statustime
)
207 printtime(sp
->st_ctime
);
209 printtime(sp
->st_mtime
);
212 color_printed
= colortype(sp
->st_mode
);
214 (void)printname(p
->fts_name
);
216 if (f_color
&& color_printed
)
220 (void)printtype(sp
->st_mode
);
221 if (S_ISLNK(sp
->st_mode
))
228 printstream(DISPLAY
*dp
)
231 extern int termwidth
;
234 for (p
= dp
->list
, chcnt
= 0; p
; p
= p
->fts_link
) {
235 if (p
->fts_number
== NO_PRINT
)
237 if (strlen(p
->fts_name
) + chcnt
+
238 (p
->fts_link
? 2 : 0) >= (unsigned)termwidth
) {
242 chcnt
+= printaname(p
, dp
->s_inode
, dp
->s_block
);
253 printcol(DISPLAY
*dp
)
255 extern int termwidth
;
256 static FTSENT
**array
;
257 static int lastentries
= -1;
277 * Have to do random access in the linked list -- build a table
280 if (dp
->entries
> lastentries
) {
281 lastentries
= dp
->entries
;
283 realloc(array
, dp
->entries
* sizeof(FTSENT
*))) == NULL
) {
288 for (p
= dp
->list
, num
= 0; p
; p
= p
->fts_link
)
289 if (p
->fts_number
!= NO_PRINT
)
292 colwidth
= dp
->maxlen
;
294 colwidth
+= dp
->s_inode
+ 1;
296 colwidth
+= dp
->s_block
+ 1;
300 colwidth
= (colwidth
+ tabwidth
) & ~(tabwidth
- 1);
301 if (termwidth
< 2 * colwidth
) {
305 numcols
= termwidth
/ colwidth
;
306 numrows
= num
/ numcols
;
310 if (dp
->list
->fts_level
!= FTS_ROOTLEVEL
&& (f_longform
|| f_size
))
311 (void)printf("total %qu\n", (u_int64_t
)howmany(dp
->btotal
, blocksize
));
314 for (row
= 0; row
< numrows
; ++row
) {
318 for (col
= 0, chcnt
= 0; col
< numcols
; ++col
) {
319 chcnt
+= printaname(array
[base
], dp
->s_inode
,
327 while ((cnt
= ((chcnt
+ tabwidth
) & ~(tabwidth
- 1)))
329 if (f_sortacross
&& col
+ 1 >= numcols
)
331 (void)putchar(f_notabs
? ' ' : '\t');
341 * print [inode] [size] name
342 * return # of characters printed, no trailing characters.
345 printaname(FTSENT
*p
, u_long inodefield
, u_long sizefield
)
350 int color_printed
= 0;
356 chcnt
+= printf("%*lu ", (int)inodefield
, (u_long
)sp
->st_ino
);
358 chcnt
+= printf("%*qu ",
359 (int)sizefield
, (u_int64_t
)howmany(sp
->st_blocks
, blocksize
));
362 color_printed
= colortype(sp
->st_mode
);
364 chcnt
+= printname(p
->fts_name
);
366 if (f_color
&& color_printed
)
370 chcnt
+= printtype(sp
->st_mode
);
375 printtime(time_t ftime
)
380 static int d_first
= -1;
384 d_first
= (*nl_langinfo(D_MD_ORDER
) == 'd');
385 #endif /* __APPLE__ */
389 #define SIXMONTHS ((365 / 2) * 86400)
391 /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */
392 format
= d_first
? "%e %b %T %Y " : "%b %e %T %Y ";
393 else if (ftime
+ SIXMONTHS
> now
&& ftime
< now
+ SIXMONTHS
)
394 /* mmm dd hh:mm || dd mmm hh:mm */
395 format
= d_first
? "%e %b %R " : "%b %e %R ";
397 /* mmm dd yyyy || dd mmm yyyy */
398 format
= d_first
? "%e %b %Y " : "%b %e %Y ";
399 strftime(longstring
, sizeof(longstring
), format
, localtime(&ftime
));
400 fputs(longstring
, stdout
);
404 printtype(u_int mode
)
408 if ((mode
& S_IFMT
) == S_IFDIR
) {
415 switch (mode
& S_IFMT
) {
434 if (mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
454 (void)write(STDOUT_FILENO
, &tmp
, 1);
464 tputs(enter_bold
, 1, putch
);
466 if (colors
[c
].num
[0] != -1) {
467 ansiseq
= tgoto(ansi_fgcol
, 0, colors
[c
].num
[0]);
469 tputs(ansiseq
, 1, putch
);
471 if (colors
[c
].num
[1] != -1) {
472 ansiseq
= tgoto(ansi_bgcol
, 0, colors
[c
].num
[1]);
474 tputs(ansiseq
, 1, putch
);
481 tputs(ansi_coloff
, 1, sig
? writech
: putch
);
482 tputs(attrs_off
, 1, sig
? writech
: putch
);
486 colortype(mode_t mode
)
488 switch (mode
& S_IFMT
) {
514 if (mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
517 else if (mode
& S_ISGID
)
527 parsecolors(const char *cs
)
533 short legacy_warn
= 0;
536 cs
= ""; /* LSCOLORS not set */
538 for (i
= 0; i
< C_NUMCOLORS
; i
++) {
542 c
[0] = defcolors
[2 * i
];
543 c
[1] = defcolors
[2 * i
+ 1];
546 c
[1] = cs
[2 * i
+ 1];
548 for (j
= 0; j
< 2; j
++) {
549 /* Legacy colours used 0-7 */
550 if (c
[j
] >= '0' && c
[j
] <= '7') {
551 colors
[i
].num
[j
] = c
[j
] - '0';
554 "warn: LSCOLORS should use "
555 "characters a-h instead of 0-9 ("
556 "see the manual page)\n");
559 } else if (c
[j
] >= 'a' && c
[j
] <= 'h')
560 colors
[i
].num
[j
] = c
[j
] - 'a';
561 else if (c
[j
] >= 'A' && c
[j
] <= 'H') {
562 colors
[i
].num
[j
] = c
[j
] - 'A';
564 } else if (tolower((unsigned char)c
[j
] == 'x'))
565 colors
[i
].num
[j
] = -1;
568 "error: invalid character '%c' in LSCOLORS"
570 colors
[i
].num
[j
] = -1;
581 (void)signal(sig
, SIG_DFL
);
582 (void)kill(getpid(), sig
);
591 char name
[MAXPATHLEN
+ 1];
592 char path
[MAXPATHLEN
+ 1];
594 if (p
->fts_level
== FTS_ROOTLEVEL
)
595 (void)snprintf(name
, sizeof(name
), "%s", p
->fts_name
);
597 (void)snprintf(name
, sizeof(name
),
598 "%s/%s", p
->fts_parent
->fts_accpath
, p
->fts_name
);
599 if ((lnklen
= readlink(name
, path
, sizeof(path
) - 1)) == -1) {
600 (void)fprintf(stderr
, "\nls: %s: %s\n", name
, strerror(errno
));
604 (void)printf(" -> ");
605 (void)printname(path
);
609 printsize(size_t width
, off_t bytes
)
614 unit
= unit_adjust(&bytes
);
617 (void)printf("%*s ", width
, "0B");
619 (void)printf("%*lld%c ", width
- 1, bytes
,
622 (void)printf("%*lld ", width
, bytes
);
626 * Output in "human-readable" format. Uses 3 digits max and puts
627 * unit suffixes at the end. Makes output compact and easy to read,
628 * especially on huge disks.
632 unit_adjust(off_t
*val
)
636 unsigned int unit_sz
;
638 abval
= fabs((double)*val
);
640 unit_sz
= abval
? ilogb(abval
) / 10 : 0;
642 if (unit_sz
>= UNIT_MAX
) {
645 unit
= unitp
[unit_sz
];
646 *val
/= (double)vals_base2
[unit_sz
];