]>
Commit | Line | Data |
---|---|---|
4b486ee8 ZJS |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #include <getopt.h> | |
3 | ||
38c569bb | 4 | #include "fd-util.h" |
4b486ee8 | 5 | #include "fs-util.h" |
38c569bb | 6 | #include "log.h" |
4b486ee8 ZJS |
7 | #include "main-func.h" |
8 | ||
9 | static char *arg_root = NULL; | |
10 | static int arg_flags = 0; | |
11 | ||
12 | static int parse_argv(int argc, char *argv[]) { | |
13 | enum { | |
14 | ARG_ROOT = 0x1000, | |
15 | }; | |
16 | ||
17 | static const struct option options[] = { | |
18 | { "help", no_argument, NULL, 'h' }, | |
19 | { "root", required_argument, NULL, ARG_ROOT }, | |
20 | ||
21 | { "prefix-root", no_argument, NULL, CHASE_PREFIX_ROOT }, | |
22 | { "nonexistent", no_argument, NULL, CHASE_NONEXISTENT }, | |
23 | { "no_autofs", no_argument, NULL, CHASE_NO_AUTOFS }, | |
24 | { "safe", no_argument, NULL, CHASE_SAFE }, | |
25 | { "open", no_argument, NULL, CHASE_OPEN }, | |
26 | { "trail-slash", no_argument, NULL, CHASE_TRAIL_SLASH }, | |
27 | { "step", no_argument, NULL, CHASE_STEP }, | |
28 | { "nofollow", no_argument, NULL, CHASE_NOFOLLOW }, | |
29 | { "warn", no_argument, NULL, CHASE_WARN }, | |
30 | {} | |
31 | }; | |
32 | ||
33 | int c; | |
34 | ||
35 | assert(argc >= 0); | |
36 | assert(argv); | |
37 | ||
38 | while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) | |
39 | switch (c) { | |
40 | ||
41 | case 'h': | |
42 | printf("Syntax:\n" | |
43 | " %s [OPTION...] path...\n" | |
44 | "Options:\n" | |
45 | , argv[0]); | |
46 | for (size_t i = 0; i < ELEMENTSOF(options) - 1; i++) | |
47 | printf(" --%s\n", options[i].name); | |
48 | return 0; | |
49 | ||
50 | case ARG_ROOT: | |
51 | arg_root = optarg; | |
52 | break; | |
53 | ||
54 | case CHASE_PREFIX_ROOT: | |
55 | case CHASE_NONEXISTENT: | |
56 | case CHASE_NO_AUTOFS: | |
57 | case CHASE_SAFE: | |
58 | case CHASE_OPEN: | |
59 | case CHASE_TRAIL_SLASH: | |
60 | case CHASE_STEP: | |
61 | case CHASE_NOFOLLOW: | |
62 | case CHASE_WARN: | |
63 | arg_flags |= c; | |
64 | break; | |
65 | ||
66 | case '?': | |
67 | return -EINVAL; | |
68 | ||
69 | default: | |
70 | assert_not_reached("Unhandled option"); | |
71 | } | |
72 | ||
73 | if (optind == argc) | |
74 | return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At least one argument is required."); | |
75 | ||
76 | return 1; | |
77 | } | |
78 | ||
79 | static int run(int argc, char **argv) { | |
80 | int r; | |
81 | ||
82 | log_show_color(true); | |
83 | log_parse_environment(); | |
84 | log_open(); | |
85 | ||
86 | r = parse_argv(argc, argv); | |
87 | if (r <= 0) | |
88 | return r; | |
89 | ||
90 | for (int i = optind; i < argc; i++) { | |
91 | _cleanup_free_ char *p = NULL; | |
92 | ||
93 | printf("%s ", argv[i]); | |
94 | fflush(stdout); | |
95 | ||
96 | r = chase_symlinks(argv[i], arg_root, arg_flags, &p); | |
97 | if (r < 0) | |
98 | log_error_errno(r, "failed: %m"); | |
99 | else | |
100 | log_info("→ %s", p); | |
38c569bb LP |
101 | |
102 | if (FLAGS_SET(arg_flags, CHASE_OPEN)) | |
103 | safe_close(r); | |
4b486ee8 ZJS |
104 | } |
105 | ||
106 | return 0; | |
107 | } | |
108 | ||
109 | DEFINE_MAIN_FUNCTION(run); |