1 /* $NetBSD: print.c,v 1.44 2008/12/28 19:30:33 christos Exp $ */
4 * Copyright (c) 1989, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
38 static char sccsid
[] = "@(#)print.c 8.5 (Berkeley) 7/28/94";
40 __RCSID("$NetBSD: print.c,v 1.44 2008/12/28 19:30:33 christos Exp $");
44 #include <sys/param.h>
65 static int printaname(FTSENT
*, int, int);
66 static void printlink(FTSENT
*);
67 static void printtime(time_t);
68 static void printtotal(DISPLAY
*dp
);
69 static int printtype(u_int
);
73 #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
76 printscol(DISPLAY
*dp
)
80 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
83 (void)printaname(p
, dp
->s_inode
, dp
->s_block
);
89 printlong(DISPLAY
*dp
)
94 char buf
[20], szbuf
[5];
98 printtotal(dp
); /* "total: %u\n" */
100 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
105 (void)printf("%*lu ", dp
->s_inode
,
106 (unsigned long)sp
->st_ino
);
109 if ((humanize_number(szbuf
, sizeof(szbuf
),
110 sp
->st_blocks
* S_BLKSIZE
,
112 (HN_DECIMAL
| HN_B
| HN_NOSPACE
))) == -1)
113 err(1, "humanize_number");
114 (void)printf("%*s ", dp
->s_block
, szbuf
);
116 (void)printf("%*llu ", dp
->s_block
,
117 (long long)howmany(sp
->st_blocks
,
121 (void)strmode(sp
->st_mode
, buf
);
123 (void)printf("%s %*lu ", buf
, dp
->s_nlink
,
124 (unsigned long)sp
->st_nlink
);
126 (void)printf("%-*s ", dp
->s_user
, np
->user
);
127 (void)printf("%-*s ", dp
->s_group
, np
->group
);
129 (void)printf("%-*s ", dp
->s_flags
, np
->flags
);
130 if (S_ISCHR(sp
->st_mode
) || S_ISBLK(sp
->st_mode
))
131 (void)printf("%*lld, %*lld ",
132 dp
->s_major
, (long long)major(sp
->st_rdev
),
133 dp
->s_minor
, (long long)minor(sp
->st_rdev
));
136 if ((humanize_number(szbuf
, sizeof(szbuf
),
137 sp
->st_size
, "", HN_AUTOSCALE
,
138 (HN_DECIMAL
| HN_B
| HN_NOSPACE
))) == -1)
139 err(1, "humanize_number");
140 (void)printf("%*s ", dp
->s_size
, szbuf
);
142 (void)printf("%*llu ", dp
->s_size
,
143 (long long)sp
->st_size
);
146 printtime(sp
->st_atime
);
147 else if (f_statustime
)
148 printtime(sp
->st_ctime
);
150 printtime(sp
->st_mtime
);
151 if (f_octal
|| f_octal_escape
)
152 (void)safe_print(p
->fts_name
);
154 (void)printescaped(p
->fts_name
);
156 (void)printf("%s", p
->fts_name
);
158 if (f_type
|| (f_typedir
&& S_ISDIR(sp
->st_mode
)))
159 (void)printtype(sp
->st_mode
);
160 if (S_ISLNK(sp
->st_mode
))
167 printcol(DISPLAY
*dp
)
169 static FTSENT
**array
;
170 static int lastentries
= -1;
172 int base
, chcnt
, col
, colwidth
, num
;
173 int numcols
, numrows
, row
;
175 colwidth
= dp
->maxlen
;
177 colwidth
+= dp
->s_inode
+ 1;
180 colwidth
+= dp
->s_size
+ 1;
182 colwidth
+= dp
->s_block
+ 1;
184 if (f_type
|| f_typedir
)
189 if (termwidth
< 2 * colwidth
) {
195 * Have to do random access in the linked list -- build a table
198 if (dp
->entries
> lastentries
) {
199 lastentries
= dp
->entries
;
201 realloc(array
, dp
->entries
* sizeof(FTSENT
*))) == NULL
) {
206 for (p
= dp
->list
, num
= 0; p
; p
= p
->fts_link
)
207 if (p
->fts_number
!= NO_PRINT
)
210 numcols
= termwidth
/ colwidth
;
211 colwidth
= termwidth
/ numcols
; /* spread out if possible */
212 numrows
= num
/ numcols
;
216 printtotal(dp
); /* "total: %u\n" */
218 for (row
= 0; row
< numrows
; ++row
) {
219 for (base
= row
, chcnt
= col
= 0; col
< numcols
; ++col
) {
220 chcnt
= printaname(array
[base
], dp
->s_inode
,
221 f_humanize
? dp
->s_size
: dp
->s_block
);
222 if ((base
+= numrows
) >= num
)
224 while (chcnt
++ < colwidth
)
232 printacol(DISPLAY
*dp
)
235 int chcnt
, col
, colwidth
;
238 colwidth
= dp
->maxlen
;
240 colwidth
+= dp
->s_inode
+ 1;
243 colwidth
+= dp
->s_size
+ 1;
245 colwidth
+= dp
->s_block
+ 1;
247 if (f_type
|| f_typedir
)
252 if (termwidth
< 2 * colwidth
) {
257 numcols
= termwidth
/ colwidth
;
258 colwidth
= termwidth
/ numcols
; /* spread out if possible */
260 printtotal(dp
); /* "total: %u\n" */
263 for (p
= dp
->list
; p
; p
= p
->fts_link
) {
266 if (col
>= numcols
) {
270 chcnt
= printaname(p
, dp
->s_inode
,
271 f_humanize
? dp
->s_size
: dp
->s_block
);
272 while (chcnt
++ < colwidth
)
280 printstream(DISPLAY
*dp
)
288 extwidth
+= dp
->s_inode
+ 1;
291 extwidth
+= dp
->s_size
+ 1;
293 extwidth
+= dp
->s_block
+ 1;
298 for (col
= 0, p
= dp
->list
; p
!= NULL
; p
= p
->fts_link
) {
302 (void)putchar(','), col
++;
303 if (col
+ 1 + extwidth
+ (int)p
->fts_namelen
>= termwidth
)
304 (void)putchar('\n'), col
= 0;
306 (void)putchar(' '), col
++;
308 col
+= printaname(p
, dp
->s_inode
,
309 f_humanize
? dp
->s_size
: dp
->s_block
);
315 * print [inode] [size] name
316 * return # of characters printed, no trailing characters.
319 printaname(FTSENT
*p
, int inodefield
, int sizefield
)
328 chcnt
+= printf("%*lu ", inodefield
, (unsigned long)sp
->st_ino
);
331 if ((humanize_number(szbuf
, sizeof(szbuf
), sp
->st_size
,
333 (HN_DECIMAL
| HN_B
| HN_NOSPACE
))) == -1)
334 err(1, "humanize_number");
335 chcnt
+= printf("%*s ", sizefield
, szbuf
);
337 chcnt
+= printf("%*llu ", sizefield
,
338 (long long)howmany(sp
->st_blocks
, blocksize
));
341 if (f_octal
|| f_octal_escape
)
342 chcnt
+= safe_print(p
->fts_name
);
344 chcnt
+= printescaped(p
->fts_name
);
346 chcnt
+= printf("%s", p
->fts_name
);
347 if (f_type
|| (f_typedir
&& S_ISDIR(sp
->st_mode
)))
348 chcnt
+= printtype(sp
->st_mode
);
353 printtime(time_t ftime
)
358 longstring
= ctime(&ftime
);
359 for (i
= 4; i
< 11; ++i
)
360 (void)putchar(longstring
[i
]);
362 #define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY)
364 for (i
= 11; i
< 24; i
++)
365 (void)putchar(longstring
[i
]);
366 else if (ftime
+ SIXMONTHS
> now
&& ftime
- SIXMONTHS
< now
)
367 for (i
= 11; i
< 16; ++i
)
368 (void)putchar(longstring
[i
]);
371 for (i
= 20; i
< 24; ++i
)
372 (void)putchar(longstring
[i
]);
378 * Display total used disk space in the form "total: %u\n".
379 * Note: POSIX (IEEE Std 1003.1-2001) says this should be always in 512 blocks,
380 * but we humanise it with -h and use 1024 with -k.
383 printtotal(DISPLAY
*dp
)
387 if (dp
->list
->fts_level
!= FTS_ROOTLEVEL
&& (f_longform
|| f_size
)) {
389 if ((humanize_number(szbuf
, sizeof(szbuf
), (int64_t)dp
->stotal
,
391 (HN_DECIMAL
| HN_B
| HN_NOSPACE
))) == -1)
392 err(1, "humanize_number");
393 (void)printf("total %s\n", szbuf
);
395 (void)printf("total %llu\n",
396 (long long)(howmany(dp
->btotal
, blocksize
)));
402 printtype(u_int mode
)
404 switch (mode
& S_IFMT
) {
421 if (mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) {
432 char name
[MAXPATHLEN
+ 1], path
[MAXPATHLEN
+ 1];
434 if (p
->fts_level
== FTS_ROOTLEVEL
)
435 (void)snprintf(name
, sizeof(name
), "%s", p
->fts_name
);
437 (void)snprintf(name
, sizeof(name
),
438 "%s/%s", p
->fts_parent
->fts_accpath
, p
->fts_name
);
439 if ((lnklen
= readlink(name
, path
, sizeof(path
) - 1)) == -1) {
440 (void)fprintf(stderr
, "\nls: %s: %s\n", name
, strerror(errno
));
444 (void)printf(" -> ");
445 if (f_octal
|| f_octal_escape
)
446 (void)safe_print(path
);
448 (void)printescaped(path
);
450 (void)printf("%s", path
);