diff options
| author | Paul Eggert | 2011-02-22 11:30:07 -0800 |
|---|---|---|
| committer | Paul Eggert | 2011-02-22 11:30:07 -0800 |
| commit | ae0d725005539d9259efac6a81ff8fdd45eb69a6 (patch) | |
| tree | c721b530409b355281537abc7b058bdb2697ee01 /lib/readlink.c | |
| parent | 8d40723d1e9661840a67ca7be9c5b073526ab421 (diff) | |
| download | emacs-ae0d725005539d9259efac6a81ff8fdd45eb69a6.tar.gz emacs-ae0d725005539d9259efac6a81ff8fdd45eb69a6.zip | |
[ChangeLog]
Work around some portability problems with symlinks.
* Makefile.in (GNULIB_MODULES): Add lstat, readlink, symlink.
* configure.in (lstat, HAVE_LSTAT): Remove special hack.
* lib/lstat.c, lib/readlink.c, lib/stat.c, lib/symlink.c:
* m4/dos.m4, m4/lstat.m4, m4/readlink.m4, m4/stat.m4, m4/symlink.m4:
New files, automatically generated from gnulib.
* aclocal.m4, configure, lib/Makefile.in, lib/gnulib.mk:
* lib/stdlib.in.h, m4/gl-comp.m4, m4/stdlib_h.m4: Regenerate.
2011-02-22 Paul Eggert <eggert@cs.ucla.edu>
[src/ChangeLog]
Work around some portability problems with symlinks.
* fileio.c (Frename_file, Fmake_symbolic_link, Ffile_symlink_p):
Simplify the code by assuming that the readlink and symlink calls
exist, even if they always fail on this host.
(Ffile_readable_p): Likewise, for fifos.
* config.in: Regenerate.
Diffstat (limited to 'lib/readlink.c')
| -rw-r--r-- | lib/readlink.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/readlink.c b/lib/readlink.c new file mode 100644 index 00000000000..35d045b9a12 --- /dev/null +++ b/lib/readlink.c | |||
| @@ -0,0 +1,74 @@ | |||
| 1 | /* Stub for readlink(). | ||
| 2 | Copyright (C) 2003-2007, 2009-2011 Free Software Foundation, Inc. | ||
| 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 | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 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 | |||
| 31 | ssize_t | ||
| 32 | readlink (const char *name, char *buf _GL_UNUSED, | ||
| 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. */ | ||
| 40 | if (stat (name, &statbuf) >= 0) | ||
| 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 | |||
| 53 | ssize_t | ||
| 54 | rpl_readlink (const char *name, char *buf, size_t bufsize) | ||
| 55 | { | ||
| 56 | # if READLINK_TRAILING_SLASH_BUG | ||
| 57 | size_t len = strlen (name); | ||
| 58 | if (len && name[len - 1] == '/') | ||
| 59 | { | ||
| 60 | /* Even if name without the slash is a symlink to a directory, | ||
| 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; | ||
| 66 | if (stat (name, &st) == 0) | ||
| 67 | errno = EINVAL; | ||
| 68 | return -1; | ||
| 69 | } | ||
| 70 | # endif /* READLINK_TRAILING_SLASH_BUG */ | ||
| 71 | return readlink (name, buf, bufsize); | ||
| 72 | } | ||
| 73 | |||
| 74 | #endif /* HAVE_READLINK */ | ||