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