1/* xreadlink.c -- readlink wrapper to return the link name in malloc'd storage 2 3 Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2, or (at your option) 8 any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; see the file COPYING. 17 If not, write to the Free Software Foundation, 18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19#include <sys/cdefs.h> 20__RCSID("$NetBSD: xreadlink.c,v 1.2 2016/05/17 14:00:09 christos Exp $"); 21 22 23/* Written by Jim Meyering <jim@meyering.net> */ 24 25#ifdef HAVE_CONFIG_H 26# include <config.h> 27#endif 28 29#include "xreadlink.h" 30 31#include <stdio.h> 32#include <errno.h> 33#include <limits.h> 34#include <sys/types.h> 35#include <stdlib.h> 36#if HAVE_UNISTD_H 37# include <unistd.h> 38#endif 39 40#ifndef SIZE_MAX 41# define SIZE_MAX ((size_t) -1) 42#endif 43#ifndef SSIZE_MAX 44# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) 45#endif 46 47#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX) 48 49#include "xalloc.h" 50 51/* Call readlink to get the symbolic link value of FILE. 52 SIZE is a hint as to how long the link is expected to be; 53 typically it is taken from st_size. It need not be correct. 54 Return a pointer to that NUL-terminated string in malloc'd storage. 55 If readlink fails, return NULL (caller may use errno to diagnose). 56 If malloc fails, or if the link value is longer than SSIZE_MAX :-), 57 give a diagnostic and exit. */ 58 59char * 60xreadlink (char const *file, size_t size) 61{ 62 /* The initial buffer size for the link value. A power of 2 63 detects arithmetic overflow earlier, but is not required. */ 64 size_t buf_size = size < MAXSIZE ? size + 1 : MAXSIZE; 65 66 while (1) 67 { 68 char *buffer = xmalloc (buf_size); 69 ssize_t r = readlink (file, buffer, buf_size); 70 size_t link_length = r; 71 72 /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1 73 with errno == ERANGE if the buffer is too small. */ 74 if (r < 0 && errno != ERANGE) 75 { 76 int saved_errno = errno; 77 free (buffer); 78 errno = saved_errno; 79 return NULL; 80 } 81 82 if (link_length < buf_size) 83 { 84 buffer[link_length] = 0; 85 return buffer; 86 } 87 88 free (buffer); 89 if (buf_size <= MAXSIZE / 2) 90 buf_size *= 2; 91 else if (buf_size < MAXSIZE) 92 buf_size = MAXSIZE; 93 else 94 xalloc_die (); 95 } 96} 97