2 * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
11 #include <sys/types.h>
20 #include "libsmartcols.h"
22 static int add_children(struct libscols_table
*tb
,
23 struct libscols_line
*ln
, int fd
);
26 enum { COL_MODE
, COL_SIZE
, COL_NAME
};
28 /* add columns to the @tb */
29 static void setup_columns(struct libscols_table
*tb
, int notree
)
31 if (!scols_table_new_column(tb
, "MODE", 0.3, 0))
33 if (!scols_table_new_column(tb
, "SIZE", 5, SCOLS_FL_RIGHT
))
35 if (!scols_table_new_column(tb
, "NAME", 0.5,
36 (notree
? 0 : SCOLS_FL_TREE
) | SCOLS_FL_NOEXTREMES
))
41 scols_unref_table(tb
);
42 err(EXIT_FAILURE
, "failed to create output columns");
45 /* add a new line to @tb, the content is based on @st */
46 static int add_line_from_stat(struct libscols_table
*tb
,
47 struct libscols_line
*parent
,
52 struct libscols_line
*ln
;
54 mode_t mode
= st
->st_mode
;
57 ln
= scols_table_new_line(tb
, parent
);
59 err(EXIT_FAILURE
, "failed to create output line");
61 /* MODE; local buffer, use scols_line_set_data() that calls strdup() */
62 xstrmode(mode
, modbuf
);
63 if (scols_line_set_data(ln
, COL_MODE
, modbuf
))
66 /* SIZE; already allocated string, use scols_line_refer_data() */
67 p
= size_to_human_string(0, st
->st_size
);
68 if (!p
|| scols_line_refer_data(ln
, COL_SIZE
, p
))
72 if (scols_line_set_data(ln
, COL_NAME
, name
))
76 if (scols_table_colors_wanted(tb
)) {
77 struct libscols_cell
*ce
= scols_line_get_cell(ln
, COL_NAME
);
80 scols_cell_set_color(ce
, "blue");
81 else if (S_ISLNK(mode
))
82 scols_cell_set_color(ce
, "cyan");
83 else if (S_ISBLK(mode
))
84 scols_cell_set_color(ce
, "magenta");
85 else if ((mode
& S_IXOTH
) || (mode
& S_IXGRP
) || (mode
& S_IXUSR
))
86 scols_cell_set_color(ce
, "green");
89 if (S_ISDIR(st
->st_mode
)) {
93 fd
= openat(parent_fd
, name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
95 fd
= open(name
, O_RDONLY
|O_NONBLOCK
|O_DIRECTORY
|O_CLOEXEC
);
97 rc
= add_children(tb
, ln
, fd
);
103 err(EXIT_FAILURE
, "failed to create cell data");
107 /* read all entries from directory addressed by @fd */
108 static int add_children(struct libscols_table
*tb
,
109 struct libscols_line
*ln
,
119 while ((d
= readdir(dir
))) {
122 if (strcmp(d
->d_name
, ".") == 0 || strcmp(d
->d_name
, "..") == 0)
124 if (fstatat(fd
, d
->d_name
, &st
, AT_SYMLINK_NOFOLLOW
) != 0)
126 add_line_from_stat(tb
, ln
, fd
, &st
, d
->d_name
);
132 static void add_lines(struct libscols_table
*tb
, const char *dirname
)
136 if (lstat(dirname
, &st
))
137 err(EXIT_FAILURE
, "%s", dirname
);
139 add_line_from_stat(tb
, NULL
, -1, &st
, dirname
);
142 static void __attribute__((__noreturn__
)) usage(FILE *out
)
144 fprintf(out
, " %s [options] [<dir> ...]\n\n", program_invocation_short_name
);
145 fputs(" -c, --csv display a csv-like output\n", out
);
146 fputs(" -i, --ascii use ascii characters only\n", out
);
147 fputs(" -l, --list use list format output\n", out
);
148 fputs(" -n, --noheadings don't print headings\n", out
);
149 fputs(" -p, --pairs use key=\"value\" output format\n", out
);
150 fputs(" -J, --json use JSON output format\n", out
);
151 fputs(" -r, --raw use raw output format\n", out
);
152 fputs(" -S, --range-start <n> first line to print\n", out
);
153 fputs(" -E, --range-end <n> last line to print\n", out
);
155 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
158 int main(int argc
, char *argv
[])
160 struct libscols_table
*tb
;
161 int c
, notree
= 0, nstart
= -1, nend
= -1;
164 static const struct option longopts
[] = {
165 { "ascii", 0, NULL
, 'i' },
166 { "csv", 0, NULL
, 'c' },
167 { "list", 0, NULL
, 'l' },
168 { "noheadings", 0, NULL
, 'n' },
169 { "pairs", 0, NULL
, 'p' },
170 { "json", 0, NULL
, 'J' },
171 { "raw", 0, NULL
, 'r' },
172 { "range-start",1, NULL
, 'S' },
173 { "range-end", 1, NULL
, 'E' },
174 { NULL
, 0, NULL
, 0 },
177 setlocale(LC_ALL
, ""); /* just to have enable UTF8 chars */
181 tb
= scols_new_table();
183 err(EXIT_FAILURE
, "failed to create output table");
185 while((c
= getopt_long(argc
, argv
, "ciJlnprS:E:", longopts
, NULL
)) != -1) {
188 scols_table_set_column_separator(tb
, ",");
189 scols_table_enable_raw(tb
, 1);
193 scols_table_enable_ascii(tb
, 1);
196 scols_table_set_name(tb
, "scolstest");
197 scols_table_enable_json(tb
, 1);
203 scols_table_enable_noheadings(tb
, 1);
206 scols_table_enable_export(tb
, 1);
210 scols_table_enable_raw(tb
, 1);
214 nstart
= strtos32_or_err(optarg
, "failed to parse range start") - 1;
217 nend
= strtos32_or_err(optarg
, "failed to parse range end") - 1;
224 scols_table_enable_colors(tb
, isatty(STDOUT_FILENO
));
225 setup_columns(tb
, notree
);
229 else while (optind
< argc
)
230 add_lines(tb
, argv
[optind
++]);
232 if (nstart
>= 0 || nend
>= 0) {
234 struct libscols_line
*start
= NULL
, *end
= NULL
;
237 start
= scols_table_get_line(tb
, nstart
);
239 end
= scols_table_get_line(tb
, nend
);
242 scols_table_print_range(tb
, start
, end
);
244 /* print all table */
245 scols_print_table(tb
);
247 scols_unref_table(tb
);