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