xref: /aosp_15_r20/external/toybox/toys/other/readlink.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* readlink.c - Return string representation of a symbolic link.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2007 Rob Landley <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker 
5*cf5a6c84SAndroid Build Coastguard Worker USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
6*cf5a6c84SAndroid Build Coastguard Worker USE_REALPATH(NEWTOY(realpath, "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]", TOYFLAG_USR|TOYFLAG_BIN))
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker config READLINK
9*cf5a6c84SAndroid Build Coastguard Worker   bool "readlink"
10*cf5a6c84SAndroid Build Coastguard Worker   default y
11*cf5a6c84SAndroid Build Coastguard Worker   help
12*cf5a6c84SAndroid Build Coastguard Worker     usage: readlink [-efmnqz] FILE...
13*cf5a6c84SAndroid Build Coastguard Worker 
14*cf5a6c84SAndroid Build Coastguard Worker     With no options, show what symlink points to, return error if not symlink.
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker     Options for producing canonical paths (all symlinks/./.. resolved):
17*cf5a6c84SAndroid Build Coastguard Worker 
18*cf5a6c84SAndroid Build Coastguard Worker     -e	Canonical path to existing entry (fail if missing)
19*cf5a6c84SAndroid Build Coastguard Worker     -f	Full path (fail if directory missing)
20*cf5a6c84SAndroid Build Coastguard Worker     -m	Ignore missing entries, show where it would be
21*cf5a6c84SAndroid Build Coastguard Worker     -n	No trailing newline
22*cf5a6c84SAndroid Build Coastguard Worker     -q	Quiet (no error messages)
23*cf5a6c84SAndroid Build Coastguard Worker     -z	NUL instead of newline
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker config REALPATH
26*cf5a6c84SAndroid Build Coastguard Worker   bool "realpath"
27*cf5a6c84SAndroid Build Coastguard Worker   default y
28*cf5a6c84SAndroid Build Coastguard Worker   help
29*cf5a6c84SAndroid Build Coastguard Worker     usage: realpath [-LPemqsz] [--relative-base DIR] [-R DIR] FILE...
30*cf5a6c84SAndroid Build Coastguard Worker 
31*cf5a6c84SAndroid Build Coastguard Worker     Display the canonical absolute pathname
32*cf5a6c84SAndroid Build Coastguard Worker 
33*cf5a6c84SAndroid Build Coastguard Worker     -R Show ../path relative to DIR (--relative-to)
34*cf5a6c84SAndroid Build Coastguard Worker     -L Logical path (resolve .. before symlinks)
35*cf5a6c84SAndroid Build Coastguard Worker     -P Physical path (default)
36*cf5a6c84SAndroid Build Coastguard Worker     -e Canonical path to existing entry (fail if missing)
37*cf5a6c84SAndroid Build Coastguard Worker     -m Ignore missing entries, show where it would be
38*cf5a6c84SAndroid Build Coastguard Worker     -q Quiet (no error messages)
39*cf5a6c84SAndroid Build Coastguard Worker     -s Don't expand symlinks
40*cf5a6c84SAndroid Build Coastguard Worker     -z NUL instead of newline
41*cf5a6c84SAndroid Build Coastguard Worker     --relative-base  If path under DIR trim off prefix
42*cf5a6c84SAndroid Build Coastguard Worker */
43*cf5a6c84SAndroid Build Coastguard Worker 
44*cf5a6c84SAndroid Build Coastguard Worker #define FOR_realpath
45*cf5a6c84SAndroid Build Coastguard Worker #define FORCE_FLAGS
46*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
47*cf5a6c84SAndroid Build Coastguard Worker 
48*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
49*cf5a6c84SAndroid Build Coastguard Worker   char *R, *relative_base;
50*cf5a6c84SAndroid Build Coastguard Worker )
51*cf5a6c84SAndroid Build Coastguard Worker 
52*cf5a6c84SAndroid Build Coastguard Worker // test TT.relative_base -RsmLP
53*cf5a6c84SAndroid Build Coastguard Worker // Trim .. out early for -s and -L. TODO: in place in the input string.
54*cf5a6c84SAndroid Build Coastguard Worker 
resolve(char * arg)55*cf5a6c84SAndroid Build Coastguard Worker static char *resolve(char *arg)
56*cf5a6c84SAndroid Build Coastguard Worker {
57*cf5a6c84SAndroid Build Coastguard Worker   int flags = FLAG(e) ? ABS_FILE : FLAG(m) ? 0 : ABS_PATH;
58*cf5a6c84SAndroid Build Coastguard Worker   char *s, *ss = 0, *dd = 0;
59*cf5a6c84SAndroid Build Coastguard Worker 
60*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(s)) flags |= ABS_KEEP;
61*cf5a6c84SAndroid Build Coastguard Worker   else if (FLAG(L)) arg = dd = xabspath(arg, ABS_KEEP);
62*cf5a6c84SAndroid Build Coastguard Worker   if (!(s = xabspath(arg, flags)) && !FLAG(q)) perror_msg_raw(arg);
63*cf5a6c84SAndroid Build Coastguard Worker   free(dd);
64*cf5a6c84SAndroid Build Coastguard Worker 
65*cf5a6c84SAndroid Build Coastguard Worker   // Trim off this prefix if path under here
66*cf5a6c84SAndroid Build Coastguard Worker 
67*cf5a6c84SAndroid Build Coastguard Worker   if (TT.relative_base) {
68*cf5a6c84SAndroid Build Coastguard Worker     ss = s;
69*cf5a6c84SAndroid Build Coastguard Worker     if (strstart(&ss, TT.relative_base) && (!*ss || *ss=='/')) {
70*cf5a6c84SAndroid Build Coastguard Worker       if (*ss=='/') ss++;
71*cf5a6c84SAndroid Build Coastguard Worker       ss = xstrdup(!*ss ? "." : ss);
72*cf5a6c84SAndroid Build Coastguard Worker     } else ss = 0;
73*cf5a6c84SAndroid Build Coastguard Worker   } else if (TT.R) ss = relative_path(TT.R, s, 0);
74*cf5a6c84SAndroid Build Coastguard Worker   if (ss) {
75*cf5a6c84SAndroid Build Coastguard Worker     free(s);
76*cf5a6c84SAndroid Build Coastguard Worker     s = ss;
77*cf5a6c84SAndroid Build Coastguard Worker   }
78*cf5a6c84SAndroid Build Coastguard Worker 
79*cf5a6c84SAndroid Build Coastguard Worker   return s;
80*cf5a6c84SAndroid Build Coastguard Worker }
81*cf5a6c84SAndroid Build Coastguard Worker 
82*cf5a6c84SAndroid Build Coastguard Worker // Resolve command line arguments that can't take part in their own resolution
presolve(char ** s)83*cf5a6c84SAndroid Build Coastguard Worker static char *presolve(char **s)
84*cf5a6c84SAndroid Build Coastguard Worker {
85*cf5a6c84SAndroid Build Coastguard Worker   char *ss = *s;
86*cf5a6c84SAndroid Build Coastguard Worker 
87*cf5a6c84SAndroid Build Coastguard Worker   if (ss) {
88*cf5a6c84SAndroid Build Coastguard Worker     *s = 0;
89*cf5a6c84SAndroid Build Coastguard Worker     if (!(*s = resolve(ss))) xexit();
90*cf5a6c84SAndroid Build Coastguard Worker   }
91*cf5a6c84SAndroid Build Coastguard Worker 
92*cf5a6c84SAndroid Build Coastguard Worker   return ss;
93*cf5a6c84SAndroid Build Coastguard Worker }
94*cf5a6c84SAndroid Build Coastguard Worker 
95*cf5a6c84SAndroid Build Coastguard Worker // Uses realpath flag context: flags (1 = resolve, 2 = -n)
do_paths(int flags)96*cf5a6c84SAndroid Build Coastguard Worker static void do_paths(int flags)
97*cf5a6c84SAndroid Build Coastguard Worker {
98*cf5a6c84SAndroid Build Coastguard Worker   char **arg, *s;
99*cf5a6c84SAndroid Build Coastguard Worker 
100*cf5a6c84SAndroid Build Coastguard Worker   if (!presolve(&TT.relative_base)) presolve(&TT.R);
101*cf5a6c84SAndroid Build Coastguard Worker 
102*cf5a6c84SAndroid Build Coastguard Worker   for (arg = toys.optargs; *arg; arg++) {
103*cf5a6c84SAndroid Build Coastguard Worker     if (!(s = (flags&1) ? resolve(*arg) : xreadlink(*arg))) toys.exitval = 1;
104*cf5a6c84SAndroid Build Coastguard Worker     else xprintf(((flags&2) && !arg[1]) ? "%s" : "%s%c", s, '\n'*!FLAG(z));
105*cf5a6c84SAndroid Build Coastguard Worker     free(s);
106*cf5a6c84SAndroid Build Coastguard Worker   }
107*cf5a6c84SAndroid Build Coastguard Worker }
108*cf5a6c84SAndroid Build Coastguard Worker 
realpath_main(void)109*cf5a6c84SAndroid Build Coastguard Worker void realpath_main(void)
110*cf5a6c84SAndroid Build Coastguard Worker {
111*cf5a6c84SAndroid Build Coastguard Worker   do_paths(1);
112*cf5a6c84SAndroid Build Coastguard Worker }
113*cf5a6c84SAndroid Build Coastguard Worker 
114*cf5a6c84SAndroid Build Coastguard Worker #define FOR_readlink
115*cf5a6c84SAndroid Build Coastguard Worker #include "generated/flags.h"
116*cf5a6c84SAndroid Build Coastguard Worker 
117*cf5a6c84SAndroid Build Coastguard Worker // Convert readlink flag context to realpath (feeding in -nf separately)
readlink_main(void)118*cf5a6c84SAndroid Build Coastguard Worker void readlink_main(void)
119*cf5a6c84SAndroid Build Coastguard Worker {
120*cf5a6c84SAndroid Build Coastguard Worker   int nf = (toys.optflags/FLAG_f)|!!(FLAG(m)|FLAG(e));
121*cf5a6c84SAndroid Build Coastguard Worker 
122*cf5a6c84SAndroid Build Coastguard Worker   toys.optflags &= FLAG_f-1;
123*cf5a6c84SAndroid Build Coastguard Worker   if (!FLAG(v)) toys.optflags |= FLAG_q;
124*cf5a6c84SAndroid Build Coastguard Worker   do_paths(nf);
125*cf5a6c84SAndroid Build Coastguard Worker }
126