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