---
Makefile | 5 +--
readlink.1 | 52 +++++++++++++++++++----------
readlink.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
realpath.1 | 16 +++++++++
4 files changed, 141 insertions(+), 43 deletions(-)
create mode 100644 realpath.1
diff --git a/Makefile b/Makefile
index c4ca41d..93babdd 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -190,7 +190,7 @@ $(LIBUTIL): $(LIBUTILOBJ)
install: all
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f $(BIN) $(DESTDIR)$(PREFIX)/bin
- cd $(DESTDIR)$(PREFIX)/bin && ln -f test [ && chmod 755 $(BIN)
+ cd $(DESTDIR)$(PREFIX)/bin && ln -f readlink realpath && ln -f test [ && chmod 755 $(BIN)
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
for m in $(MAN); do sed "s/^\.Os sbase/.Os sbase $(VERSION)/g" < "$$m" > $(DESTDIR)$(MANPREFIX)/man1/"$$m"; done
cd $(DESTDIR)$(MANPREFIX)/man1 && chmod 644 $(MAN)
_AT_@ -219,8 +219,9 @@ sbase-box: $(LIB) $(SRC)
echo 'int main(int argc, char *argv[]) { char *s = basename(argv[0]);' >> build/$_AT_.c
echo 'if(!strcmp(s,"sbase-box")) { argc--; argv++; s = basename(argv[0]); } if(0) ;' >> build/$_AT_.c
echo "else if (!strcmp(s, \"[\")) return test_main(argc, argv);" >> build/$_AT_.c
+ echo "else if (!strcmp(s, \"realpath\")) return readlink_main(argc, argv);" >> build/$_AT_.c
for f in $(SRC); do echo "else if(!strcmp(s, \"$${f%.c}\")) return $${f%.c}_main(argc, argv);"; done >> build/$_AT_.c
- echo 'else { fputs("[ ", stdout);' >> build/$_AT_.c
+ echo 'else { fputs("[ realpath ", stdout);' >> build/$_AT_.c
for f in $(SRC); do echo "fputs(\"$${f%.c} \", stdout);"; done >> build/$_AT_.c
echo 'putchar(0xa); }; return 0; }' >> build/$_AT_.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $_AT_ build/*.c $(LIB)
diff --git a/readlink.1 b/readlink.1
index 46b4cad..3de0855 100644
--- a/readlink.1
+++ b/readlink.1
_AT_@ -1,32 +1,48 @@
-.Dd 2015-11-16
+.Dd 2015-11-14
.Dt READLINK 1
.Os sbase
.Sh NAME
.Nm readlink
-.Nd print symbolic link target or canonical file name
+.Nd Print symbolic link targets or canonical paths
.Sh SYNOPSIS
.Nm
-.Op Fl f
-.Op Fl n
-.Ar path
+.Op Fl e | f | m
+.Op Fl n | z
+.Op Fl q
+.Ar file
+.Op file ...
.Sh DESCRIPTION
.Nm
-writes the target of
-.Ar path ,
-if it is a symbolic link, to stdout.
-If not,
+prints the target of each
+.Ar file
+which must be an existing symbolic link. With the
+.Fl e, f,
+or
+.Fl m
+flags,
.Nm
-exits with a non-zero return value.
+instead prints a canonicalized path.
.Sh OPTIONS
.Bl -tag -width Ds
-.It Fl f
-Canonicalize
-.Ar path ,
-which needn't be a symlink,
-by recursively following every symlink in its path components.
-.It Fl n
-Do not print the terminating newline.
+.It Fl e | f | m
+All | All but the last | None of the path components must exist.
+.Fl f
+is identical to
+.Xr realpath 1
+behavior.
+.It Fl n | Fl z
+Nothing | NUL is printed after each resolved path. By default, a newline is
+printed.
+.It Fl q
+Suppress error messages. Exit status will indicate if errors were encountered.
.El
+.Sh EXIT STATUS
+.Bl -tag -width Ds
+.It 0
+All paths were successfully resolved.
+.It 1
+An error was encountered resolving at least one of the given paths.
.Sh SEE ALSO
-.Xr readlink 2 ,
+.Xr readlink 3
.Xr realpath 3
+.Xr realpath 1
diff --git a/readlink.c b/readlink.c
index d059584..731b580 100644
--- a/readlink.c
+++ b/readlink.c
_AT_@ -1,54 +1,119 @@
/* See LICENSE file for copyright and license details. */
+#include <sys/stat.h>
+#include <errno.h>
+#include <libgen.h>
#include <limits.h>
-#include <stdio.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
+static int efmflag = 0;
+static int nflag = 0;
+static int qflag = 0;
+static int zflag = 0;
+
static void
usage(void)
{
- eprintf("usage: %s [-fn] path\n", argv0);
+ eprintf("usage: %s [-e | -f | -m] [-z | -n] [-q] file [file ...]\n", argv0);
}
int
main(int argc, char *argv[])
{
- char buf[PATH_MAX];
- ssize_t n;
- int nflag = 0, fflag = 0;
+ int i, n, e = 0, ret = 0;
+ char rp[PATH_MAX], le, *p;
+ struct stat s;
+
+ if (!strcmp(basename(argv[0]), "realpath"))
+ efmflag = 'f';
+ else
+ efmflag = 'L';
ARGBEGIN {
+ case 'e':
case 'f':
- fflag = ARGC();
+ case 'm':
+ efmflag = ARGC();
break;
case 'n':
nflag = 1;
break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'z':
+ zflag = 1;
+ break;
default:
usage();
} ARGEND
- if (argc != 1)
+ if (!argc)
usage();
- if (strlen(argv[0]) >= PATH_MAX)
- eprintf("path too long\n");
-
- if (fflag) {
- if (!realpath(argv[0], buf))
- eprintf("realpath %s:", argv[0]);
- } else {
- if ((n = readlink(argv[0], buf, PATH_MAX - 1)) < 0)
- eprintf("readlink %s:", argv[0]);
- buf[n] = '\0';
+ if (zflag)
+ le = '\0';
+ else if (!nflag)
+ le = '\n';
+ for (i = 0; i < argc; i++) {
+ switch (efmflag) {
+ case 'e':
+ if (!realpath(argv[i], rp)) {
+ if (!qflag)
+ weprintf("realpath '%s':", argv[i]);
+ e = 1;
+ }
+ break;
+ case 'm':
+ if (!realpathm(argv[i], rp)) {
+ if (!qflag)
+ weprintf("realpathm '%s':", argv[i]);
+ e = 1;
+ }
+ break;
+ case 'f':
+ if (!realpathm(argv[i], rp)) {
+ if (!qflag)
+ weprintf("realpathm '%s':", argv[i]);
+ e = 1;
+ } else {
+ p = strrchr(rp, '/');
+ if (p == rp)
+ p = NULL;
+ }
+ if (p) {
+ *p = '\0';
+ if (stat(rp, &s) < 0) {
+ if (!qflag)
+ weprintf("stat '%s':", rp);
+ e = 1;
+ break;
+ } else {
+ *p = '/';
+ }
+ }
+ break;
+ case 'L':
+ if ((n = readlink(argv[i], rp, PATH_MAX-1)) < 0) {
+ if (!qflag)
+ weprintf("readlink '%s':", argv[i]);
+ e = 1;
+ } else {
+ rp[n] = '\0';
+ }
+ break;
+ }
+ if (e) {
+ ret = 1;
+ e = 0;
+ } else {
+ fputs(rp, stdout);
+ putchar(le);
+ }
}
-
- fputs(buf, stdout);
- if (!nflag)
- putchar('\n');
-
- return fshut(stdout, "<stdout>");
+ return ret;
}
diff --git a/realpath.1 b/realpath.1
new file mode 100644
index 0000000..e1f5f7e
--- /dev/null
+++ b/realpath.1
_AT_@ -0,0 +1,16 @@
+.Dd 2015-11-14
+.Dt REALPATH 1
+.Os sbase
+.Sh NAME
+.Nm realpath
+.Nd Print resolved canonical paths
+.Sh SYNOPSIS
+.Nm
+behaves identically to
+.Xr readlink 1
+with the
+.Fl f
+flag. All other flags are supported.
+.Sh SEE ALSO
+.Xr readlink 1
+.Xr realpath 3
--
2.3.6
--dkEUBIird37B8yKS--
Received on Mon Sep 17 2001 - 00:00:00 CEST
This archive was generated by hypermail 2.3.0 : Sat Nov 21 2015 - 04:48:11 CET