--- 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 - 00:36:11 CET