From f66b47bc6f7ce63409855668d0d1550b83638609 Mon Sep 17 00:00:00 2001 From: stateless Date: Sat, 15 Jun 2013 15:17:57 +0100 Subject: [PATCH] Add readlink Signed-off-by: Christoph Lohmann <20h@r-36.net> --- Makefile | 1 + readlink.1 | 25 +++++++++++++++++++++++++ readlink.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 readlink.1 create mode 100644 readlink.c diff --git a/Makefile b/Makefile index a7a653d..d567b1f 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,7 @@ SRC = \ paste.c \ printenv.c \ pwd.c \ + readlink.c \ renice.c \ rm.c \ rmdir.c \ diff --git a/readlink.1 b/readlink.1 new file mode 100644 index 0000000..2a0476a --- /dev/null +++ b/readlink.1 @@ -0,0 +1,25 @@ +.TH READLINK 1 sbase\-VERSION +.SH NAME +readlink \- print value of a symbolic link or canonical file name +.SH SYNOPSIS +.B readlink +.RB [ \-fn ] +.IR file +.SH DESCRIPTION +The readlink utility when invoked with the pathname of a symbolic link as +its argument dereferences the symbolic link and prints the name of target +on standard output. If the -f option is not specified and readlink is +invoked with an argument other than the pathname of a symbolic link, it +exits with a nonzero exit code without printing anything. +.SH OPTIONS +.TP +.B \-f +Canonicalize by following every symlink in every component of the +given path recursively. The argument does not need to be a symbolic +link. +.TP +.B \-n +Do not output the trailing newline. +.SH SEE ALSO +.IR readlink (2), +.IR realpath (3) diff --git a/readlink.c b/readlink.c new file mode 100644 index 0000000..cb86134 --- /dev/null +++ b/readlink.c @@ -0,0 +1,55 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include "util.h" + +static void +usage(void) +{ + eprintf("usage: %s [-fn] file\n", argv0); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char buf[PATH_MAX]; + bool nflag = false; + bool fflag = false; + + ARGBEGIN { + case 'f': + fflag = true; + break; + case 'n': + nflag = true; + break; + default: + usage(); + } ARGEND; + + if (argc != 1) + usage(); + + if (strlen(argv[0]) > PATH_MAX - 1) + exit(1); + + if (fflag) { + if (realpath(argv[0], buf) == NULL) + exit(1); + } else { + if (readlink(argv[0], buf, sizeof(buf)) < 0) + exit(1); + } + + printf("%s", buf); + if (!nflag) + putchar('\n'); + + return 0; +}