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