aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.in30
-rw-r--r--lib/dosname.h53
-rw-r--r--lib/gnulib.mk45
-rw-r--r--lib/lstat.c91
-rw-r--r--lib/readlink.c74
-rw-r--r--lib/stat.c105
-rw-r--r--lib/symlink.c57
7 files changed, 443 insertions, 12 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 7135d3ebbf9..04ee541a09c 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -24,7 +24,7 @@
24# the same distribution terms as the rest of that program. 24# the same distribution terms as the rest of that program.
25# 25#
26# Generated by gnulib-tool. 26# Generated by gnulib-tool.
27# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value mktime strftime sys_stat 27# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value lstat mktime readlink strftime symlink sys_stat
28 28
29VPATH = @srcdir@ 29VPATH = @srcdir@
30pkgdatadir = $(datadir)/@PACKAGE@ 30pkgdatadir = $(datadir)/@PACKAGE@
@@ -55,11 +55,13 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \
55 $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gl-comp.m4 \ 55 $(top_srcdir)/m4/getopt.m4 $(top_srcdir)/m4/gl-comp.m4 \
56 $(top_srcdir)/m4/gnulib-common.m4 \ 56 $(top_srcdir)/m4/gnulib-common.m4 \
57 $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/longlong.m4 \ 57 $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/longlong.m4 \
58 $(top_srcdir)/m4/md5.m4 $(top_srcdir)/m4/mktime.m4 \ 58 $(top_srcdir)/m4/lstat.m4 $(top_srcdir)/m4/md5.m4 \
59 $(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/st_dm_mode.m4 \ 59 $(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/multiarch.m4 \
60 $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ 60 $(top_srcdir)/m4/readlink.m4 $(top_srcdir)/m4/st_dm_mode.m4 \
61 $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/m4/stdlib_h.m4 \ 61 $(top_srcdir)/m4/stat.m4 $(top_srcdir)/m4/stdbool.m4 \
62 $(top_srcdir)/m4/strftime.m4 $(top_srcdir)/m4/sys_stat_h.m4 \ 62 $(top_srcdir)/m4/stddef_h.m4 $(top_srcdir)/m4/stdint.m4 \
63 $(top_srcdir)/m4/stdlib_h.m4 $(top_srcdir)/m4/strftime.m4 \
64 $(top_srcdir)/m4/symlink.m4 $(top_srcdir)/m4/sys_stat_h.m4 \
63 $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \ 65 $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \
64 $(top_srcdir)/m4/tm_gmtoff.m4 $(top_srcdir)/m4/unistd_h.m4 \ 66 $(top_srcdir)/m4/tm_gmtoff.m4 $(top_srcdir)/m4/unistd_h.m4 \
65 $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/configure.in 67 $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/configure.in
@@ -602,10 +604,11 @@ BUILT_SOURCES = arg-nonnull.h c++defs.h $(GETOPT_H) $(STDBOOL_H) \
602 $(STDDEF_H) $(STDINT_H) stdlib.h sys/stat.h time.h unistd.h \ 604 $(STDDEF_H) $(STDINT_H) stdlib.h sys/stat.h time.h unistd.h \
603 warn-on-use.h 605 warn-on-use.h
604EXTRA_DIST = $(top_srcdir)/./arg-nonnull.h $(top_srcdir)/./c++defs.h \ 606EXTRA_DIST = $(top_srcdir)/./arg-nonnull.h $(top_srcdir)/./c++defs.h \
605 md5.c md5.h ftoastr.c ftoastr.h filemode.c filemode.h \ 607 md5.c md5.h dosname.h ftoastr.c ftoastr.h filemode.c \
606 getloadavg.c getopt.c getopt.in.h getopt1.c getopt_int.h \ 608 filemode.h getloadavg.c getopt.c getopt.in.h getopt1.c \
607 intprops.h mktime-internal.h mktime.c stdbool.in.h stddef.in.h \ 609 getopt_int.h intprops.h lstat.c mktime-internal.h mktime.c \
608 stdint.in.h stdlib.in.h strftime.c strftime.h sys_stat.in.h \ 610 readlink.c stat.c stdbool.in.h stddef.in.h stdint.in.h \
611 stdlib.in.h strftime.c strftime.h symlink.c sys_stat.in.h \
609 time.in.h time_r.c unistd.in.h $(top_srcdir)/./warn-on-use.h 612 time.in.h time_r.c unistd.in.h $(top_srcdir)/./warn-on-use.h
610MOSTLYCLEANDIRS = sys 613MOSTLYCLEANDIRS = sys
611MOSTLYCLEANFILES = core *.stackdump arg-nonnull.h arg-nonnull.h-t \ 614MOSTLYCLEANFILES = core *.stackdump arg-nonnull.h arg-nonnull.h-t \
@@ -619,7 +622,8 @@ libgnu_a_SOURCES = dtoastr.c gettext.h ignore-value.h
619libgnu_a_LIBADD = $(gl_LIBOBJS) 622libgnu_a_LIBADD = $(gl_LIBOBJS)
620libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) 623libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
621EXTRA_libgnu_a_SOURCES = md5.c ftoastr.c filemode.c getloadavg.c \ 624EXTRA_libgnu_a_SOURCES = md5.c ftoastr.c filemode.c getloadavg.c \
622 getopt.c getopt1.c mktime.c strftime.c time_r.c 625 getopt.c getopt1.c lstat.c mktime.c readlink.c stat.c \
626 strftime.c symlink.c time_r.c
623ARG_NONNULL_H = arg-nonnull.h 627ARG_NONNULL_H = arg-nonnull.h
624CXXDEFS_H = c++defs.h 628CXXDEFS_H = c++defs.h
625WARN_ON_USE_H = warn-on-use.h 629WARN_ON_USE_H = warn-on-use.h
@@ -678,9 +682,13 @@ distclean-compile:
678@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getloadavg.Po@am__quote@ 682@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getloadavg.Po@am__quote@
679@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ 683@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@
680@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ 684@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@
685@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lstat.Po@am__quote@
681@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ 686@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@
682@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@ 687@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@
688@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readlink.Po@am__quote@
689@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat.Po@am__quote@
683@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strftime.Po@am__quote@ 690@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strftime.Po@am__quote@
691@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symlink.Po@am__quote@
684@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@ 692@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@
685 693
686.c.o: 694.c.o:
diff --git a/lib/dosname.h b/lib/dosname.h
new file mode 100644
index 00000000000..acdd03b156e
--- /dev/null
+++ b/lib/dosname.h
@@ -0,0 +1,53 @@
1/* File names on MS-DOS/Windows systems.
2
3 Copyright (C) 2000-2001, 2004-2006, 2009-2011 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 3 of the License, or
8 (at your option) 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. If not, see <http://www.gnu.org/licenses/>.
17
18 From Paul Eggert and Jim Meyering. */
19
20#ifndef _DOSNAME_H
21#define _DOSNAME_H
22
23#if (defined _WIN32 || defined __WIN32__ || \
24 defined __MSDOS__ || defined __CYGWIN__ || \
25 defined __EMX__ || defined __DJGPP__)
26 /* This internal macro assumes ASCII, but all hosts that support drive
27 letters use ASCII. */
28# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
29 <= 'z' - 'a')
30# define FILE_SYSTEM_PREFIX_LEN(Filename) \
31 (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
32# ifndef __CYGWIN__
33# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
34# endif
35# define ISSLASH(C) ((C) == '/' || (C) == '\\')
36#else
37# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
38# define ISSLASH(C) ((C) == '/')
39#endif
40
41#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
42# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
43#endif
44
45#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
46# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
47# else
48# define IS_ABSOLUTE_FILE_NAME(F) \
49 (ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
50#endif
51#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
52
53#endif /* DOSNAME_H_ */
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 53cc3815254..b5fd4a358db 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -9,7 +9,7 @@
9# the same distribution terms as the rest of that program. 9# the same distribution terms as the rest of that program.
10# 10#
11# Generated by gnulib-tool. 11# Generated by gnulib-tool.
12# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value mktime strftime sys_stat 12# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value lstat mktime readlink strftime symlink sys_stat
13 13
14 14
15MOSTLYCLEANFILES += core *.stackdump 15MOSTLYCLEANFILES += core *.stackdump
@@ -78,6 +78,13 @@ EXTRA_libgnu_a_SOURCES += md5.c
78 78
79## end gnulib module crypto/md5 79## end gnulib module crypto/md5
80 80
81## begin gnulib module dosname
82
83
84EXTRA_DIST += dosname.h
85
86## end gnulib module dosname
87
81## begin gnulib module dtoastr 88## begin gnulib module dtoastr
82 89
83libgnu_a_SOURCES += dtoastr.c 90libgnu_a_SOURCES += dtoastr.c
@@ -151,6 +158,15 @@ EXTRA_DIST += intprops.h
151 158
152## end gnulib module intprops 159## end gnulib module intprops
153 160
161## begin gnulib module lstat
162
163
164EXTRA_DIST += lstat.c
165
166EXTRA_libgnu_a_SOURCES += lstat.c
167
168## end gnulib module lstat
169
154## begin gnulib module mktime 170## begin gnulib module mktime
155 171
156 172
@@ -160,6 +176,24 @@ EXTRA_libgnu_a_SOURCES += mktime.c
160 176
161## end gnulib module mktime 177## end gnulib module mktime
162 178
179## begin gnulib module readlink
180
181
182EXTRA_DIST += readlink.c
183
184EXTRA_libgnu_a_SOURCES += readlink.c
185
186## end gnulib module readlink
187
188## begin gnulib module stat
189
190
191EXTRA_DIST += stat.c
192
193EXTRA_libgnu_a_SOURCES += stat.c
194
195## end gnulib module stat
196
163## begin gnulib module stdbool 197## begin gnulib module stdbool
164 198
165BUILT_SOURCES += $(STDBOOL_H) 199BUILT_SOURCES += $(STDBOOL_H)
@@ -344,6 +378,15 @@ EXTRA_libgnu_a_SOURCES += strftime.c
344 378
345## end gnulib module strftime 379## end gnulib module strftime
346 380
381## begin gnulib module symlink
382
383
384EXTRA_DIST += symlink.c
385
386EXTRA_libgnu_a_SOURCES += symlink.c
387
388## end gnulib module symlink
389
347## begin gnulib module sys_stat 390## begin gnulib module sys_stat
348 391
349BUILT_SOURCES += sys/stat.h 392BUILT_SOURCES += sys/stat.h
diff --git a/lib/lstat.c b/lib/lstat.c
new file mode 100644
index 00000000000..b26065ede28
--- /dev/null
+++ b/lib/lstat.c
@@ -0,0 +1,91 @@
1/* Work around a bug of lstat on some systems
2
3 Copyright (C) 1997-2006, 2008-2011 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 3 of the License, or
8 (at your option) 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. If not, see <http://www.gnu.org/licenses/>. */
17
18/* written by Jim Meyering */
19
20#include <config.h>
21
22#if !HAVE_LSTAT
23/* On systems that lack symlinks, our replacement <sys/stat.h> already
24 defined lstat as stat, so there is nothing further to do other than
25 avoid an empty file. */
26typedef int dummy;
27#else /* HAVE_LSTAT */
28
29/* Get the original definition of lstat. It might be defined as a macro. */
30# define __need_system_sys_stat_h
31# include <sys/types.h>
32# include <sys/stat.h>
33# undef __need_system_sys_stat_h
34
35static inline int
36orig_lstat (const char *filename, struct stat *buf)
37{
38 return lstat (filename, buf);
39}
40
41/* Specification. */
42# include <sys/stat.h>
43
44# include <string.h>
45# include <errno.h>
46
47/* lstat works differently on Linux and Solaris systems. POSIX (see
48 `pathname resolution' in the glossary) requires that programs like
49 `ls' take into consideration the fact that FILE has a trailing slash
50 when FILE is a symbolic link. On Linux and Solaris 10 systems, the
51 lstat function already has the desired semantics (in treating
52 `lstat ("symlink/", sbuf)' just like `lstat ("symlink/.", sbuf)',
53 but on Solaris 9 and earlier it does not.
54
55 If FILE has a trailing slash and specifies a symbolic link,
56 then use stat() to get more info on the referent of FILE.
57 If the referent is a non-directory, then set errno to ENOTDIR
58 and return -1. Otherwise, return stat's result. */
59
60int
61rpl_lstat (const char *file, struct stat *sbuf)
62{
63 size_t len;
64 int lstat_result = orig_lstat (file, sbuf);
65
66 if (lstat_result != 0)
67 return lstat_result;
68
69 /* This replacement file can blindly check against '/' rather than
70 using the ISSLASH macro, because all platforms with '\\' either
71 lack symlinks (mingw) or have working lstat (cygwin) and thus do
72 not compile this file. 0 len should have already been filtered
73 out above, with a failure return of ENOENT. */
74 len = strlen (file);
75 if (file[len - 1] != '/' || S_ISDIR (sbuf->st_mode))
76 return 0;
77
78 /* At this point, a trailing slash is only permitted on
79 symlink-to-dir; but it should have found information on the
80 directory, not the symlink. Call stat() to get info about the
81 link's referent. Our replacement stat guarantees valid results,
82 even if the symlink is not pointing to a directory. */
83 if (!S_ISLNK (sbuf->st_mode))
84 {
85 errno = ENOTDIR;
86 return -1;
87 }
88 return stat (file, sbuf);
89}
90
91#endif /* HAVE_LSTAT */
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
31ssize_t
32readlink (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
53ssize_t
54rpl_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 */
diff --git a/lib/stat.c b/lib/stat.c
new file mode 100644
index 00000000000..cbc9100fd4d
--- /dev/null
+++ b/lib/stat.c
@@ -0,0 +1,105 @@
1/* Work around platform bugs in stat.
2 Copyright (C) 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/* written by Eric Blake */
18
19#include <config.h>
20
21/* Get the original definition of stat. It might be defined as a macro. */
22#define __need_system_sys_stat_h
23#include <sys/types.h>
24#include <sys/stat.h>
25#undef __need_system_sys_stat_h
26
27static inline int
28orig_stat (const char *filename, struct stat *buf)
29{
30 return stat (filename, buf);
31}
32
33/* Specification. */
34#include <sys/stat.h>
35
36#include <errno.h>
37#include <limits.h>
38#include <stdbool.h>
39#include <string.h>
40#include "dosname.h"
41
42/* Store information about NAME into ST. Work around bugs with
43 trailing slashes. Mingw has other bugs (such as st_ino always
44 being 0 on success) which this wrapper does not work around. But
45 at least this implementation provides the ability to emulate fchdir
46 correctly. */
47
48int
49rpl_stat (char const *name, struct stat *st)
50{
51 int result = orig_stat (name, st);
52#if REPLACE_FUNC_STAT_FILE
53 /* Solaris 9 mistakenly succeeds when given a non-directory with a
54 trailing slash. */
55 if (result == 0 && !S_ISDIR (st->st_mode))
56 {
57 size_t len = strlen (name);
58 if (ISSLASH (name[len - 1]))
59 {
60 errno = ENOTDIR;
61 return -1;
62 }
63 }
64#endif /* REPLACE_FUNC_STAT_FILE */
65#if REPLACE_FUNC_STAT_DIR
66 if (result == -1 && errno == ENOENT)
67 {
68 /* Due to mingw's oddities, there are some directories (like
69 c:\) where stat() only succeeds with a trailing slash, and
70 other directories (like c:\windows) where stat() only
71 succeeds without a trailing slash. But we want the two to be
72 synonymous, since chdir() manages either style. Likewise, Mingw also
73 reports ENOENT for names longer than PATH_MAX, when we want
74 ENAMETOOLONG, and for stat("file/"), when we want ENOTDIR.
75 Fortunately, mingw PATH_MAX is small enough for stack
76 allocation. */
77 char fixed_name[PATH_MAX + 1] = {0};
78 size_t len = strlen (name);
79 bool check_dir = false;
80 if (PATH_MAX <= len)
81 errno = ENAMETOOLONG;
82 else if (len)
83 {
84 strcpy (fixed_name, name);
85 if (ISSLASH (fixed_name[len - 1]))
86 {
87 check_dir = true;
88 while (len && ISSLASH (fixed_name[len - 1]))
89 fixed_name[--len] = '\0';
90 if (!len)
91 fixed_name[0] = '/';
92 }
93 else
94 fixed_name[len++] = '/';
95 result = orig_stat (fixed_name, st);
96 if (result == 0 && check_dir && !S_ISDIR (st->st_mode))
97 {
98 result = -1;
99 errno = ENOTDIR;
100 }
101 }
102 }
103#endif /* REPLACE_FUNC_STAT_DIR */
104 return result;
105}
diff --git a/lib/symlink.c b/lib/symlink.c
new file mode 100644
index 00000000000..2896cc9655b
--- /dev/null
+++ b/lib/symlink.c
@@ -0,0 +1,57 @@
1/* Stub for symlink().
2 Copyright (C) 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
27#if HAVE_SYMLINK
28
29# undef symlink
30
31/* Create a symlink, but reject trailing slash. */
32int
33rpl_symlink (char const *contents, char const *name)
34{
35 size_t len = strlen (name);
36 if (len && name[len - 1] == '/')
37 {
38 struct stat st;
39 if (lstat (name, &st) == 0)
40 errno = EEXIST;
41 return -1;
42 }
43 return symlink (contents, name);
44}
45
46#else /* !HAVE_SYMLINK */
47
48/* The system does not support symlinks. */
49int
50symlink (char const *contents _GL_UNUSED,
51 char const *name _GL_UNUSED)
52{
53 errno = ENOSYS;
54 return -1;
55}
56
57#endif /* !HAVE_SYMLINK */