1 /* 2 * Copyright (c) 2013, The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google, Inc. nor the names of its contributors 15 * may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <limits.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 37 static int skip_newline, quiet_errors, canonicalize; 38 39 static void usage(char* name) { 40 fprintf(stderr, "Usage: %s [OPTION]... FILE\n", name); 41 } 42 43 int readlink_main(int argc, char* argv[]) { 44 int c; 45 while ((c = getopt(argc, argv, "nfqs")) != -1) { 46 switch (c) { 47 case 'n': 48 skip_newline = 1; 49 break; 50 case 'f': 51 canonicalize = 1; 52 break; 53 case 'q': 54 case 's': 55 quiet_errors = 1; 56 break; 57 case '?': 58 default: 59 usage(argv[0]); 60 return EXIT_FAILURE; 61 } 62 } 63 int index = optind; 64 if (argc - index != 1) { 65 usage(argv[0]); 66 return EXIT_FAILURE; 67 } 68 69 char name[PATH_MAX+1]; 70 if (canonicalize) { 71 if(!realpath(argv[optind], name)) { 72 if (!quiet_errors) { 73 perror("readlink"); 74 } 75 return EXIT_FAILURE; 76 } 77 } else { 78 ssize_t len = readlink(argv[1], name, PATH_MAX); 79 80 if (len < 0) { 81 if (!quiet_errors) { 82 perror("readlink"); 83 } 84 return EXIT_FAILURE; 85 } 86 name[len] = '\0'; 87 } 88 89 fputs(name, stdout); 90 if (!skip_newline) { 91 fputs("\n", stdout); 92 } 93 94 return EXIT_SUCCESS; 95 } 96