~cfuhrman/+junk/netbsd-othersrc-trunk

« back to all changes in this revision

Viewing changes to bin/ls/print.c

  • Committer: stacktic
  • Date: 2009-03-23 21:04:00 UTC
  • Revision ID: svn-v4:288d5a72-fed7-e111-8680-000c29dcf8fe:trunk:1946
ImportedĀ fs-utilsĀ binaries

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $NetBSD$        */
 
2
/* from */
 
3
/*      NetBSD: print.c,v 1.45 2009/02/14 08:02:04 lukem Exp    */
 
4
 
 
5
/*
 
6
 * Copyright (c) 1989, 1993, 1994
 
7
 *      The Regents of the University of California.  All rights reserved.
 
8
 *
 
9
 * This code is derived from software contributed to Berkeley by
 
10
 * Michael Fischbein.
 
11
 *
 
12
 * Redistribution and use in source and binary forms, with or without
 
13
 * modification, are permitted provided that the following conditions
 
14
 * are met:
 
15
 * 1. Redistributions of source code must retain the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer.
 
17
 * 2. Redistributions in binary form must reproduce the above copyright
 
18
 *    notice, this list of conditions and the following disclaimer in the
 
19
 *    documentation and/or other materials provided with the distribution.
 
20
 * 3. 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.
 
23
 *
 
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
 
34
 * SUCH DAMAGE.
 
35
 */
 
36
 
 
37
#include <sys/cdefs.h>
 
38
#ifndef lint
 
39
#if 0
 
40
static char sccsid[] = "@(#)print.c     8.5 (Berkeley) 7/28/94";
 
41
#else
 
42
__RCSID("$NetBSD: print.c,v 1.45 2009/02/14 08:02:04 lukem Exp $");
 
43
#endif
 
44
#endif /* not lint */
 
45
 
 
46
#include <sys/param.h>
 
47
#include <sys/stat.h>
 
48
 
 
49
#include <err.h>
 
50
#include <errno.h>
 
51
#ifndef USE_UKFS
 
52
#include <fts.h>
 
53
#endif
 
54
#include <grp.h>
 
55
#include <pwd.h>
 
56
#include <stdio.h>
 
57
#include <stdlib.h>
 
58
#include <string.h>
 
59
#include <time.h>
 
60
#include <tzfile.h>
 
61
#include <unistd.h>
 
62
#include <util.h>
 
63
 
 
64
#ifdef USE_UKFS
 
65
#include <rump/ukfs.h>
 
66
#include <fsu_fts.h>
 
67
 
 
68
#define FTSENT FSU_FTSENT
 
69
#define readlink(n, p, s) ukfs_readlink(ukfs, n ,p, s)
 
70
 
 
71
extern struct ukfs *ukfs;
 
72
#endif
 
73
 
 
74
#include "ls.h"
 
75
#include "extern.h"
 
76
 
 
77
extern int termwidth;
 
78
 
 
79
static int      printaname(FTSENT *, int, int);
 
80
static void     printlink(FTSENT *);
 
81
static void     printtime(time_t);
 
82
static void     printtotal(DISPLAY *dp);
 
83
static int      printtype(u_int);
 
84
 
 
85
static time_t   now;
 
86
 
 
87
#define IS_NOPRINT(p)   ((p)->fts_number == NO_PRINT)
 
88
 
 
89
void
 
90
printscol(DISPLAY *dp)
 
91
{
 
92
        FTSENT *p;
 
93
 
 
94
        for (p = dp->list; p; p = p->fts_link) {
 
95
                if (IS_NOPRINT(p))
 
96
                        continue;
 
97
                (void)printaname(p, dp->s_inode, dp->s_block);
 
98
                (void)putchar('\n');
 
99
        }
 
100
}
 
101
 
 
102
void
 
103
printlong(DISPLAY *dp)
 
104
{
 
105
        struct stat *sp;
 
106
        FTSENT *p;
 
107
        NAMES *np;
 
108
        char buf[20], szbuf[5];
 
109
 
 
110
        now = time(NULL);
 
111
 
 
112
        printtotal(dp);         /* "total: %u\n" */
 
113
 
 
114
        for (p = dp->list; p; p = p->fts_link) {
 
115
                if (IS_NOPRINT(p))
 
116
                        continue;
 
117
                sp = p->fts_statp;
 
118
                if (f_inode)
 
119
                        (void)printf("%*lu ", dp->s_inode,
 
120
                            (unsigned long)sp->st_ino);
 
121
                if (f_size) {
 
122
                        if (f_humanize) {
 
123
                                if ((humanize_number(szbuf, sizeof(szbuf),
 
124
                                        sp->st_blocks * S_BLKSIZE,
 
125
                            "", HN_AUTOSCALE,
 
126
                            (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
 
127
                                err(1, "humanize_number");
 
128
                        (void)printf("%*s ", dp->s_block, szbuf);
 
129
                        } else {
 
130
                        (void)printf("%*llu ", dp->s_block,
 
131
                                        (long long)howmany(sp->st_blocks,
 
132
                                                                blocksize));
 
133
                        }
 
134
                }
 
135
                (void)strmode(sp->st_mode, buf);
 
136
                np = p->fts_pointer;
 
137
                (void)printf("%s %*lu ", buf, dp->s_nlink,
 
138
                    (unsigned long)sp->st_nlink);
 
139
                if (!f_grouponly)
 
140
                        (void)printf("%-*s  ", dp->s_user, np->user);
 
141
                (void)printf("%-*s  ", dp->s_group, np->group);
 
142
                if (f_flags)
 
143
                        (void)printf("%-*s ", dp->s_flags, np->flags);
 
144
                if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
 
145
                        (void)printf("%*lld, %*lld ",
 
146
                            dp->s_major, (long long)major(sp->st_rdev),
 
147
                            dp->s_minor, (long long)minor(sp->st_rdev));
 
148
                else
 
149
                        if (f_humanize) {
 
150
                                if ((humanize_number(szbuf, sizeof(szbuf),
 
151
                                    sp->st_size, "", HN_AUTOSCALE,
 
152
                                    (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
 
153
                                        err(1, "humanize_number");
 
154
                                (void)printf("%*s ", dp->s_size, szbuf);
 
155
                        } else {
 
156
                                (void)printf("%*llu ", dp->s_size,
 
157
                                    (long long)sp->st_size);
 
158
                        }
 
159
                if (f_accesstime)
 
160
                        printtime(sp->st_atime);
 
161
                else if (f_statustime)
 
162
                        printtime(sp->st_ctime);
 
163
                else
 
164
                        printtime(sp->st_mtime);
 
165
                if (f_octal || f_octal_escape)
 
166
                        (void)safe_print(p->fts_name);
 
167
                else if (f_nonprint)
 
168
                        (void)printescaped(p->fts_name);
 
169
                else
 
170
                        (void)printf("%s", p->fts_name);
 
171
 
 
172
                if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
 
173
                        (void)printtype(sp->st_mode);
 
174
                if (S_ISLNK(sp->st_mode))
 
175
                        printlink(p);
 
176
                (void)putchar('\n');
 
177
        }
 
178
}
 
179
 
 
180
void
 
181
printcol(DISPLAY *dp)
 
182
{
 
183
        static FTSENT **array;
 
184
        static int lastentries = -1;
 
185
        FTSENT *p;
 
186
        int base, chcnt, col, colwidth, num;
 
187
        int numcols, numrows, row;
 
188
 
 
189
        colwidth = dp->maxlen;
 
190
        if (f_inode)
 
191
                colwidth += dp->s_inode + 1;
 
192
        if (f_size) {
 
193
                if (f_humanize)
 
194
                        colwidth += dp->s_size + 1;
 
195
                else
 
196
                        colwidth += dp->s_block + 1;
 
197
        }
 
198
        if (f_type || f_typedir)
 
199
                colwidth += 1;
 
200
 
 
201
        colwidth += 1;
 
202
 
 
203
        if (termwidth < 2 * colwidth) {
 
204
                printscol(dp);
 
205
                return;
 
206
        }
 
207
 
 
208
        /*
 
209
         * Have to do random access in the linked list -- build a table
 
210
         * of pointers.
 
211
         */
 
212
        if (dp->entries > lastentries) {
 
213
                lastentries = dp->entries;
 
214
                if ((array =
 
215
                    realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
 
216
                        warn(NULL);
 
217
                        printscol(dp);
 
218
                }
 
219
        }
 
220
        for (p = dp->list, num = 0; p; p = p->fts_link)
 
221
                if (p->fts_number != NO_PRINT)
 
222
                        array[num++] = p;
 
223
 
 
224
        numcols = termwidth / colwidth;
 
225
        colwidth = termwidth / numcols;         /* spread out if possible */
 
226
        numrows = num / numcols;
 
227
        if (num % numcols)
 
228
                ++numrows;
 
229
 
 
230
        printtotal(dp);                         /* "total: %u\n" */
 
231
 
 
232
        for (row = 0; row < numrows; ++row) {
 
233
                for (base = row, chcnt = col = 0; col < numcols; ++col) {
 
234
                        chcnt = printaname(array[base], dp->s_inode,
 
235
                            f_humanize ? dp->s_size : dp->s_block);
 
236
                        if ((base += numrows) >= num)
 
237
                                break;
 
238
                        while (chcnt++ < colwidth)
 
239
                                (void)putchar(' ');
 
240
                }
 
241
                (void)putchar('\n');
 
242
        }
 
243
}
 
244
 
 
245
void
 
246
printacol(DISPLAY *dp)
 
247
{
 
248
        FTSENT *p;
 
249
        int chcnt, col, colwidth;
 
250
        int numcols;
 
251
 
 
252
        colwidth = dp->maxlen;
 
253
        if (f_inode)
 
254
                colwidth += dp->s_inode + 1;
 
255
        if (f_size) {
 
256
                if (f_humanize)
 
257
                        colwidth += dp->s_size + 1;
 
258
                else
 
259
                        colwidth += dp->s_block + 1;
 
260
        }
 
261
        if (f_type || f_typedir)
 
262
                colwidth += 1;
 
263
 
 
264
        colwidth += 1;
 
265
 
 
266
        if (termwidth < 2 * colwidth) {
 
267
                printscol(dp);
 
268
                return;
 
269
        }
 
270
 
 
271
        numcols = termwidth / colwidth;
 
272
        colwidth = termwidth / numcols;         /* spread out if possible */
 
273
 
 
274
        printtotal(dp);                         /* "total: %u\n" */
 
275
 
 
276
        chcnt = col = 0;
 
277
        for (p = dp->list; p; p = p->fts_link) {
 
278
                if (IS_NOPRINT(p))
 
279
                        continue;
 
280
                if (col >= numcols) {
 
281
                        chcnt = col = 0;
 
282
                        (void)putchar('\n');
 
283
                }
 
284
                chcnt = printaname(p, dp->s_inode,
 
285
                    f_humanize ? dp->s_size : dp->s_block);
 
286
                while (chcnt++ < colwidth)
 
287
                        (void)putchar(' ');
 
288
                col++;
 
289
        }
 
290
        (void)putchar('\n');
 
291
}
 
292
 
 
293
void
 
294
printstream(DISPLAY *dp)
 
295
{
 
296
        FTSENT *p;
 
297
        int col;
 
298
        int extwidth;
 
299
 
 
300
        extwidth = 0;
 
301
        if (f_inode)
 
302
                extwidth += dp->s_inode + 1;
 
303
        if (f_size) {
 
304
                if (f_humanize)
 
305
                        extwidth += dp->s_size + 1;
 
306
                else
 
307
                        extwidth += dp->s_block + 1;
 
308
        }
 
309
        if (f_type)
 
310
                extwidth += 1;
 
311
 
 
312
        for (col = 0, p = dp->list; p != NULL; p = p->fts_link) {
 
313
                if (IS_NOPRINT(p))
 
314
                        continue;
 
315
                if (col > 0) {
 
316
                        (void)putchar(','), col++;
 
317
                        if (col + 1 + extwidth + (int)p->fts_namelen >= termwidth)
 
318
                                (void)putchar('\n'), col = 0;
 
319
                        else
 
320
                                (void)putchar(' '), col++;
 
321
                }
 
322
                col += printaname(p, dp->s_inode,
 
323
                    f_humanize ? dp->s_size : dp->s_block);
 
324
        }
 
325
        (void)putchar('\n');
 
326
}
 
327
 
 
328
/*
 
329
 * print [inode] [size] name
 
330
 * return # of characters printed, no trailing characters.
 
331
 */
 
332
static int
 
333
printaname(FTSENT *p, int inodefield, int sizefield)
 
334
{
 
335
        struct stat *sp;
 
336
        int chcnt;
 
337
        char szbuf[5];
 
338
 
 
339
        sp = p->fts_statp;
 
340
        chcnt = 0;
 
341
        if (f_inode)
 
342
                chcnt += printf("%*lu ", inodefield, (unsigned long)sp->st_ino);
 
343
        if (f_size) {
 
344
                if (f_humanize) {
 
345
                        if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size,
 
346
                            "", HN_AUTOSCALE,
 
347
                            (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
 
348
                                err(1, "humanize_number");
 
349
                        chcnt += printf("%*s ", sizefield, szbuf);
 
350
                } else {
 
351
                        chcnt += printf("%*llu ", sizefield,
 
352
                            (long long)howmany(sp->st_blocks, blocksize));
 
353
                }
 
354
        }
 
355
        if (f_octal || f_octal_escape)
 
356
                chcnt += safe_print(p->fts_name);
 
357
        else if (f_nonprint)
 
358
                chcnt += printescaped(p->fts_name);
 
359
        else
 
360
                chcnt += printf("%s", p->fts_name);
 
361
        if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
 
362
                chcnt += printtype(sp->st_mode);
 
363
        return (chcnt);
 
364
}
 
365
 
 
366
static void
 
367
printtime(time_t ftime)
 
368
{
 
369
        int i;
 
370
        char *longstring;
 
371
 
 
372
        longstring = ctime(&ftime);
 
373
        for (i = 4; i < 11; ++i)
 
374
                (void)putchar(longstring[i]);
 
375
 
 
376
#define SIXMONTHS       ((DAYSPERNYEAR / 2) * SECSPERDAY)
 
377
        if (f_sectime)
 
378
                for (i = 11; i < 24; i++)
 
379
                        (void)putchar(longstring[i]);
 
380
        else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now)
 
381
                for (i = 11; i < 16; ++i)
 
382
                        (void)putchar(longstring[i]);
 
383
        else {
 
384
                (void)putchar(' ');
 
385
                for (i = 20; i < 24; ++i)
 
386
                        (void)putchar(longstring[i]);
 
387
        }
 
388
        (void)putchar(' ');
 
389
}
 
390
 
 
391
/*
 
392
 * Display total used disk space in the form "total: %u\n".
 
393
 * Note: POSIX (IEEE Std 1003.1-2001) says this should be always in 512 blocks,
 
394
 * but we humanise it with -h and use 1024 with -k.
 
395
 */
 
396
static void
 
397
printtotal(DISPLAY *dp)
 
398
{
 
399
        char szbuf[5];
 
400
        
 
401
        if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) {
 
402
                if (f_humanize) {
 
403
                        if ((humanize_number(szbuf, sizeof(szbuf), (int64_t)dp->stotal,
 
404
                            "", HN_AUTOSCALE,
 
405
                            (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
 
406
                                err(1, "humanize_number");
 
407
                        (void)printf("total %s\n", szbuf);
 
408
                } else {
 
409
                        (void)printf("total %llu\n",
 
410
                            (long long)(howmany(dp->btotal, blocksize)));
 
411
                }
 
412
        }
 
413
}
 
414
 
 
415
static int
 
416
printtype(u_int mode)
 
417
{
 
418
        switch (mode & S_IFMT) {
 
419
        case S_IFDIR:
 
420
                (void)putchar('/');
 
421
                return (1);
 
422
        case S_IFIFO:
 
423
                (void)putchar('|');
 
424
                return (1);
 
425
        case S_IFLNK:
 
426
                (void)putchar('@');
 
427
                return (1);
 
428
        case S_IFSOCK:
 
429
                (void)putchar('=');
 
430
                return (1);
 
431
        case S_IFWHT:
 
432
                (void)putchar('%');
 
433
                return (1);
 
434
        }
 
435
        if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
 
436
                (void)putchar('*');
 
437
                return (1);
 
438
        }
 
439
        return (0);
 
440
}
 
441
 
 
442
static void
 
443
printlink(FTSENT *p)
 
444
{
 
445
        int lnklen;
 
446
        char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1];
 
447
 
 
448
        if (p->fts_level == FTS_ROOTLEVEL)
 
449
                (void)snprintf(name, sizeof(name), "%s", p->fts_name);
 
450
        else
 
451
                (void)snprintf(name, sizeof(name),
 
452
                    "%s/%s", p->fts_parent->fts_accpath, p->fts_name);
 
453
        if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) {
 
454
                (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno));
 
455
                return;
 
456
        }
 
457
        path[lnklen] = '\0';
 
458
        (void)printf(" -> ");
 
459
        if (f_octal || f_octal_escape)
 
460
                (void)safe_print(path);
 
461
        else if (f_nonprint)
 
462
                (void)printescaped(path);
 
463
        else
 
464
                (void)printf("%s", path);
 
465
}