This source file includes following definitions.
- parse_format_name_argument
- parse_command_line
- my_itoa
- symbolic_uid
- symbolic_gid
- string_date
- message
- yaml_dump_stbuf
- yaml_dump_string
- yaml_dump_record
- ls_dump_stbuf
- ls_dump_record
- process_ls_line
- process_input
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <config.h>
37
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #include "lib/global.h"
42
43 #include "lib/vfs/utilvfs.h"
44 #include "lib/util.h"
45 #include "lib/strutil.h"
46 #include "lib/timefmt.h"
47 #include "lib/widget.h"
48
49
50
51
52
53
54
55 typedef enum
56 {
57 FORMAT_YAML,
58 FORMAT_LS
59 } output_format_t;
60
61
62
63 static gboolean parse_format_name_argument (const gchar *option_name, const gchar *value,
64 gpointer data, GError **error);
65
66
67
68
69 static gboolean opt_drop_mtime = FALSE;
70 static gboolean opt_drop_ids = FALSE;
71 static gboolean opt_symbolic_ids = FALSE;
72 static output_format_t opt_output_format = FORMAT_LS;
73
74
75 static int error_count = 0;
76
77 static GOptionEntry entries[] = {
78 {
79 "drop-mtime",
80 0,
81 0,
82 G_OPTION_ARG_NONE,
83 &opt_drop_mtime,
84 "Don't include mtime in the output.",
85 NULL,
86 },
87 {
88 "drop-ids",
89 0,
90 0,
91 G_OPTION_ARG_NONE,
92 &opt_drop_ids,
93 "Don't include uid/gid in the output.",
94 NULL,
95 },
96 {
97 "symbolic-ids",
98 0,
99 0,
100 G_OPTION_ARG_NONE,
101 &opt_symbolic_ids,
102 "Print the strings '<<uid>>'/'<<gid>>' instead of the numeric IDs when they match the "
103 "process' uid/gid.",
104 NULL,
105 },
106 {
107 "format",
108 'f',
109 0,
110 G_OPTION_ARG_CALLBACK,
111 parse_format_name_argument,
112 "Output format. Default: ls.",
113 "<ls|yaml>",
114 },
115 G_OPTION_ENTRY_NULL,
116 };
117
118
119
120
121
122
123
124
125
126 static gboolean
127 parse_format_name_argument (const gchar *option_name, const gchar *value, gpointer data,
128 GError **error)
129 {
130 (void) option_name;
131 (void) data;
132
133 if (strcmp (value, "yaml") == 0)
134 opt_output_format = FORMAT_YAML;
135 else if (strcmp (value, "ls") == 0)
136 opt_output_format = FORMAT_LS;
137 else
138 {
139 g_set_error (error, MC_ERROR, G_OPTION_ERROR_FAILED, "unknown output format '%s'", value);
140 return FALSE;
141 }
142
143 return TRUE;
144 }
145
146
147
148 static gboolean
149 parse_command_line (int *argc, char **argv[])
150 {
151 GError *error = NULL;
152 GOptionContext *context;
153
154 context = g_option_context_new ("- Parses its input, which is expected to be in a format "
155 "similar to 'ls -l', and writes the result to stdout.");
156 g_option_context_add_main_entries (context, entries, NULL);
157 if (!g_option_context_parse (context, argc, argv, &error))
158 {
159 g_print ("option parsing failed: %s\n", error->message);
160 g_error_free (error);
161
162 return FALSE;
163 }
164
165 return TRUE;
166 }
167
168
169
170
171
172
173
174 static const char *
175 my_itoa (int i)
176 {
177 static char buf[BUF_SMALL];
178
179 sprintf (buf, "%d", i);
180 return buf;
181 }
182
183
184
185
186
187
188 static const char *
189 symbolic_uid (uid_t uid)
190 {
191 return (opt_symbolic_ids && uid == getuid ()) ? "<<uid>>" : my_itoa ((int) uid);
192 }
193
194
195
196 static const char *
197 symbolic_gid (gid_t gid)
198 {
199 return (opt_symbolic_ids && gid == getgid ()) ? "<<gid>>" : my_itoa ((int) gid);
200 }
201
202
203
204 static const char *
205 string_date (time_t t)
206 {
207 static char buf[BUF_SMALL];
208
209
210
211
212
213
214
215 FMT_LOCALTIME (buf, sizeof buf, "%Y-%m-%d %H:%M:%S", t);
216 return buf;
217 }
218
219
220
221
222
223
224
225
226
227 void
228 message (int flags, const char *title, const char *text, ...)
229 {
230 char *p;
231 va_list ap;
232
233 (void) flags;
234 (void) title;
235
236 va_start (ap, text);
237 p = g_strdup_vprintf (text, ap);
238 va_end (ap);
239 printf ("message(): vfs_parse_ls_lga(): parsing error at: %s\n", p);
240 g_free (p);
241 }
242
243
244
245
246
247
248
249 static void
250 yaml_dump_stbuf (const struct stat *st)
251 {
252
253 printf (" perm: %s\n", string_perm (st->st_mode));
254 if (!opt_drop_ids)
255 {
256 printf (" uid: %s\n", symbolic_uid (st->st_uid));
257 printf (" gid: %s\n", symbolic_gid (st->st_gid));
258 }
259 printf (" size: %" PRIuMAX "\n", (uintmax_t) st->st_size);
260 printf (" nlink: %d\n", (int) st->st_nlink);
261 if (!opt_drop_mtime)
262 printf (" mtime: %s\n", string_date (st->st_mtime));
263 }
264
265
266
267 static void
268 yaml_dump_string (const char *name, const char *val)
269 {
270 char *q;
271
272 q = g_shell_quote (val);
273 printf (" %s: %s\n", name, q);
274 g_free (q);
275 }
276
277
278
279 static void
280 yaml_dump_record (gboolean success, const char *input_line, const struct stat *st,
281 const char *filename, const char *linkname)
282 {
283 printf ("-\n");
284
285 if (success)
286 {
287 if (filename != NULL)
288 yaml_dump_string ("name", filename);
289 if (linkname != NULL)
290 yaml_dump_string ("linkname", linkname);
291 yaml_dump_stbuf (st);
292 }
293 else
294 {
295 yaml_dump_string ("cannot parse input line", input_line);
296 }
297 }
298
299
300
301
302
303
304
305 static void
306 ls_dump_stbuf (const struct stat *st)
307 {
308
309 printf ("%s %3d ", string_perm (st->st_mode), (int) st->st_nlink);
310 if (!opt_drop_ids)
311 {
312 printf ("%8s ", symbolic_uid (st->st_uid));
313 printf ("%8s ", symbolic_gid (st->st_gid));
314 }
315 printf ("%10" PRIuMAX " ", (uintmax_t) st->st_size);
316 if (!opt_drop_mtime)
317 printf ("%s ", string_date (st->st_mtime));
318 }
319
320
321
322 static void
323 ls_dump_record (gboolean success, const char *input_line, const struct stat *st,
324 const char *filename, const char *linkname)
325 {
326 if (success)
327 {
328 ls_dump_stbuf (st);
329 if (filename != NULL)
330 printf ("%s", filename);
331 if (linkname != NULL)
332 printf (" -> %s", linkname);
333 printf ("\n");
334 }
335 else
336 {
337 printf ("cannot parse input line: '%s'\n", input_line);
338 }
339 }
340
341
342
343
344
345
346
347 static void
348 process_ls_line (const char *line)
349 {
350 struct stat st;
351 char *filename, *linkname;
352 gboolean success;
353
354 memset (&st, 0, sizeof st);
355 filename = NULL;
356 linkname = NULL;
357
358 success = vfs_parse_ls_lga (line, &st, &filename, &linkname, NULL);
359
360 if (!success)
361 error_count++;
362
363 if (opt_output_format == FORMAT_YAML)
364 yaml_dump_record (success, line, &st, filename, linkname);
365 else
366 ls_dump_record (success, line, &st, filename, linkname);
367
368 g_free (filename);
369 g_free (linkname);
370 }
371
372
373
374 static void
375 process_input (FILE *input)
376 {
377 char line[BUF_4K];
378
379 while (fgets (line, sizeof line, input) != NULL)
380 {
381 str_rstrip_eol (line);
382 if (strncmp (line, "total ", 6) == 0)
383 continue;
384 process_ls_line (line);
385 }
386 }
387
388
389
390 int
391 main (int argc, char *argv[])
392 {
393 FILE *input;
394
395 if (!parse_command_line (&argc, &argv))
396 return EXIT_FAILURE;
397
398 if (argc >= 2)
399 {
400 input = fopen (argv[1], "r");
401 if (input == NULL)
402 {
403 perror (argv[1]);
404 return EXIT_FAILURE;
405 }
406 }
407 else
408 {
409 input = stdin;
410 }
411
412 process_input (input);
413
414 return (error_count > 0) ? EXIT_FAILURE : EXIT_SUCCESS;
415 }
416
417