Blame lib/readlink.c

Packit Service fdd496
/* Stub for readlink().
Packit Service fdd496
   Copyright (C) 2003-2007, 2009-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#include <config.h>
Packit Service fdd496
Packit Service fdd496
/* Specification.  */
Packit Service fdd496
#include <unistd.h>
Packit Service fdd496
Packit Service fdd496
#include <errno.h>
Packit Service fdd496
#include <string.h>
Packit Service fdd496
#include <sys/stat.h>
Packit Service fdd496
Packit Service fdd496
#if !HAVE_READLINK
Packit Service fdd496
Packit Service fdd496
/* readlink() substitute for systems that don't have a readlink() function,
Packit Service fdd496
   such as DJGPP 2.03 and mingw32.  */
Packit Service fdd496
Packit Service fdd496
ssize_t
Packit Service fdd496
readlink (const char *name, char *buf _GL_UNUSED,
Packit Service fdd496
          size_t bufsize _GL_UNUSED)
Packit Service fdd496
{
Packit Service fdd496
  struct stat statbuf;
Packit Service fdd496
Packit Service fdd496
  /* In general we should use lstat() here, not stat().  But on platforms
Packit Service fdd496
     without symbolic links, lstat() - if it exists - would be equivalent to
Packit Service fdd496
     stat(), therefore we can use stat().  This saves us a configure check.  */
Packit Service fdd496
  if (stat (name, &statbuf) >= 0)
Packit Service fdd496
    errno = EINVAL;
Packit Service fdd496
  return -1;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#else /* HAVE_READLINK */
Packit Service fdd496
Packit Service fdd496
# undef readlink
Packit Service fdd496
Packit Service fdd496
/* readlink() wrapper that uses correct types, for systems like cygwin
Packit Service fdd496
   1.5.x where readlink returns int, and which rejects trailing slash,
Packit Service fdd496
   for Solaris 9.  */
Packit Service fdd496
Packit Service fdd496
ssize_t
Packit Service fdd496
rpl_readlink (const char *name, char *buf, size_t bufsize)
Packit Service fdd496
{
Packit Service fdd496
# if READLINK_TRAILING_SLASH_BUG
Packit Service fdd496
  size_t len = strlen (name);
Packit Service fdd496
  if (len && name[len - 1] == '/')
Packit Service fdd496
    {
Packit Service fdd496
      /* Even if name without the slash is a symlink to a directory,
Packit Service fdd496
         both lstat() and stat() must resolve the trailing slash to
Packit Service fdd496
         the directory rather than the symlink.  We can therefore
Packit Service fdd496
         safely use stat() to distinguish between EINVAL and
Packit Service fdd496
         ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat().  */
Packit Service fdd496
      struct stat st;
Packit Service fdd496
      if (stat (name, &st) == 0)
Packit Service fdd496
        errno = EINVAL;
Packit Service fdd496
      return -1;
Packit Service fdd496
    }
Packit Service fdd496
# endif /* READLINK_TRAILING_SLASH_BUG */
Packit Service fdd496
  return readlink (name, buf, bufsize);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#endif /* HAVE_READLINK */