summaryrefslogtreecommitdiff
path: root/src/test/test-chase-symlinks.c
blob: 013b36e2a7a5e502892343046574dc9d2313855a (plain)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <getopt.h>

#include "fd-util.h"
#include "fs-util.h"
#include "log.h"
#include "main-func.h"

static char *arg_root = NULL;
static int arg_flags = 0;

static int parse_argv(int argc, char *argv[]) {
        enum {
                ARG_ROOT = 0x1000,
        };

        static const struct option options[] = {
                { "help",                no_argument,       NULL, 'h'                     },
                { "root",                required_argument, NULL, ARG_ROOT                },

                { "prefix-root",         no_argument,       NULL, CHASE_PREFIX_ROOT       },
                { "nonexistent",         no_argument,       NULL, CHASE_NONEXISTENT       },
                { "no_autofs",           no_argument,       NULL, CHASE_NO_AUTOFS         },
                { "safe",                no_argument,       NULL, CHASE_SAFE              },
                { "open",                no_argument,       NULL, CHASE_OPEN              },
                { "trail-slash",         no_argument,       NULL, CHASE_TRAIL_SLASH       },
                { "step",                no_argument,       NULL, CHASE_STEP              },
                { "nofollow",            no_argument,       NULL, CHASE_NOFOLLOW          },
                { "warn",                no_argument,       NULL, CHASE_WARN              },
                {}
        };

        int c;

        assert(argc >= 0);
        assert(argv);

        while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0)
                switch (c) {

                case 'h':
                        printf("Syntax:\n"
                               "  %s [OPTION...] path...\n"
                               "Options:\n"
                               , argv[0]);
                        for (size_t i = 0; i < ELEMENTSOF(options) - 1; i++)
                                printf("  --%s\n", options[i].name);
                        return 0;

                case ARG_ROOT:
                        arg_root = optarg;
                        break;

                case CHASE_PREFIX_ROOT:
                case CHASE_NONEXISTENT:
                case CHASE_NO_AUTOFS:
                case CHASE_SAFE:
                case CHASE_OPEN:
                case CHASE_TRAIL_SLASH:
                case CHASE_STEP:
                case CHASE_NOFOLLOW:
                case CHASE_WARN:
                        arg_flags |= c;
                        break;

                case '?':
                        return -EINVAL;

                default:
                        assert_not_reached("Unhandled option");
                }

        if (optind == argc)
                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At least one argument is required.");

        return 1;
}

static int run(int argc, char **argv) {
        int r;

        log_show_color(true);
        log_parse_environment();
        log_open();

        r = parse_argv(argc, argv);
        if (r <= 0)
                return r;

        for (int i = optind; i < argc; i++) {
                _cleanup_free_ char *p = NULL;

                printf("%s ", argv[i]);
                fflush(stdout);

                r = chase_symlinks(argv[i], arg_root, arg_flags, &p);
                if (r < 0)
                        log_error_errno(r, "failed: %m");
                else
                        log_info("→ %s", p);

                if (FLAGS_SET(arg_flags, CHASE_OPEN))
                        safe_close(r);
        }

        return 0;
}

DEFINE_MAIN_FUNCTION(run);