|
@@ -2,9 +2,8 @@
|
|
|
*
|
|
|
* Copyright 2007 Rob Landley <rob@landley.net>
|
|
|
|
|
|
-// -ef positions match ABS_FILE ABS_PATH
|
|
|
-USE_READLINK(NEWTOY(readlink, "<1nqmef(canonicalize)[-mef]", TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
-USE_REALPATH(OLDTOY(realpath, readlink, TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
+USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
+USE_REALPATH(NEWTOY(realpath, "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]", TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
|
|
|
config READLINK
|
|
|
bool "readlink"
|
|
@@ -20,36 +19,97 @@ config READLINK
|
|
|
-f Full path (fail if directory missing)
|
|
|
-m Ignore missing entries, show where it would be
|
|
|
-n No trailing newline
|
|
|
- -q Quiet (no output, just error code)
|
|
|
+ -q Quiet (no error messages)
|
|
|
+ -z NUL instead of newline
|
|
|
|
|
|
config REALPATH
|
|
|
bool "realpath"
|
|
|
default y
|
|
|
help
|
|
|
- usage: realpath FILE...
|
|
|
+ usage: realpath [-LPemqsz] [--relative-base DIR] [-R DIR] FILE...
|
|
|
|
|
|
Display the canonical absolute pathname
|
|
|
+
|
|
|
+ -R Show ../path relative to DIR (--relative-to)
|
|
|
+ -L Logical path (resolve .. before symlinks)
|
|
|
+ -P Physical path (default)
|
|
|
+ -e Canonical path to existing entry (fail if missing)
|
|
|
+ -m Ignore missing entries, show where it would be
|
|
|
+ -q Quiet (no error messages)
|
|
|
+ -s Don't expand symlinks
|
|
|
+ -z NUL instead of newline
|
|
|
+ --relative-base Paths below DIR aren't absolute
|
|
|
*/
|
|
|
|
|
|
-#define FOR_readlink
|
|
|
+/* TODO
|
|
|
+# relative-to is affected by flags
|
|
|
+$ realpath --relative-to=nothing/potato .
|
|
|
+realpath: nothing/potato: No such file or directory
|
|
|
+$ realpath -m --relative-to=nothing/potato .
|
|
|
+../..
|
|
|
+
|
|
|
+# -L and -s are similar but not the same
|
|
|
+$ realpath -s --relative-to=. ccc
|
|
|
+ccc
|
|
|
+$ realpath -L --relative-to=. ccc
|
|
|
+../../mcm/ccc
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#define FOR_realpath
|
|
|
#define FORCE_FLAGS
|
|
|
+#define TT this.readlink // workaround: first FOR_ doesn't match filename
|
|
|
#include "toys.h"
|
|
|
|
|
|
-void readlink_main(void)
|
|
|
+GLOBALS(
|
|
|
+ char *R, *relative_base;
|
|
|
+)
|
|
|
+
|
|
|
+// test TT.relative_base -RsmLP
|
|
|
+// Trim .. out early for -s and -L. TODO: in place in the input string.
|
|
|
+
|
|
|
+static char *resolve(char *arg)
|
|
|
+{
|
|
|
+ int flags = FLAG(e) ? ABS_FILE : FLAG(m) ? 0 : ABS_PATH;
|
|
|
+ char *s;
|
|
|
+
|
|
|
+ if (FLAG(s)) flags |= ABS_KEEP;
|
|
|
+ if (!(s = xabspath(arg, flags)) && !FLAG(q)) perror_msg("%s", arg);
|
|
|
+
|
|
|
+ return s;
|
|
|
+}
|
|
|
+
|
|
|
+// Uses realpath flag context: flags (1 = resolve, 2 = -n)
|
|
|
+static void do_paths(int flags)
|
|
|
{
|
|
|
char **arg, *s;
|
|
|
|
|
|
- if (toys.which->name[3]=='l') toys.optflags |= FLAG_f;
|
|
|
+ if (TT.R && !(TT.R = resolve(TT.R))) xexit();
|
|
|
+ if (TT.relative_base && !(TT.relative_base = resolve(TT.relative_base)))
|
|
|
+ xexit();
|
|
|
+
|
|
|
for (arg = toys.optargs; *arg; arg++) {
|
|
|
- // Calculating full canonical path?
|
|
|
- // Take advantage of flag positions: m = 0, f = ABS_PATH, e = ABS_FILE
|
|
|
- if (toys.optflags & (FLAG_f|FLAG_e|FLAG_m))
|
|
|
- s = xabspath(*arg, toys.optflags&(FLAG_f|FLAG_e));
|
|
|
- else s = xreadlink(*arg);
|
|
|
-
|
|
|
- if (s) {
|
|
|
- if (!FLAG(q)) xprintf("%s%s", s, (FLAG(n) && !arg[1]) ? "" : "\n");
|
|
|
- free(s);
|
|
|
- } else toys.exitval = 1;
|
|
|
+ if (!(s = (flags&1) ? resolve(*arg) : xreadlink(*arg))) toys.exitval = 1;
|
|
|
+ else xprintf(((flags&2) && !arg[1]) ? "%s" : "%s%c", s, '\n'*!FLAG(z));
|
|
|
+ free(s);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+void realpath_main(void)
|
|
|
+{
|
|
|
+ do_paths(1);
|
|
|
+}
|
|
|
+
|
|
|
+#define FOR_readlink
|
|
|
+#include "generated/flags.h"
|
|
|
+
|
|
|
+// Convert readlink flag context to realpath (feeding in -nf separately)
|
|
|
+void readlink_main(void)
|
|
|
+{
|
|
|
+ int nf = (toys.optflags/FLAG_f)|!!(FLAG(m)|FLAG(e));
|
|
|
+
|
|
|
+ toys.optflags &= FLAG_f-1;
|
|
|
+ if (!FLAG(v)) toys.optflags |= FLAG_q;
|
|
|
+ do_paths(nf);
|
|
|
+}
|