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
  10//usage:#define readlink_trivial_usage
  11//usage:        IF_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE"
  12//usage:#define readlink_full_usage "\n\n"
  13//usage:       "Display the value of a symlink"
  14//usage:        IF_FEATURE_READLINK_FOLLOW( "\n"
  15//usage:     "\n        -f      Canonicalize by following all symlinks"
  16//usage:     "\n        -n      Don't add newline"
  17//usage:     "\n        -v      Verbose"
  18//usage:        )
  19
  20#include "libbb.h"
  21
  22/*
  23 * # readlink --version
  24 * readlink (GNU coreutils) 6.10
  25 * # readlink --help
  26 *   -f, --canonicalize
  27 *      canonicalize by following every symlink in
  28 *      every component of the given name recursively;
  29 *      all but the last component must exist
  30 *   -e, --canonicalize-existing
  31 *      canonicalize by following every symlink in
  32 *      every component of the given name recursively,
  33 *      all components must exist
  34 *   -m, --canonicalize-missing
  35 *      canonicalize by following every symlink in
  36 *      every component of the given name recursively,
  37 *      without requirements on components existence
  38 *   -n, --no-newline              do not output the trailing newline
  39 *   -q, --quiet, -s, --silent     suppress most error messages
  40 *   -v, --verbose                 report error messages
  41 *
  42 * bbox supports: -f (partially) -n -v (fully), -q -s (accepts but ignores)
  43 * Note: we export the -f flag, but our -f behaves like coreutils' -e.
  44 * Unfortunately, there isn't a C lib function we can leverage to get this
  45 * behavior which means we'd have to implement the full stack ourselves :(.
  46 */
  47
  48int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  49int readlink_main(int argc UNUSED_PARAM, char **argv)
  50{
  51        char *buf;
  52        char *fname;
  53
  54        IF_FEATURE_READLINK_FOLLOW(
  55                unsigned opt;
  56                /* We need exactly one non-option argument.  */
  57                opt_complementary = "=1";
  58                opt = getopt32(argv, "fnvsq");
  59                fname = argv[optind];
  60        )
  61        IF_NOT_FEATURE_READLINK_FOLLOW(
  62                const unsigned opt = 0;
  63                if (argc != 2) bb_show_usage();
  64                fname = argv[1];
  65        )
  66
  67        /* compat: coreutils readlink reports errors silently via exit code */
  68        if (!(opt & 4)) /* not -v */
  69                logmode = LOGMODE_NONE;
  70
  71        if (opt & 1) { /* -f */
  72                buf = xmalloc_realpath(fname);
  73        } else {
  74                buf = xmalloc_readlink_or_warn(fname);
  75        }
  76
  77        if (!buf)
  78                return EXIT_FAILURE;
  79        printf((opt & 2) ? "%s" : "%s\n", buf);
  80
  81        if (ENABLE_FEATURE_CLEAN_UP)
  82                free(buf);
  83
  84        fflush_stdout_and_exit(EXIT_SUCCESS);
  85}
  86