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