]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libsmartcols/samples/tree.c
misc: Fix various typos
[thirdparty/util-linux.git] / libsmartcols / samples / tree.c
CommitLineData
3a29e909 1/*
3a29e909
OO
2 * Copyright (C) 2010-2014 Karel Zak <kzak@redhat.com>
3 *
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
6 */
3a29e909
OO
7#include <stdlib.h>
8#include <unistd.h>
9#include <string.h>
3a29e909 10#include <errno.h>
d9554c97
KZ
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <dirent.h>
14#include <getopt.h>
3a29e909
OO
15
16#include "c.h"
17#include "nls.h"
d9554c97 18#include "strutils.h"
3a29e909
OO
19
20#include "libsmartcols.h"
21
d9554c97
KZ
22static int add_children(struct libscols_table *tb,
23 struct libscols_line *ln, int fd);
24
25
26enum { COL_MODE, COL_SIZE, COL_NAME };
27
f92b26c1
KZ
28/* add columns to the @tb */
29static void setup_columns(struct libscols_table *tb, int notree)
d9554c97
KZ
30{
31 if (!scols_table_new_column(tb, "MODE", 0.3, 0))
32 goto fail;
33 if (!scols_table_new_column(tb, "SIZE", 5, SCOLS_FL_RIGHT))
34 goto fail;
35 if (!scols_table_new_column(tb, "NAME", 0.5,
36 (notree ? 0 : SCOLS_FL_TREE) | SCOLS_FL_NOEXTREMES))
37 goto fail;
38
39 return;
40fail:
41 scols_unref_table(tb);
9e930041 42 err(EXIT_FAILURE, "failed to create output columns");
d9554c97
KZ
43}
44
f92b26c1 45/* add a new line to @tb, the content is based on @st */
d9554c97
KZ
46static int add_line_from_stat(struct libscols_table *tb,
47 struct libscols_line *parent,
48 int parent_fd,
49 struct stat *st,
50 const char *name)
51{
52 struct libscols_line *ln;
53 char modbuf[11], *p;
54 mode_t mode = st->st_mode;
55 int rc = 0;
56
57 ln = scols_table_new_line(tb, parent);
58 if (!ln)
59 err(EXIT_FAILURE, "failed to create output line");
60
61 /* MODE; local buffer, use scols_line_set_data() that calls strdup() */
b0b24b11 62 xstrmode(mode, modbuf);
d9554c97
KZ
63 if (scols_line_set_data(ln, COL_MODE, modbuf))
64 goto fail;
65
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))
69 goto fail;
70
71 /* NAME */
72 if (scols_line_set_data(ln, COL_NAME, name))
73 goto fail;
74
75 /* colors */
76 if (scols_table_colors_wanted(tb)) {
77 struct libscols_cell *ce = scols_line_get_cell(ln, COL_NAME);
78
79 if (S_ISDIR(mode))
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");
87 }
88
89 if (S_ISDIR(st->st_mode)) {
90 int fd;
91
92 if (parent_fd >= 0)
93 fd = openat(parent_fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
94 else
95 fd = open(name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC);
96 if (fd >= 0) {
97 rc = add_children(tb, ln, fd);
98 close(fd);
99 }
100 }
101 return rc;
102fail:
103 err(EXIT_FAILURE, "failed to create cell data");
104 return -1;
105}
106
9e930041 107/* read all entries from directory addressed by @fd */
d9554c97
KZ
108static int add_children(struct libscols_table *tb,
109 struct libscols_line *ln,
110 int fd)
111{
112 DIR *dir;
113 struct dirent *d;
114
115 dir = fdopendir(fd);
116 if (!dir)
117 return -errno;
118
119 while ((d = readdir(dir))) {
120 struct stat st;
121
122 if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0)
123 continue;
124 if (fstatat(fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0)
125 continue;
126 add_line_from_stat(tb, ln, fd, &st, d->d_name);
127 }
128 closedir(dir);
129 return 0;
130}
131
132static void add_lines(struct libscols_table *tb, const char *dirname)
133{
134 struct stat st;
135
136 if (lstat(dirname, &st))
137 err(EXIT_FAILURE, "%s", dirname);
138
139 add_line_from_stat(tb, NULL, -1, &st, dirname);
140}
141
142static void __attribute__((__noreturn__)) usage(FILE *out)
143{
f92b26c1 144 fprintf(out, " %s [options] [<dir> ...]\n\n", program_invocation_short_name);
2a750b4c
KZ
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);
d9554c97
KZ
154
155 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
156}
3a29e909
OO
157
158int main(int argc, char *argv[])
159{
160 struct libscols_table *tb;
2a750b4c
KZ
161 int c, notree = 0, nstart = -1, nend = -1;
162
d9554c97
KZ
163
164 static const struct option longopts[] = {
d9554c97 165 { "ascii", 0, 0, 'i' },
d1b4d14f 166 { "csv", 0, 0, 'c' },
f92b26c1
KZ
167 { "list", 0, 0, 'l' },
168 { "noheadings", 0, 0, 'n' },
169 { "pairs", 0, 0, 'p' },
6f273796
KZ
170 { "json", 0, 0, 'J' },
171 { "raw", 0, 0, 'r' },
2a750b4c
KZ
172 { "range-start",1, 0, 'S' },
173 { "range-end", 1, 0, 'E' },
d9554c97
KZ
174 { NULL, 0, 0, 0 },
175 };
8a38a8d3 176
f92b26c1 177 setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */
71dbc865 178
4418714f
KZ
179 scols_init_debug(0);
180
71dbc865 181 tb = scols_new_table();
8a38a8d3 182 if (!tb)
9e930041 183 err(EXIT_FAILURE, "failed to create output table");
d9554c97 184
2a750b4c 185 while((c = getopt_long(argc, argv, "ciJlnprS:E:", longopts, NULL)) != -1) {
d9554c97 186 switch(c) {
f92b26c1
KZ
187 case 'c':
188 scols_table_set_column_separator(tb, ",");
189 scols_table_enable_raw(tb, 1);
190 notree = 1;
191 break;
192 case 'i':
193 scols_table_enable_ascii(tb, 1);
d9554c97 194 break;
6f273796
KZ
195 case 'J':
196 scols_table_set_name(tb, "scolstest");
197 scols_table_enable_json(tb, 1);
198 break;
d9554c97
KZ
199 case 'l':
200 notree = 1;
201 break;
202 case 'n':
203 scols_table_enable_noheadings(tb, 1);
204 break;
205 case 'p':
206 scols_table_enable_export(tb, 1);
207 notree = 1;
208 break;
d9554c97
KZ
209 case 'r':
210 scols_table_enable_raw(tb, 1);
211 notree = 1;
212 break;
2a750b4c
KZ
213 case 'S':
214 nstart = strtos32_or_err(optarg, "failed to parse range start") - 1;
215 break;
216 case 'E':
217 nend = strtos32_or_err(optarg, "failed to parse range end") - 1;
218 break;
d9554c97
KZ
219 default:
220 usage(stderr);
221 }
3a29e909
OO
222 }
223
d9554c97 224 scols_table_enable_colors(tb, 1);
f92b26c1 225 setup_columns(tb, notree);
3a29e909 226
2f09ae9d
KZ
227 if (optind == argc)
228 add_lines(tb, ".");
229 else while (optind < argc)
d9554c97 230 add_lines(tb, argv[optind++]);
3a29e909 231
2a750b4c
KZ
232 if (nstart >= 0 || nend >= 0) {
233 /* print subset */
234 struct libscols_line *start = NULL, *end = NULL;
235
236 if (nstart >= 0)
237 start = scols_table_get_line(tb, nstart);
238 if (nend >= 0)
239 end = scols_table_get_line(tb, nend);
3a29e909 240
2a750b4c
KZ
241 if (start || end)
242 scols_table_print_range(tb, start, end);
243 } else
244 /* print all table */
245 scols_print_table(tb);
246
247 scols_unref_table(tb);
3a29e909
OO
248 return EXIT_SUCCESS;
249}