Introduce ada_structop_operation
[deliverable/binutils-gdb.git] / gnulib / import / readlink.c
CommitLineData
9c9d63b1
PM
1/* Read the contents of a symbolic link.
2 Copyright (C) 2003-2007, 2009-2021 Free Software Foundation, Inc.
2196f55f
YQ
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
c0c3707f 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
2196f55f
YQ
16
17#include <config.h>
18
19/* Specification. */
20#include <unistd.h>
21
22#include <errno.h>
23#include <string.h>
24#include <sys/stat.h>
25
26#if !HAVE_READLINK
27
28/* readlink() substitute for systems that don't have a readlink() function,
29 such as DJGPP 2.03 and mingw32. */
30
31ssize_t
9c9d63b1 32readlink (char const *file, char *buf _GL_UNUSED,
2196f55f
YQ
33 size_t bufsize _GL_UNUSED)
34{
35 struct stat statbuf;
36
37 /* In general we should use lstat() here, not stat(). But on platforms
38 without symbolic links, lstat() - if it exists - would be equivalent to
39 stat(), therefore we can use stat(). This saves us a configure check. */
9c9d63b1 40 if (stat (file, &statbuf) >= 0)
2196f55f
YQ
41 errno = EINVAL;
42 return -1;
43}
44
45#else /* HAVE_READLINK */
46
47# undef readlink
48
49/* readlink() wrapper that uses correct types, for systems like cygwin
50 1.5.x where readlink returns int, and which rejects trailing slash,
51 for Solaris 9. */
52
53ssize_t
9c9d63b1 54rpl_readlink (char const *file, char *buf, size_t bufsize)
2196f55f
YQ
55{
56# if READLINK_TRAILING_SLASH_BUG
9c9d63b1
PM
57 size_t file_len = strlen (file);
58 if (file_len && file[file_len - 1] == '/')
2196f55f 59 {
9c9d63b1 60 /* Even if FILE without the slash is a symlink to a directory,
2196f55f
YQ
61 both lstat() and stat() must resolve the trailing slash to
62 the directory rather than the symlink. We can therefore
63 safely use stat() to distinguish between EINVAL and
64 ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */
65 struct stat st;
9c9d63b1 66 if (stat (file, &st) == 0 || errno == EOVERFLOW)
2196f55f
YQ
67 errno = EINVAL;
68 return -1;
69 }
70# endif /* READLINK_TRAILING_SLASH_BUG */
9c9d63b1
PM
71
72 ssize_t r = readlink (file, buf, bufsize);
73
74# if READLINK_TRUNCATE_BUG
75 if (r < 0 && errno == ERANGE)
76 {
77 /* Try again with a bigger buffer. This is just for test cases;
78 real code invariably discards short reads. */
79 char stackbuf[4032];
80 r = readlink (file, stackbuf, sizeof stackbuf);
81 if (r < 0)
82 {
83 if (errno == ERANGE)
84 {
85 /* Clear the buffer, which is good enough for real code.
86 Thankfully, no test cases try short reads of enormous
87 symlinks and what would be the point anyway? */
88 r = bufsize;
89 memset (buf, 0, r);
90 }
91 }
92 else
93 {
94 if (bufsize < r)
95 r = bufsize;
96 memcpy (buf, stackbuf, r);
97 }
98 }
99# endif
100
101 return r;
2196f55f
YQ
102}
103
104#endif /* HAVE_READLINK */
This page took 0.490533 seconds and 4 git commands to generate.