Line data Source code
1 : /* readlink -- display value of a symbolic link.
2 : Copyright (C) 2002-2007 Free Software Foundation, Inc.
3 :
4 : This program is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation, either version 3 of the License, or
7 : (at your option) any later version.
8 :
9 : This program is distributed in the hope that it will be useful,
10 : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : GNU General Public License for more details.
13 :
14 : You should have received a copy of the GNU General Public License
15 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
16 :
17 : /* Written by Dmitry V. Levin */
18 :
19 : #include <config.h>
20 : #include <stdio.h>
21 : #include <getopt.h>
22 : #include <sys/types.h>
23 :
24 : #include "system.h"
25 : #include "canonicalize.h"
26 : #include "error.h"
27 : #include "areadlink.h"
28 : #include "quote.h"
29 :
30 : /* The official name of this program (e.g., no `g' prefix). */
31 : #define PROGRAM_NAME "readlink"
32 :
33 : #define AUTHORS "Dmitry V. Levin"
34 :
35 : /* Name this program was run with. */
36 : char *program_name;
37 :
38 : /* If true, do not output the trailing newline. */
39 : static bool no_newline;
40 :
41 : /* If true, report error messages. */
42 : static bool verbose;
43 :
44 : static struct option const longopts[] =
45 : {
46 : {"canonicalize", no_argument, NULL, 'f'},
47 : {"canonicalize-existing", no_argument, NULL, 'e'},
48 : {"canonicalize-missing", no_argument, NULL, 'm'},
49 : {"no-newline", no_argument, NULL, 'n'},
50 : {"quiet", no_argument, NULL, 'q'},
51 : {"silent", no_argument, NULL, 's'},
52 : {"verbose", no_argument, NULL, 'v'},
53 : {GETOPT_HELP_OPTION_DECL},
54 : {GETOPT_VERSION_OPTION_DECL},
55 : {NULL, 0, NULL, 0}
56 : };
57 :
58 : void
59 41 : usage (int status)
60 : {
61 41 : if (status != EXIT_SUCCESS)
62 40 : fprintf (stderr, _("Try `%s --help' for more information.\n"),
63 : program_name);
64 : else
65 : {
66 1 : printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
67 1 : fputs (_("Display value of a symbolic link on standard output.\n\n"),
68 : stdout);
69 1 : fputs (_("\
70 : -f, --canonicalize canonicalize by following every symlink in\n\
71 : every component of the given name recursively;\n\
72 : all but the last component must exist\n\
73 : -e, --canonicalize-existing canonicalize by following every symlink in\n\
74 : every component of the given name recursively,\n\
75 : all components must exist\n\
76 : "), stdout);
77 1 : fputs (_("\
78 : -m, --canonicalize-missing canonicalize by following every symlink in\n\
79 : every component of the given name recursively,\n\
80 : without requirements on components existence\n\
81 : -n, --no-newline do not output the trailing newline\n\
82 : -q, --quiet,\n\
83 : -s, --silent suppress most error messages\n\
84 : -v, --verbose report error messages\n\
85 : "), stdout);
86 1 : fputs (HELP_OPTION_DESCRIPTION, stdout);
87 1 : fputs (VERSION_OPTION_DESCRIPTION, stdout);
88 1 : emit_bug_reporting_address ();
89 : }
90 41 : exit (status);
91 : }
92 :
93 : int
94 64 : main (int argc, char **argv)
95 : {
96 : /* If not -1, use this method to canonicalize. */
97 64 : int can_mode = -1;
98 :
99 : /* File name to canonicalize. */
100 : const char *fname;
101 :
102 : /* Result of canonicalize. */
103 : char *value;
104 :
105 : int optc;
106 :
107 : initialize_main (&argc, &argv);
108 64 : program_name = argv[0];
109 64 : setlocale (LC_ALL, "");
110 : bindtextdomain (PACKAGE, LOCALEDIR);
111 : textdomain (PACKAGE);
112 :
113 64 : atexit (close_stdout);
114 :
115 160 : while ((optc = getopt_long (argc, argv, "efmnqsv", longopts, NULL)) != -1)
116 : {
117 40 : switch (optc)
118 : {
119 19 : case 'e':
120 19 : can_mode = CAN_EXISTING;
121 19 : break;
122 5 : case 'f':
123 5 : can_mode = CAN_ALL_BUT_LAST;
124 5 : break;
125 1 : case 'm':
126 1 : can_mode = CAN_MISSING;
127 1 : break;
128 2 : case 'n':
129 2 : no_newline = true;
130 2 : break;
131 2 : case 'q':
132 : case 's':
133 2 : verbose = false;
134 2 : break;
135 3 : case 'v':
136 3 : verbose = true;
137 3 : break;
138 1 : case_GETOPT_HELP_CHAR;
139 1 : case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
140 6 : default:
141 6 : usage (EXIT_FAILURE);
142 : }
143 : }
144 :
145 56 : if (optind >= argc)
146 : {
147 12 : error (0, 0, _("missing operand"));
148 12 : usage (EXIT_FAILURE);
149 : }
150 :
151 44 : fname = argv[optind++];
152 :
153 44 : if (optind < argc)
154 : {
155 22 : error (0, 0, _("extra operand %s"), quote (argv[optind]));
156 22 : usage (EXIT_FAILURE);
157 : }
158 :
159 22 : value = (can_mode != -1
160 15 : ? canonicalize_filename_mode (fname, can_mode)
161 37 : : areadlink_with_size (fname, 63));
162 22 : if (value)
163 : {
164 14 : printf ("%s%s", value, (no_newline ? "" : "\n"));
165 14 : free (value);
166 14 : return EXIT_SUCCESS;
167 : }
168 :
169 8 : if (verbose)
170 2 : error (EXIT_FAILURE, errno, "%s", fname);
171 :
172 6 : return EXIT_FAILURE;
173 : }
|