busybox/coreutils/readlink.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Mini readlink implementation for busybox
   4 *
   5 * Copyright (C) 2000,2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9//config:config READLINK
  10//config:       bool "readlink (4 kb)"
  11//config:       default y
  12//config:       help
  13//config:       This program reads a symbolic link and returns the name
  14//config:       of the file it points to
  15//config:
  16//config:config FEATURE_READLINK_FOLLOW
  17//config:       bool "Enable canonicalization by following all symlinks (-f)"
  18//config:       default y
  19//config:       depends on READLINK
  20//config:       help
  21//config:       Enable the readlink option (-f).
  22
  23//applet:IF_READLINK(APPLET_NOFORK(readlink, readlink, BB_DIR_USR_BIN, BB_SUID_DROP, readlink))
  24
  25//kbuild:lib-$(CONFIG_READLINK) += readlink.o
  26
  27//usage:#define readlink_trivial_usage
  28//usage:        IF_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE"
  29//usage:#define readlink_full_usage "\n\n"
  30//usage:       "Display the value of a symlink"
  31//usage:        IF_FEATURE_READLINK_FOLLOW( "\n"
  32//usage:     "\n        -f      Canonicalize by following all symlinks"
  33//usage:     "\n        -n      Don't add newline"
  34//usage:     "\n        -v      Verbose"
  35//usage:        )
  36
  37#include "libbb.h"
  38
  39/*
  40 * # readlink --version
  41 * readlink (GNU coreutils) 6.10
  42 * # readlink --help
  43 *   -f, --canonicalize
  44 *      canonicalize by following every symlink in
  45 *      every component of the given name recursively;
  46 *      all but the last component must exist
  47 *   -e, --canonicalize-existing
  48 *      canonicalize by following every symlink in
  49 *      every component of the given name recursively,
  50 *      all components must exist
  51 *   -m, --canonicalize-missing
  52 *      canonicalize by following every symlink in
  53 *      every component of the given name recursively,
  54 *      without requirements on components existence
  55 *   -n, --no-newline              do not output the trailing newline
  56 *   -q, --quiet, -s, --silent     suppress most error messages
  57 *   -v, --verbose                 report error messages
  58 *
  59 * bbox supports: -f (partially) -n -v (fully), -q -s (accepts but ignores)
  60 * Note: we export the -f flag, but our -f behaves like coreutils' -e.
  61 * Unfortunately, there isn't a C lib function we can leverage to get this
  62 * behavior which means we'd have to implement the full stack ourselves :(.
  63 */
  64
  65int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  66int readlink_main(int argc UNUSED_PARAM, char **argv)
  67{
  68        char *buf;
  69        char *fname;
  70
  71        IF_FEATURE_READLINK_FOLLOW(
  72                unsigned opt;
  73                /* We need exactly one non-option argument.  */
  74                opt = getopt32(argv, "^" "fnvsq" "\0" "=1");
  75                fname = argv[optind];
  76        )
  77        IF_NOT_FEATURE_READLINK_FOLLOW(
  78                const unsigned opt = 0;
  79                if (argc != 2) bb_show_usage();
  80                fname = argv[1];
  81        )
  82
  83        /* compat: coreutils readlink reports errors silently via exit code */
  84        if (!(opt & 4)) /* not -v */
  85                logmode = LOGMODE_NONE;
  86
  87        /* NOFORK: only one alloc is allowed; must free */
  88        if (opt & 1) { /* -f */
  89                buf = xmalloc_realpath_coreutils(fname);
  90        } else {
  91                buf = xmalloc_readlink_or_warn(fname);
  92        }
  93
  94        if (!buf)
  95                return EXIT_FAILURE;
  96        printf((opt & 2) ? "%s" : "%s\n", buf);
  97        free(buf);
  98
  99        fflush_stdout_and_exit(EXIT_SUCCESS);
 100}
 101