aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--admin/ChangeLog8
-rwxr-xr-xadmin/merge-gnulib13
-rw-r--r--configure.ac4
-rw-r--r--lib/at-func.c146
-rw-r--r--lib/euidaccess.c221
-rw-r--r--lib/faccessat.c45
-rw-r--r--lib/fcntl.in.h355
-rw-r--r--lib/getgroups.c116
-rw-r--r--lib/gnulib.mk97
-rw-r--r--lib/group-member.c119
-rw-r--r--lib/root-uid.h30
-rw-r--r--lib/xalloc-oversized.h38
-rw-r--r--m4/euidaccess.m452
-rw-r--r--m4/faccessat.m428
-rw-r--r--m4/fcntl_h.m450
-rw-r--r--m4/getgroups.m4107
-rw-r--r--m4/gnulib-comp.m4105
-rw-r--r--m4/group-member.m429
-rw-r--r--nt/ChangeLog7
-rw-r--r--nt/inc/ms-w32.h7
-rw-r--r--src/ChangeLog67
-rw-r--r--src/Makefile.in3
-rw-r--r--src/callproc.c12
-rw-r--r--src/charset.c2
-rw-r--r--src/conf_post.h4
-rw-r--r--src/fileio.c184
-rw-r--r--src/lisp.h2
-rw-r--r--src/lread.c92
-rw-r--r--src/nsterm.m2
-rw-r--r--src/process.c36
-rw-r--r--src/sysdep.c6
-rw-r--r--src/term.c4
-rw-r--r--src/w32.c18
-rw-r--r--src/xrdb.c101
35 files changed, 1878 insertions, 245 deletions
diff --git a/ChangeLog b/ChangeLog
index e8bff20d56d..f5f649aae6d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
12012-11-14 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use faccessat, not access, when checking file permissions (Bug#12632).
4 * .bzrignore: Add lib/fcntl.h.
5 * configure.ac (euidaccess): Remove check; gnulib does this for us now.
6 (gl_FCNTL_O_FLAGS): Define a dummy version.
7 * lib/at-func.c, lib/euidaccess.c, lib/faccessat.c, lib/fcntl.in.h:
8 * lib/getgroups.c, lib/group-member.c, lib/root-uid.h:
9 * lib/xalloc-oversized.h, m4/euidaccess.m4, m4/faccessat.m4:
10 * m4/fcntl_h.m4, m4/getgroups.m4, m4/group-member.m4:
11 New files, from gnulib.
12 * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
13
12012-11-05 Paul Eggert <eggert@cs.ucla.edu> 142012-11-05 Paul Eggert <eggert@cs.ucla.edu>
2 15
3 Assume at least POSIX.1-1988 for getpgrp, setpgid, setsid (Bug#12800). 16 Assume at least POSIX.1-1988 for getpgrp, setpgid, setsid (Bug#12800).
diff --git a/admin/ChangeLog b/admin/ChangeLog
index 496e1c1bb6a..fd28bf1228f 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,3 +1,11 @@
12012-11-14 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use faccessat, not access, when checking file permissions (Bug#12632).
4 * merge-gnulib (GNULIB_MODULES): Add faccessat.
5 (GNULIB_TOOL_FLAGS): Avoid at-internal, fchdir, malloc-posix,
6 openat-die, openat-h, save-cwd. Do not avoid fcntl-h.
7 Omit gnulib's m4/fcntl-o.m4.
8
12012-11-05 Paul Eggert <eggert@cs.ucla.edu> 92012-11-05 Paul Eggert <eggert@cs.ucla.edu>
2 10
3 Assume at least POSIX.1-1988 for getpgrp, setpgid, setsid (Bug#12800). 11 Assume at least POSIX.1-1988 for getpgrp, setpgid, setsid (Bug#12800).
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 901daf4e442..f7a675e5101 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -28,7 +28,7 @@ GNULIB_URL=git://git.savannah.gnu.org/gnulib.git
28GNULIB_MODULES=' 28GNULIB_MODULES='
29 alloca-opt c-ctype c-strcase 29 alloca-opt c-ctype c-strcase
30 careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 30 careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
31 dtoastr dtotimespec dup2 environ execinfo 31 dtoastr dtotimespec dup2 environ execinfo faccessat
32 filemode getloadavg getopt-gnu gettime gettimeofday 32 filemode getloadavg getopt-gnu gettime gettimeofday
33 ignore-value intprops largefile lstat 33 ignore-value intprops largefile lstat
34 manywarnings mktime pselect pthread_sigmask readlink 34 manywarnings mktime pselect pthread_sigmask readlink
@@ -39,9 +39,12 @@ GNULIB_MODULES='
39' 39'
40 40
41GNULIB_TOOL_FLAGS=' 41GNULIB_TOOL_FLAGS='
42 --avoid=errno --avoid=fcntl --avoid=fcntl-h --avoid=fstat 42 --avoid=at-internal
43 --avoid=msvc-inval --avoid=msvc-nothrow 43 --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat
44 --avoid=raise --avoid=select --avoid=sigprocmask --avoid=sys_types 44 --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow
45 --avoid=openat-die --avoid=openat-h
46 --avoid=raise
47 --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types
45 --avoid=threadlib 48 --avoid=threadlib
46 --conditional-dependencies --import --no-changelog --no-vc-files 49 --conditional-dependencies --import --no-changelog --no-vc-files
47 --makefile-name=gnulib.mk 50 --makefile-name=gnulib.mk
@@ -85,7 +88,7 @@ test -x "$gnulib_srcdir"/gnulib-tool || {
85} 88}
86 89
87"$gnulib_srcdir"/gnulib-tool --dir="$src" $GNULIB_TOOL_FLAGS $GNULIB_MODULES && 90"$gnulib_srcdir"/gnulib-tool --dir="$src" $GNULIB_TOOL_FLAGS $GNULIB_MODULES &&
88rm -- "$src"m4/gnulib-cache.m4 "$src"m4/warn-on-use.m4 && 91rm -- "$src"m4/fcntl-o.m4 "$src"m4/gnulib-cache.m4 "$src"m4/warn-on-use.m4 &&
89cp -- "$gnulib_srcdir"/build-aux/texinfo.tex "$src"doc/misc && 92cp -- "$gnulib_srcdir"/build-aux/texinfo.tex "$src"doc/misc &&
90cp -- "$gnulib_srcdir"/build-aux/move-if-change "$src"build-aux && 93cp -- "$gnulib_srcdir"/build-aux/move-if-change "$src"build-aux &&
91autoreconf -i -I m4 -- ${src:+"$src"} 94autoreconf -i -I m4 -- ${src:+"$src"}
diff --git a/configure.ac b/configure.ac
index 9146c669096..b0c81a23f8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -572,6 +572,8 @@ else
572 test "x$NON_GCC_TEST_OPTIONS" != x && CC="$CC $NON_GCC_TEST_OPTIONS" 572 test "x$NON_GCC_TEST_OPTIONS" != x && CC="$CC $NON_GCC_TEST_OPTIONS"
573fi 573fi
574 574
575# Avoid gnulib's tests for O_NOATIME and O_NOFOLLOW, as we don't use them.
576AC_DEFUN([gl_FCNTL_O_FLAGS])
575# Avoid gnulib's threadlib module, as we do threads our own way. 577# Avoid gnulib's threadlib module, as we do threads our own way.
576AC_DEFUN([gl_THREADLIB]) 578AC_DEFUN([gl_THREADLIB])
577 579
@@ -2872,7 +2874,7 @@ AC_SUBST(BLESSMAIL_TARGET)
2872AC_CHECK_FUNCS(gethostname \ 2874AC_CHECK_FUNCS(gethostname \
2873closedir getrusage get_current_dir_name \ 2875closedir getrusage get_current_dir_name \
2874lrand48 \ 2876lrand48 \
2875fpathconf select euidaccess getpagesize setlocale \ 2877fpathconf select getpagesize setlocale \
2876utimes getrlimit setrlimit getcwd shutdown getaddrinfo \ 2878utimes getrlimit setrlimit getcwd shutdown getaddrinfo \
2877strsignal setitimer \ 2879strsignal setitimer \
2878sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \ 2880sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \
diff --git a/lib/at-func.c b/lib/at-func.c
new file mode 100644
index 00000000000..481eea475a1
--- /dev/null
+++ b/lib/at-func.c
@@ -0,0 +1,146 @@
1/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
2 Copyright (C) 2006, 2009-2012 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 Jim Meyering */
18
19#include "dosname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
20
21#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
22# include <errno.h>
23# ifndef ENOTSUP
24# define ENOTSUP EINVAL
25# endif
26#else
27# include "openat.h"
28# include "openat-priv.h"
29# include "save-cwd.h"
30#endif
31
32#ifdef AT_FUNC_USE_F1_COND
33# define CALL_FUNC(F) \
34 (flag == AT_FUNC_USE_F1_COND \
35 ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \
36 : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS))
37# define VALIDATE_FLAG(F) \
38 if (flag & ~AT_FUNC_USE_F1_COND) \
39 { \
40 errno = EINVAL; \
41 return FUNC_FAIL; \
42 }
43#else
44# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS))
45# define VALIDATE_FLAG(F) /* empty */
46#endif
47
48#ifdef AT_FUNC_RESULT
49# define FUNC_RESULT AT_FUNC_RESULT
50#else
51# define FUNC_RESULT int
52#endif
53
54#ifdef AT_FUNC_FAIL
55# define FUNC_FAIL AT_FUNC_FAIL
56#else
57# define FUNC_FAIL -1
58#endif
59
60/* Call AT_FUNC_F1 to operate on FILE, which is in the directory
61 open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value,
62 AT_FUNC_POST_FILE_PARAM_DECLS must include a parameter named flag;
63 call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than
64 AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT
65 or AT_FUNC_FAIL are defined. If possible, do it without changing the
66 working directory. Otherwise, resort to using save_cwd/fchdir,
67 then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd
68 fails, then give a diagnostic and exit nonzero. */
69FUNC_RESULT
70AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
71{
72 VALIDATE_FLAG (flag);
73
74 if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file))
75 return CALL_FUNC (file);
76
77#ifdef GNULIB_SUPPORT_ONLY_AT_FDCWD
78 errno = ENOTSUP;
79 return FUNC_FAIL;
80#else
81 {
82 /* Be careful to choose names unlikely to conflict with
83 AT_FUNC_POST_FILE_PARAM_DECLS. */
84 struct saved_cwd saved_cwd;
85 int saved_errno;
86 FUNC_RESULT err;
87
88 {
89 char proc_buf[OPENAT_BUFFER_SIZE];
90 char *proc_file = openat_proc_name (proc_buf, fd, file);
91 if (proc_file)
92 {
93 FUNC_RESULT proc_result = CALL_FUNC (proc_file);
94 int proc_errno = errno;
95 if (proc_file != proc_buf)
96 free (proc_file);
97 /* If the syscall succeeds, or if it fails with an unexpected
98 errno value, then return right away. Otherwise, fall through
99 and resort to using save_cwd/restore_cwd. */
100 if (FUNC_FAIL != proc_result)
101 return proc_result;
102 if (! EXPECTED_ERRNO (proc_errno))
103 {
104 errno = proc_errno;
105 return proc_result;
106 }
107 }
108 }
109
110 if (save_cwd (&saved_cwd) != 0)
111 openat_save_fail (errno);
112 if (0 <= fd && fd == saved_cwd.desc)
113 {
114 /* If saving the working directory collides with the user's
115 requested fd, then the user's fd must have been closed to
116 begin with. */
117 free_cwd (&saved_cwd);
118 errno = EBADF;
119 return FUNC_FAIL;
120 }
121
122 if (fchdir (fd) != 0)
123 {
124 saved_errno = errno;
125 free_cwd (&saved_cwd);
126 errno = saved_errno;
127 return FUNC_FAIL;
128 }
129
130 err = CALL_FUNC (file);
131 saved_errno = (err == FUNC_FAIL ? errno : 0);
132
133 if (restore_cwd (&saved_cwd) != 0)
134 openat_restore_fail (errno);
135
136 free_cwd (&saved_cwd);
137
138 if (saved_errno)
139 errno = saved_errno;
140 return err;
141 }
142#endif
143}
144#undef CALL_FUNC
145#undef FUNC_RESULT
146#undef FUNC_FAIL
diff --git a/lib/euidaccess.c b/lib/euidaccess.c
new file mode 100644
index 00000000000..ca2ceca5d22
--- /dev/null
+++ b/lib/euidaccess.c
@@ -0,0 +1,221 @@
1/* euidaccess -- check if effective user id can access file
2
3 Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2012 Free
4 Software Foundation, Inc.
5
6 This file is part of the GNU C Library.
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21/* Written by David MacKenzie and Torbjorn Granlund.
22 Adapted for GNU C library by Roland McGrath. */
23
24#ifndef _LIBC
25# include <config.h>
26#endif
27
28#include <fcntl.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32
33#include "root-uid.h"
34
35#if HAVE_LIBGEN_H
36# include <libgen.h>
37#endif
38
39#include <errno.h>
40#ifndef __set_errno
41# define __set_errno(val) errno = (val)
42#endif
43
44#if defined EACCES && !defined EACCESS
45# define EACCESS EACCES
46#endif
47
48#ifndef F_OK
49# define F_OK 0
50# define X_OK 1
51# define W_OK 2
52# define R_OK 4
53#endif
54
55
56#ifdef _LIBC
57
58# define access __access
59# define getuid __getuid
60# define getgid __getgid
61# define geteuid __geteuid
62# define getegid __getegid
63# define group_member __group_member
64# define euidaccess __euidaccess
65# undef stat
66# define stat stat64
67
68#endif
69
70/* Return 0 if the user has permission of type MODE on FILE;
71 otherwise, return -1 and set 'errno'.
72 Like access, except that it uses the effective user and group
73 id's instead of the real ones, and it does not always check for read-only
74 file system, text busy, etc. */
75
76int
77euidaccess (const char *file, int mode)
78{
79#if HAVE_FACCESSAT /* glibc, AIX 7, Solaris 11, Cygwin 1.7 */
80 return faccessat (AT_FDCWD, file, mode, AT_EACCESS);
81#elif defined EFF_ONLY_OK /* IRIX, OSF/1, Interix */
82 return access (file, mode | EFF_ONLY_OK);
83#elif defined ACC_SELF /* AIX */
84 return accessx (file, mode, ACC_SELF);
85#elif HAVE_EACCESS /* FreeBSD */
86 return eaccess (file, mode);
87#else /* Mac OS X, NetBSD, OpenBSD, HP-UX, Solaris, Cygwin, mingw, BeOS */
88
89 uid_t uid = getuid ();
90 gid_t gid = getgid ();
91 uid_t euid = geteuid ();
92 gid_t egid = getegid ();
93 struct stat stats;
94
95# if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS
96
97 /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to
98 return the correct result even if this would make it
99 nonreentrant. Define this only if your entire application is
100 safe even if the uid or gid might temporarily change. If your
101 application uses signal handlers or threads it is probably not
102 safe. */
103
104 if (mode == F_OK)
105 return stat (file, &stats);
106 else
107 {
108 int result;
109 int saved_errno;
110
111 if (uid != euid)
112 setreuid (euid, uid);
113 if (gid != egid)
114 setregid (egid, gid);
115
116 result = access (file, mode);
117 saved_errno = errno;
118
119 /* Restore them. */
120 if (uid != euid)
121 setreuid (uid, euid);
122 if (gid != egid)
123 setregid (gid, egid);
124
125 errno = saved_errno;
126 return result;
127 }
128
129# else
130
131 /* The following code assumes the traditional Unix model, and is not
132 correct on systems that have ACLs or the like. However, it's
133 better than nothing, and it is reentrant. */
134
135 unsigned int granted;
136 if (uid == euid && gid == egid)
137 /* If we are not set-uid or set-gid, access does the same. */
138 return access (file, mode);
139
140 if (stat (file, &stats) != 0)
141 return -1;
142
143 /* The super-user can read and write any file, and execute any file
144 that anyone can execute. */
145 if (euid == ROOT_UID
146 && ((mode & X_OK) == 0
147 || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
148 return 0;
149
150 /* Convert the mode to traditional form, clearing any bogus bits. */
151 if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
152 mode &= 7;
153 else
154 mode = ((mode & R_OK ? 4 : 0)
155 + (mode & W_OK ? 2 : 0)
156 + (mode & X_OK ? 1 : 0));
157
158 if (mode == 0)
159 return 0; /* The file exists. */
160
161 /* Convert the file's permission bits to traditional form. */
162 if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6)
163 && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3)
164 && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0))
165 granted = stats.st_mode;
166 else
167 granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0)
168 + (stats.st_mode & S_IWUSR ? 2 << 6 : 0)
169 + (stats.st_mode & S_IXUSR ? 1 << 6 : 0)
170 + (stats.st_mode & S_IRGRP ? 4 << 3 : 0)
171 + (stats.st_mode & S_IWGRP ? 2 << 3 : 0)
172 + (stats.st_mode & S_IXGRP ? 1 << 3 : 0)
173 + (stats.st_mode & S_IROTH ? 4 << 0 : 0)
174 + (stats.st_mode & S_IWOTH ? 2 << 0 : 0)
175 + (stats.st_mode & S_IXOTH ? 1 << 0 : 0));
176
177 if (euid == stats.st_uid)
178 granted >>= 6;
179 else if (egid == stats.st_gid || group_member (stats.st_gid))
180 granted >>= 3;
181
182 if ((mode & ~granted) == 0)
183 return 0;
184 __set_errno (EACCESS);
185 return -1;
186
187# endif
188#endif
189}
190#undef euidaccess
191#ifdef weak_alias
192weak_alias (__euidaccess, euidaccess)
193#endif
194
195#ifdef TEST
196# include <error.h>
197# include <stdio.h>
198# include <stdlib.h>
199
200char *program_name;
201
202int
203main (int argc, char **argv)
204{
205 char *file;
206 int mode;
207 int err;
208
209 program_name = argv[0];
210 if (argc < 3)
211 abort ();
212 file = argv[1];
213 mode = atoi (argv[2]);
214
215 err = euidaccess (file, mode);
216 printf ("%d\n", err);
217 if (err != 0)
218 error (0, errno, "%s", file);
219 exit (0);
220}
221#endif
diff --git a/lib/faccessat.c b/lib/faccessat.c
new file mode 100644
index 00000000000..d11a3efaad6
--- /dev/null
+++ b/lib/faccessat.c
@@ -0,0 +1,45 @@
1/* Check the access rights of a file relative to an open directory.
2 Copyright (C) 2009-2012 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#include <unistd.h>
22#include <fcntl.h>
23
24#ifndef HAVE_ACCESS
25/* Mingw lacks access, but it also lacks real vs. effective ids, so
26 the gnulib euidaccess module is good enough. */
27# undef access
28# define access euidaccess
29#endif
30
31/* Invoke access or euidaccess on file, FILE, using mode MODE, in the directory
32 open on descriptor FD. If possible, do it without changing the
33 working directory. Otherwise, resort to using save_cwd/fchdir, then
34 (access|euidaccess)/restore_cwd. If either the save_cwd or the
35 restore_cwd fails, then give a diagnostic and exit nonzero.
36 Note that this implementation only supports AT_EACCESS, although some
37 native versions also support AT_SYMLINK_NOFOLLOW. */
38
39#define AT_FUNC_NAME faccessat
40#define AT_FUNC_F1 euidaccess
41#define AT_FUNC_F2 access
42#define AT_FUNC_USE_F1_COND AT_EACCESS
43#define AT_FUNC_POST_FILE_PARAM_DECLS , int mode, int flag
44#define AT_FUNC_POST_FILE_ARGS , mode
45#include "at-func.c"
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
new file mode 100644
index 00000000000..fb402ee1f0f
--- /dev/null
+++ b/lib/fcntl.in.h
@@ -0,0 +1,355 @@
1/* Like <fcntl.h>, but with non-working flags defined to 0.
2
3 Copyright (C) 2006-2012 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 Paul Eggert */
19
20#if __GNUC__ >= 3
21@PRAGMA_SYSTEM_HEADER@
22#endif
23@PRAGMA_COLUMNS@
24
25#if defined __need_system_fcntl_h
26/* Special invocation convention. */
27
28/* Needed before <sys/stat.h>.
29 May also define off_t to a 64-bit type on native Windows. */
30#include <sys/types.h>
31/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
32 <fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
33 But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
34 extern "C" { ... } block, which leads to errors in C++ mode with the
35 overridden <sys/stat.h> from gnulib. These errors are known to be gone
36 with g++ version >= 4.3. */
37#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
38# include <sys/stat.h>
39#endif
40#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
41
42#else
43/* Normal invocation convention. */
44
45#ifndef _@GUARD_PREFIX@_FCNTL_H
46
47/* Needed before <sys/stat.h>.
48 May also define off_t to a 64-bit type on native Windows. */
49#include <sys/types.h>
50/* On some systems other than glibc, <sys/stat.h> is a prerequisite of
51 <fcntl.h>. On glibc systems, we would like to avoid namespace pollution.
52 But on glibc systems, <fcntl.h> includes <sys/stat.h> inside an
53 extern "C" { ... } block, which leads to errors in C++ mode with the
54 overridden <sys/stat.h> from gnulib. These errors are known to be gone
55 with g++ version >= 4.3. */
56#if !(defined __GLIBC__ || defined __UCLIBC__) || (defined __cplusplus && defined GNULIB_NAMESPACE && !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
57# include <sys/stat.h>
58#endif
59/* The include_next requires a split double-inclusion guard. */
60#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
61
62#ifndef _@GUARD_PREFIX@_FCNTL_H
63#define _@GUARD_PREFIX@_FCNTL_H
64
65#ifndef __GLIBC__ /* Avoid namespace pollution on glibc systems. */
66# include <unistd.h>
67#endif
68
69/* Native Windows platforms declare open(), creat() in <io.h>. */
70#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
71 && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
72# include <io.h>
73#endif
74
75
76/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
77
78/* The definition of _GL_ARG_NONNULL is copied here. */
79
80/* The definition of _GL_WARN_ON_USE is copied here. */
81
82
83/* Declare overridden functions. */
84
85#if @GNULIB_FCNTL@
86# if @REPLACE_FCNTL@
87# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
88# undef fcntl
89# define fcntl rpl_fcntl
90# endif
91_GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...));
92_GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...));
93# else
94# if !@HAVE_FCNTL@
95_GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...));
96# endif
97_GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...));
98# endif
99_GL_CXXALIASWARN (fcntl);
100#elif defined GNULIB_POSIXCHECK
101# undef fcntl
102# if HAVE_RAW_DECL_FCNTL
103_GL_WARN_ON_USE (fcntl, "fcntl is not always POSIX compliant - "
104 "use gnulib module fcntl for portability");
105# endif
106#endif
107
108#if @GNULIB_OPEN@
109# if @REPLACE_OPEN@
110# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
111# undef open
112# define open rpl_open
113# endif
114_GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
115 _GL_ARG_NONNULL ((1)));
116_GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
117# else
118_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
119# endif
120/* On HP-UX 11, in C++ mode, open() is defined as an inline function with a
121 default argument. _GL_CXXALIASWARN does not work in this case. */
122# if !defined __hpux
123_GL_CXXALIASWARN (open);
124# endif
125#elif defined GNULIB_POSIXCHECK
126# undef open
127/* Assume open is always declared. */
128_GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
129 "use gnulib module open for portability");
130#endif
131
132#if @GNULIB_OPENAT@
133# if @REPLACE_OPENAT@
134# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
135# undef openat
136# define openat rpl_openat
137# endif
138_GL_FUNCDECL_RPL (openat, int,
139 (int fd, char const *file, int flags, /* mode_t mode */ ...)
140 _GL_ARG_NONNULL ((2)));
141_GL_CXXALIAS_RPL (openat, int,
142 (int fd, char const *file, int flags, /* mode_t mode */ ...));
143# else
144# if !@HAVE_OPENAT@
145_GL_FUNCDECL_SYS (openat, int,
146 (int fd, char const *file, int flags, /* mode_t mode */ ...)
147 _GL_ARG_NONNULL ((2)));
148# endif
149_GL_CXXALIAS_SYS (openat, int,
150 (int fd, char const *file, int flags, /* mode_t mode */ ...));
151# endif
152_GL_CXXALIASWARN (openat);
153#elif defined GNULIB_POSIXCHECK
154# undef openat
155# if HAVE_RAW_DECL_OPENAT
156_GL_WARN_ON_USE (openat, "openat is not portable - "
157 "use gnulib module openat for portability");
158# endif
159#endif
160
161
162/* Fix up the FD_* macros, only known to be missing on mingw. */
163
164#ifndef FD_CLOEXEC
165# define FD_CLOEXEC 1
166#endif
167
168/* Fix up the supported F_* macros. Intentionally leave other F_*
169 macros undefined. Only known to be missing on mingw. */
170
171#ifndef F_DUPFD_CLOEXEC
172# define F_DUPFD_CLOEXEC 0x40000000
173/* Witness variable: 1 if gnulib defined F_DUPFD_CLOEXEC, 0 otherwise. */
174# define GNULIB_defined_F_DUPFD_CLOEXEC 1
175#else
176# define GNULIB_defined_F_DUPFD_CLOEXEC 0
177#endif
178
179#ifndef F_DUPFD
180# define F_DUPFD 1
181#endif
182
183#ifndef F_GETFD
184# define F_GETFD 2
185#endif
186
187/* Fix up the O_* macros. */
188
189#if !defined O_DIRECT && defined O_DIRECTIO
190/* Tru64 spells it 'O_DIRECTIO'. */
191# define O_DIRECT O_DIRECTIO
192#endif
193
194#if !defined O_CLOEXEC && defined O_NOINHERIT
195/* Mingw spells it 'O_NOINHERIT'. */
196# define O_CLOEXEC O_NOINHERIT
197#endif
198
199#ifndef O_CLOEXEC
200# define O_CLOEXEC 0
201#endif
202
203#ifndef O_DIRECT
204# define O_DIRECT 0
205#endif
206
207#ifndef O_DIRECTORY
208# define O_DIRECTORY 0
209#endif
210
211#ifndef O_DSYNC
212# define O_DSYNC 0
213#endif
214
215#ifndef O_EXEC
216# ifdef O_PATH
217# define O_EXEC O_PATH
218# else
219# define O_EXEC O_RDONLY /* This is often close enough in older systems. */
220# endif
221#endif
222
223#ifndef O_IGNORE_CTTY
224# define O_IGNORE_CTTY 0
225#endif
226
227#ifndef O_NDELAY
228# define O_NDELAY 0
229#endif
230
231#ifndef O_NOATIME
232# define O_NOATIME 0
233#endif
234
235#ifndef O_NONBLOCK
236# define O_NONBLOCK O_NDELAY
237#endif
238
239/* If the gnulib module 'nonblocking' is in use, guarantee a working non-zero
240 value of O_NONBLOCK. Otherwise, O_NONBLOCK is defined (above) to O_NDELAY
241 or to 0 as fallback. */
242#if @GNULIB_NONBLOCKING@
243# if O_NONBLOCK
244# define GNULIB_defined_O_NONBLOCK 0
245# else
246# define GNULIB_defined_O_NONBLOCK 1
247# undef O_NONBLOCK
248# define O_NONBLOCK 0x40000000
249# endif
250#endif
251
252#ifndef O_NOCTTY
253# define O_NOCTTY 0
254#endif
255
256#ifndef O_NOFOLLOW
257# define O_NOFOLLOW 0
258#endif
259
260#ifndef O_NOLINK
261# define O_NOLINK 0
262#endif
263
264#ifndef O_NOLINKS
265# define O_NOLINKS 0
266#endif
267
268#ifndef O_NOTRANS
269# define O_NOTRANS 0
270#endif
271
272#ifndef O_RSYNC
273# define O_RSYNC 0
274#endif
275
276#ifndef O_SEARCH
277# ifdef O_PATH
278# define O_SEARCH O_PATH
279# else
280# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */
281# endif
282#endif
283
284#ifndef O_SYNC
285# define O_SYNC 0
286#endif
287
288#ifndef O_TTY_INIT
289# define O_TTY_INIT 0
290#endif
291
292#if ~O_ACCMODE & (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
293# undef O_ACCMODE
294# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR | O_EXEC | O_SEARCH)
295#endif
296
297/* For systems that distinguish between text and binary I/O.
298 O_BINARY is usually declared in fcntl.h */
299#if !defined O_BINARY && defined _O_BINARY
300 /* For MSC-compatible compilers. */
301# define O_BINARY _O_BINARY
302# define O_TEXT _O_TEXT
303#endif
304
305#if defined __BEOS__ || defined __HAIKU__
306 /* BeOS 5 and Haiku have O_BINARY and O_TEXT, but they have no effect. */
307# undef O_BINARY
308# undef O_TEXT
309#endif
310
311#ifndef O_BINARY
312# define O_BINARY 0
313# define O_TEXT 0
314#endif
315
316/* Fix up the AT_* macros. */
317
318/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its
319 value exceeds INT_MAX, so its use as an int doesn't conform to the
320 C standard, and GCC and Sun C complain in some cases. If the bug
321 is present, undef AT_FDCWD here, so it can be redefined below. */
322#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553
323# undef AT_FDCWD
324#endif
325
326/* Use the same bit pattern as Solaris 9, but with the proper
327 signedness. The bit pattern is important, in case this actually is
328 Solaris with the above workaround. */
329#ifndef AT_FDCWD
330# define AT_FDCWD (-3041965)
331#endif
332
333/* Use the same values as Solaris 9. This shouldn't matter, but
334 there's no real reason to differ. */
335#ifndef AT_SYMLINK_NOFOLLOW
336# define AT_SYMLINK_NOFOLLOW 4096
337#endif
338
339#ifndef AT_REMOVEDIR
340# define AT_REMOVEDIR 1
341#endif
342
343/* Solaris 9 lacks these two, so just pick unique values. */
344#ifndef AT_SYMLINK_FOLLOW
345# define AT_SYMLINK_FOLLOW 2
346#endif
347
348#ifndef AT_EACCESS
349# define AT_EACCESS 4
350#endif
351
352
353#endif /* _@GUARD_PREFIX@_FCNTL_H */
354#endif /* _@GUARD_PREFIX@_FCNTL_H */
355#endif
diff --git a/lib/getgroups.c b/lib/getgroups.c
new file mode 100644
index 00000000000..f9d36236afe
--- /dev/null
+++ b/lib/getgroups.c
@@ -0,0 +1,116 @@
1/* provide consistent interface to getgroups for systems that don't allow N==0
2
3 Copyright (C) 1996, 1999, 2003, 2006-2012 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#include <unistd.h>
23
24#include <errno.h>
25#include <stdlib.h>
26#include <stdint.h>
27
28#if !HAVE_GETGROUPS
29
30/* Provide a stub that fails with ENOSYS, since there is no group
31 information available on mingw. */
32int
33getgroups (int n _GL_UNUSED, GETGROUPS_T *groups _GL_UNUSED)
34{
35 errno = ENOSYS;
36 return -1;
37}
38
39#else /* HAVE_GETGROUPS */
40
41# undef getgroups
42# ifndef GETGROUPS_ZERO_BUG
43# define GETGROUPS_ZERO_BUG 0
44# endif
45
46/* On at least Ultrix 4.3 and NextStep 3.2, getgroups (0, NULL) always
47 fails. On other systems, it returns the number of supplemental
48 groups for the process. This function handles that special case
49 and lets the system-provided function handle all others. However,
50 it can fail with ENOMEM if memory is tight. It is unspecified
51 whether the effective group id is included in the list. */
52
53int
54rpl_getgroups (int n, gid_t *group)
55{
56 int n_groups;
57 GETGROUPS_T *gbuf;
58 int saved_errno;
59
60 if (n < 0)
61 {
62 errno = EINVAL;
63 return -1;
64 }
65
66 if (n != 0 || !GETGROUPS_ZERO_BUG)
67 {
68 int result;
69 if (sizeof *group == sizeof *gbuf)
70 return getgroups (n, (GETGROUPS_T *) group);
71
72 if (SIZE_MAX / sizeof *gbuf <= n)
73 {
74 errno = ENOMEM;
75 return -1;
76 }
77 gbuf = malloc (n * sizeof *gbuf);
78 if (!gbuf)
79 return -1;
80 result = getgroups (n, gbuf);
81 if (0 <= result)
82 {
83 n = result;
84 while (n--)
85 group[n] = gbuf[n];
86 }
87 saved_errno = errno;
88 free (gbuf);
89 errno == saved_errno;
90 return result;
91 }
92
93 n = 20;
94 while (1)
95 {
96 /* No need to worry about address arithmetic overflow here,
97 since the ancient systems that we're running on have low
98 limits on the number of secondary groups. */
99 gbuf = malloc (n * sizeof *gbuf);
100 if (!gbuf)
101 return -1;
102 n_groups = getgroups (n, gbuf);
103 if (n_groups == -1 ? errno != EINVAL : n_groups < n)
104 break;
105 free (gbuf);
106 n *= 2;
107 }
108
109 saved_errno = errno;
110 free (gbuf);
111 errno = saved_errno;
112
113 return n_groups;
114}
115
116#endif /* HAVE_GETGROUPS */
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 324e5cb78fd..f74c46ae9c8 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
21# the same distribution terms as the rest of that program. 21# the same distribution terms as the rest of that program.
22# 22#
23# Generated by gnulib-tool. 23# Generated by gnulib-tool.
24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=errno --avoid=fcntl --avoid=fcntl-h --avoid=fstat --avoid=msvc-inval --avoid=msvc-nothrow --avoid=raise --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask readlink socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub utimens warnings 24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=at-internal --avoid=errno --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=openat-die --avoid=openat-h --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat filemode getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings mktime pselect pthread_sigmask readlink socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub utimens warnings
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -158,6 +158,17 @@ EXTRA_libgnu_a_SOURCES += dup2.c
158 158
159## end gnulib module dup2 159## end gnulib module dup2
160 160
161## begin gnulib module euidaccess
162
163if gl_GNULIB_ENABLED_euidaccess
164
165endif
166EXTRA_DIST += euidaccess.c
167
168EXTRA_libgnu_a_SOURCES += euidaccess.c
169
170## end gnulib module euidaccess
171
161## begin gnulib module execinfo 172## begin gnulib module execinfo
162 173
163BUILT_SOURCES += $(EXECINFO_H) 174BUILT_SOURCES += $(EXECINFO_H)
@@ -183,6 +194,50 @@ EXTRA_libgnu_a_SOURCES += execinfo.c
183 194
184## end gnulib module execinfo 195## end gnulib module execinfo
185 196
197## begin gnulib module faccessat
198
199
200EXTRA_DIST += at-func.c faccessat.c
201
202EXTRA_libgnu_a_SOURCES += at-func.c faccessat.c
203
204## end gnulib module faccessat
205
206## begin gnulib module fcntl-h
207
208BUILT_SOURCES += fcntl.h
209
210# We need the following in order to create <fcntl.h> when the system
211# doesn't have one that works with the given compiler.
212fcntl.h: fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
213 $(AM_V_GEN)rm -f $@-t $@ && \
214 { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
215 sed -e 's|@''GUARD_PREFIX''@|GL|g' \
216 -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
217 -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
218 -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
219 -e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \
220 -e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \
221 -e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \
222 -e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \
223 -e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \
224 -e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \
225 -e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \
226 -e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \
227 -e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \
228 -e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \
229 -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
230 -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
231 -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
232 < $(srcdir)/fcntl.in.h; \
233 } > $@-t && \
234 mv $@-t $@
235MOSTLYCLEANFILES += fcntl.h fcntl.h-t
236
237EXTRA_DIST += fcntl.in.h
238
239## end gnulib module fcntl-h
240
186## begin gnulib module filemode 241## begin gnulib module filemode
187 242
188libgnu_a_SOURCES += filemode.c 243libgnu_a_SOURCES += filemode.c
@@ -200,6 +255,17 @@ EXTRA_libgnu_a_SOURCES += fpending.c
200 255
201## end gnulib module fpending 256## end gnulib module fpending
202 257
258## begin gnulib module getgroups
259
260if gl_GNULIB_ENABLED_getgroups
261
262endif
263EXTRA_DIST += getgroups.c
264
265EXTRA_libgnu_a_SOURCES += getgroups.c
266
267## end gnulib module getgroups
268
203## begin gnulib module getloadavg 269## begin gnulib module getloadavg
204 270
205 271
@@ -259,6 +325,17 @@ EXTRA_libgnu_a_SOURCES += gettimeofday.c
259 325
260## end gnulib module gettimeofday 326## end gnulib module gettimeofday
261 327
328## begin gnulib module group-member
329
330if gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1
331
332endif
333EXTRA_DIST += group-member.c
334
335EXTRA_libgnu_a_SOURCES += group-member.c
336
337## end gnulib module group-member
338
262## begin gnulib module ignore-value 339## begin gnulib module ignore-value
263 340
264 341
@@ -371,6 +448,15 @@ EXTRA_libgnu_a_SOURCES += readlink.c
371 448
372## end gnulib module readlink 449## end gnulib module readlink
373 450
451## begin gnulib module root-uid
452
453if gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c
454
455endif
456EXTRA_DIST += root-uid.h
457
458## end gnulib module root-uid
459
374## begin gnulib module signal-h 460## begin gnulib module signal-h
375 461
376BUILT_SOURCES += signal.h 462BUILT_SOURCES += signal.h
@@ -1329,6 +1415,15 @@ EXTRA_DIST += verify.h
1329 1415
1330## end gnulib module verify 1416## end gnulib module verify
1331 1417
1418## begin gnulib module xalloc-oversized
1419
1420if gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec
1421
1422endif
1423EXTRA_DIST += xalloc-oversized.h
1424
1425## end gnulib module xalloc-oversized
1426
1332 1427
1333mostlyclean-local: mostlyclean-generic 1428mostlyclean-local: mostlyclean-generic
1334 @for dir in '' $(MOSTLYCLEANDIRS); do \ 1429 @for dir in '' $(MOSTLYCLEANDIRS); do \
diff --git a/lib/group-member.c b/lib/group-member.c
new file mode 100644
index 00000000000..5fcc7e01d0c
--- /dev/null
+++ b/lib/group-member.c
@@ -0,0 +1,119 @@
1/* group-member.c -- determine whether group id is in calling user's group list
2
3 Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2012 Free Software
4 Foundation, Inc.
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#include <config.h>
20
21/* Specification. */
22#include <unistd.h>
23
24#include <stdio.h>
25#include <sys/types.h>
26#include <stdlib.h>
27
28#include "xalloc-oversized.h"
29
30/* Most processes have no more than this many groups, and for these
31 processes we can avoid using malloc. */
32enum { GROUPBUF_SIZE = 100 };
33
34struct group_info
35 {
36 gid_t *group;
37 gid_t groupbuf[GROUPBUF_SIZE];
38 };
39
40static void
41free_group_info (struct group_info const *g)
42{
43 if (g->group != g->groupbuf)
44 free (g->group);
45}
46
47static int
48get_group_info (struct group_info *gi)
49{
50 int n_groups = getgroups (GROUPBUF_SIZE, gi->groupbuf);
51 gi->group = gi->groupbuf;
52
53 if (n_groups < 0)
54 {
55 int n_group_slots = getgroups (0, NULL);
56 if (0 <= n_group_slots
57 && ! xalloc_oversized (n_group_slots, sizeof *gi->group))
58 {
59 gi->group = malloc (n_group_slots * sizeof *gi->group);
60 if (gi->group)
61 n_groups = getgroups (n_group_slots, gi->group);
62 }
63 }
64
65 /* In case of error, the user loses. */
66 return n_groups;
67}
68
69/* Return non-zero if GID is one that we have in our groups list.
70 Note that the groups list is not guaranteed to contain the current
71 or effective group ID, so they should generally be checked
72 separately. */
73
74int
75group_member (gid_t gid)
76{
77 int i;
78 int found;
79 struct group_info gi;
80 int n_groups = get_group_info (&gi);
81
82 /* Search through the list looking for GID. */
83 found = 0;
84 for (i = 0; i < n_groups; i++)
85 {
86 if (gid == gi.group[i])
87 {
88 found = 1;
89 break;
90 }
91 }
92
93 free_group_info (&gi);
94
95 return found;
96}
97
98#ifdef TEST
99
100char *program_name;
101
102int
103main (int argc, char **argv)
104{
105 int i;
106
107 program_name = argv[0];
108
109 for (i = 1; i < argc; i++)
110 {
111 gid_t gid;
112
113 gid = atoi (argv[i]);
114 printf ("%d: %s\n", gid, group_member (gid) ? "yes" : "no");
115 }
116 exit (0);
117}
118
119#endif /* TEST */
diff --git a/lib/root-uid.h b/lib/root-uid.h
new file mode 100644
index 00000000000..2379773c291
--- /dev/null
+++ b/lib/root-uid.h
@@ -0,0 +1,30 @@
1/* The user ID that always has appropriate privileges in the POSIX sense.
2
3 Copyright 2012 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 Paul Eggert. */
19
20#ifndef ROOT_UID_H_
21#define ROOT_UID_H_
22
23/* The user ID that always has appropriate privileges in the POSIX sense. */
24#ifdef __TANDEM
25# define ROOT_UID 65535
26#else
27# define ROOT_UID 0
28#endif
29
30#endif
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
new file mode 100644
index 00000000000..ad777d8dd79
--- /dev/null
+++ b/lib/xalloc-oversized.h
@@ -0,0 +1,38 @@
1/* xalloc-oversized.h -- memory allocation size checking
2
3 Copyright (C) 1990-2000, 2003-2004, 2006-2012 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#ifndef XALLOC_OVERSIZED_H_
19# define XALLOC_OVERSIZED_H_
20
21# include <stddef.h>
22
23/* Return 1 if an array of N objects, each of size S, cannot exist due
24 to size arithmetic overflow. S must be positive and N must be
25 nonnegative. This is a macro, not a function, so that it
26 works correctly even when SIZE_MAX < N.
27
28 By gnulib convention, SIZE_MAX represents overflow in size
29 calculations, so the conservative dividend to use here is
30 SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value.
31 However, malloc (SIZE_MAX) fails on all known hosts where
32 sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for
33 exactly-SIZE_MAX allocations on such hosts; this avoids a test and
34 branch when S is known to be 1. */
35# define xalloc_oversized(n, s) \
36 ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n))
37
38#endif /* !XALLOC_OVERSIZED_H_ */
diff --git a/m4/euidaccess.m4 b/m4/euidaccess.m4
new file mode 100644
index 00000000000..2de95b88ba8
--- /dev/null
+++ b/m4/euidaccess.m4
@@ -0,0 +1,52 @@
1# euidaccess.m4 serial 15
2dnl Copyright (C) 2002-2012 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_FUNC_NONREENTRANT_EUIDACCESS],
8[
9 AC_REQUIRE([gl_FUNC_EUIDACCESS])
10 AC_CHECK_DECLS([setregid])
11 AC_DEFINE([PREFER_NONREENTRANT_EUIDACCESS], [1],
12 [Define this if you prefer euidaccess to return the correct result
13 even if this would make it nonreentrant. Define this only if your
14 entire application is safe even if the uid or gid might temporarily
15 change. If your application uses signal handlers or threads it
16 is probably not safe.])
17])
18
19AC_DEFUN([gl_FUNC_EUIDACCESS],
20[
21 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
22
23 dnl Persuade glibc <unistd.h> to declare euidaccess().
24 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
25
26 AC_CHECK_FUNCS([euidaccess])
27 if test $ac_cv_func_euidaccess = no; then
28 HAVE_EUIDACCESS=0
29 fi
30])
31
32# Prerequisites of lib/euidaccess.c.
33AC_DEFUN([gl_PREREQ_EUIDACCESS], [
34 dnl Prefer POSIX faccessat over non-standard euidaccess.
35 AC_CHECK_FUNCS_ONCE([faccessat])
36 dnl Try various other non-standard fallbacks.
37 AC_CHECK_HEADERS([libgen.h])
38 AC_FUNC_GETGROUPS
39
40 # Solaris 9 and 10 need -lgen to get the eaccess function.
41 # Save and restore LIBS so -lgen isn't added to it. Otherwise, *all*
42 # programs in the package would end up linked with that potentially-shared
43 # library, inducing unnecessary run-time overhead.
44 LIB_EACCESS=
45 AC_SUBST([LIB_EACCESS])
46 gl_saved_libs=$LIBS
47 AC_SEARCH_LIBS([eaccess], [gen],
48 [test "$ac_cv_search_eaccess" = "none required" ||
49 LIB_EACCESS=$ac_cv_search_eaccess])
50 AC_CHECK_FUNCS([eaccess])
51 LIBS=$gl_saved_libs
52])
diff --git a/m4/faccessat.m4 b/m4/faccessat.m4
new file mode 100644
index 00000000000..82f3b1f8dde
--- /dev/null
+++ b/m4/faccessat.m4
@@ -0,0 +1,28 @@
1# serial 6
2# See if we need to provide faccessat replacement.
3
4dnl Copyright (C) 2009-2012 Free Software Foundation, Inc.
5dnl This file is free software; the Free Software Foundation
6dnl gives unlimited permission to copy and/or distribute it,
7dnl with or without modifications, as long as this notice is preserved.
8
9# Written by Eric Blake.
10
11AC_DEFUN([gl_FUNC_FACCESSAT],
12[
13 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
14
15 dnl Persuade glibc <unistd.h> to declare faccessat().
16 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
17
18 AC_CHECK_FUNCS_ONCE([faccessat])
19 if test $ac_cv_func_faccessat = no; then
20 HAVE_FACCESSAT=0
21 fi
22])
23
24# Prerequisites of lib/faccessat.m4.
25AC_DEFUN([gl_PREREQ_FACCESSAT],
26[
27 AC_CHECK_FUNCS([access])
28])
diff --git a/m4/fcntl_h.m4 b/m4/fcntl_h.m4
new file mode 100644
index 00000000000..cac28aeb283
--- /dev/null
+++ b/m4/fcntl_h.m4
@@ -0,0 +1,50 @@
1# serial 15
2# Configure fcntl.h.
3dnl Copyright (C) 2006-2007, 2009-2012 Free Software Foundation, Inc.
4dnl This file is free software; the Free Software Foundation
5dnl gives unlimited permission to copy and/or distribute it,
6dnl with or without modifications, as long as this notice is preserved.
7
8dnl Written by Paul Eggert.
9
10AC_DEFUN([gl_FCNTL_H],
11[
12 AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
13 AC_REQUIRE([gl_FCNTL_O_FLAGS])
14 gl_NEXT_HEADERS([fcntl.h])
15
16 dnl Ensure the type pid_t gets defined.
17 AC_REQUIRE([AC_TYPE_PID_T])
18
19 dnl Ensure the type mode_t gets defined.
20 AC_REQUIRE([AC_TYPE_MODE_T])
21
22 dnl Check for declarations of anything we want to poison if the
23 dnl corresponding gnulib module is not in use, if it is not common
24 dnl enough to be declared everywhere.
25 gl_WARN_ON_USE_PREPARE([[#include <fcntl.h>
26 ]], [fcntl openat])
27])
28
29AC_DEFUN([gl_FCNTL_MODULE_INDICATOR],
30[
31 dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
32 AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
33 gl_MODULE_INDICATOR_SET_VARIABLE([$1])
34 dnl Define it also as a C macro, for the benefit of the unit tests.
35 gl_MODULE_INDICATOR_FOR_TESTS([$1])
36])
37
38AC_DEFUN([gl_FCNTL_H_DEFAULTS],
39[
40 GNULIB_FCNTL=0; AC_SUBST([GNULIB_FCNTL])
41 GNULIB_NONBLOCKING=0; AC_SUBST([GNULIB_NONBLOCKING])
42 GNULIB_OPEN=0; AC_SUBST([GNULIB_OPEN])
43 GNULIB_OPENAT=0; AC_SUBST([GNULIB_OPENAT])
44 dnl Assume proper GNU behavior unless another module says otherwise.
45 HAVE_FCNTL=1; AC_SUBST([HAVE_FCNTL])
46 HAVE_OPENAT=1; AC_SUBST([HAVE_OPENAT])
47 REPLACE_FCNTL=0; AC_SUBST([REPLACE_FCNTL])
48 REPLACE_OPEN=0; AC_SUBST([REPLACE_OPEN])
49 REPLACE_OPENAT=0; AC_SUBST([REPLACE_OPENAT])
50])
diff --git a/m4/getgroups.m4 b/m4/getgroups.m4
new file mode 100644
index 00000000000..17473af486b
--- /dev/null
+++ b/m4/getgroups.m4
@@ -0,0 +1,107 @@
1# serial 18
2
3dnl From Jim Meyering.
4dnl A wrapper around AC_FUNC_GETGROUPS.
5
6# Copyright (C) 1996-1997, 1999-2004, 2008-2012 Free Software Foundation, Inc.
7#
8# This file is free software; the Free Software Foundation
9# gives unlimited permission to copy and/or distribute it,
10# with or without modifications, as long as this notice is preserved.
11
12m4_version_prereq([2.70], [] ,[
13
14# This is taken from the following Autoconf patch:
15# http://git.savannah.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=7fbb553727ed7e0e689a17594b58559ecf3ea6e9
16AC_DEFUN([AC_FUNC_GETGROUPS],
17[
18 AC_REQUIRE([AC_TYPE_GETGROUPS])dnl
19 AC_REQUIRE([AC_TYPE_SIZE_T])dnl
20 AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
21 AC_CHECK_FUNC([getgroups])
22
23 # If we don't yet have getgroups, see if it's in -lbsd.
24 # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1.
25 ac_save_LIBS=$LIBS
26 if test $ac_cv_func_getgroups = no; then
27 AC_CHECK_LIB(bsd, getgroups, [GETGROUPS_LIB=-lbsd])
28 fi
29
30 # Run the program to test the functionality of the system-supplied
31 # getgroups function only if there is such a function.
32 if test $ac_cv_func_getgroups = yes; then
33 AC_CACHE_CHECK([for working getgroups], [ac_cv_func_getgroups_works],
34 [AC_RUN_IFELSE(
35 [AC_LANG_PROGRAM(
36 [AC_INCLUDES_DEFAULT],
37 [[/* On Ultrix 4.3, getgroups (0, 0) always fails. */
38 return getgroups (0, 0) == -1;]])
39 ],
40 [ac_cv_func_getgroups_works=yes],
41 [ac_cv_func_getgroups_works=no],
42 [case "$host_os" in # ((
43 # Guess yes on glibc systems.
44 *-gnu*) ac_cv_func_getgroups_works="guessing yes" ;;
45 # If we don't know, assume the worst.
46 *) ac_cv_func_getgroups_works="guessing no" ;;
47 esac
48 ])
49 ])
50 else
51 ac_cv_func_getgroups_works=no
52 fi
53 case "$ac_cv_func_getgroups_works" in
54 *yes)
55 AC_DEFINE([HAVE_GETGROUPS], [1],
56 [Define to 1 if your system has a working `getgroups' function.])
57 ;;
58 esac
59 LIBS=$ac_save_LIBS
60])# AC_FUNC_GETGROUPS
61
62])
63
64AC_DEFUN([gl_FUNC_GETGROUPS],
65[
66 AC_REQUIRE([AC_TYPE_GETGROUPS])
67 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
68 AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
69
70 AC_FUNC_GETGROUPS
71 if test $ac_cv_func_getgroups != yes; then
72 HAVE_GETGROUPS=0
73 else
74 if test "$ac_cv_type_getgroups" != gid_t \
75 || { case "$ac_cv_func_getgroups_works" in
76 *yes) false;;
77 *) true;;
78 esac
79 }; then
80 REPLACE_GETGROUPS=1
81 AC_DEFINE([GETGROUPS_ZERO_BUG], [1], [Define this to 1 if
82 getgroups(0,NULL) does not return the number of groups.])
83 else
84 dnl Detect FreeBSD bug; POSIX requires getgroups(-1,ptr) to fail.
85 AC_CACHE_CHECK([whether getgroups handles negative values],
86 [gl_cv_func_getgroups_works],
87 [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
88 [[int size = getgroups (0, 0);
89 gid_t *list = malloc (size * sizeof *list);
90 return getgroups (-1, list) != -1;]])],
91 [gl_cv_func_getgroups_works=yes],
92 [gl_cv_func_getgroups_works=no],
93 [case "$host_os" in
94 # Guess yes on glibc systems.
95 *-gnu*) gl_cv_func_getgroups_works="guessing yes" ;;
96 # If we don't know, assume the worst.
97 *) gl_cv_func_getgroups_works="guessing no" ;;
98 esac
99 ])])
100 case "$gl_cv_func_getgroups_works" in
101 *yes) ;;
102 *) REPLACE_GETGROUPS=1 ;;
103 esac
104 fi
105 fi
106 test -n "$GETGROUPS_LIB" && LIBS="$GETGROUPS_LIB $LIBS"
107])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 5cd278454e7..30f81b4781f 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -54,18 +54,23 @@ AC_DEFUN([gl_EARLY],
54 # Code from module dtotimespec: 54 # Code from module dtotimespec:
55 # Code from module dup2: 55 # Code from module dup2:
56 # Code from module environ: 56 # Code from module environ:
57 # Code from module euidaccess:
57 # Code from module execinfo: 58 # Code from module execinfo:
58 # Code from module extensions: 59 # Code from module extensions:
59 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) 60 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
60 # Code from module extern-inline: 61 # Code from module extern-inline:
62 # Code from module faccessat:
63 # Code from module fcntl-h:
61 # Code from module filemode: 64 # Code from module filemode:
62 # Code from module fpending: 65 # Code from module fpending:
66 # Code from module getgroups:
63 # Code from module getloadavg: 67 # Code from module getloadavg:
64 # Code from module getopt-gnu: 68 # Code from module getopt-gnu:
65 # Code from module getopt-posix: 69 # Code from module getopt-posix:
66 # Code from module gettext-h: 70 # Code from module gettext-h:
67 # Code from module gettime: 71 # Code from module gettime:
68 # Code from module gettimeofday: 72 # Code from module gettimeofday:
73 # Code from module group-member:
69 # Code from module ignore-value: 74 # Code from module ignore-value:
70 # Code from module include_next: 75 # Code from module include_next:
71 # Code from module intprops: 76 # Code from module intprops:
@@ -81,6 +86,7 @@ AC_DEFUN([gl_EARLY],
81 # Code from module pselect: 86 # Code from module pselect:
82 # Code from module pthread_sigmask: 87 # Code from module pthread_sigmask:
83 # Code from module readlink: 88 # Code from module readlink:
89 # Code from module root-uid:
84 # Code from module signal-h: 90 # Code from module signal-h:
85 # Code from module snippet/_Noreturn: 91 # Code from module snippet/_Noreturn:
86 # Code from module snippet/arg-nonnull: 92 # Code from module snippet/arg-nonnull:
@@ -122,6 +128,7 @@ AC_DEFUN([gl_EARLY],
122 # Code from module utimens: 128 # Code from module utimens:
123 # Code from module verify: 129 # Code from module verify:
124 # Code from module warnings: 130 # Code from module warnings:
131 # Code from module xalloc-oversized:
125]) 132])
126 133
127# This macro should be invoked from ./configure.ac, in the section 134# This macro should be invoked from ./configure.ac, in the section
@@ -160,6 +167,14 @@ AC_DEFUN([gl_INIT],
160 gl_UNISTD_MODULE_INDICATOR([environ]) 167 gl_UNISTD_MODULE_INDICATOR([environ])
161 gl_EXECINFO_H 168 gl_EXECINFO_H
162 AC_REQUIRE([gl_EXTERN_INLINE]) 169 AC_REQUIRE([gl_EXTERN_INLINE])
170 gl_FUNC_FACCESSAT
171 if test $HAVE_FACCESSAT = 0; then
172 AC_LIBOBJ([faccessat])
173 gl_PREREQ_FACCESSAT
174 fi
175 gl_MODULE_INDICATOR([faccessat])
176 gl_UNISTD_MODULE_INDICATOR([faccessat])
177 gl_FCNTL_H
163 gl_FILEMODE 178 gl_FILEMODE
164 gl_FUNC_FPENDING 179 gl_FUNC_FPENDING
165 if test $ac_cv_func___fpending = no; then 180 if test $ac_cv_func___fpending = no; then
@@ -278,18 +293,53 @@ AC_DEFUN([gl_INIT],
278 gl_UNISTD_H 293 gl_UNISTD_H
279 gl_UTIMENS 294 gl_UTIMENS
280 gl_gnulib_enabled_dosname=false 295 gl_gnulib_enabled_dosname=false
296 gl_gnulib_enabled_euidaccess=false
297 gl_gnulib_enabled_getgroups=false
281 gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false 298 gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
299 gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=false
282 gl_gnulib_enabled_pathmax=false 300 gl_gnulib_enabled_pathmax=false
301 gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
283 gl_gnulib_enabled_stat=false 302 gl_gnulib_enabled_stat=false
284 gl_gnulib_enabled_strtoll=false 303 gl_gnulib_enabled_strtoll=false
285 gl_gnulib_enabled_strtoull=false 304 gl_gnulib_enabled_strtoull=false
286 gl_gnulib_enabled_verify=false 305 gl_gnulib_enabled_verify=false
306 gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
287 func_gl_gnulib_m4code_dosname () 307 func_gl_gnulib_m4code_dosname ()
288 { 308 {
289 if ! $gl_gnulib_enabled_dosname; then 309 if ! $gl_gnulib_enabled_dosname; then
290 gl_gnulib_enabled_dosname=true 310 gl_gnulib_enabled_dosname=true
291 fi 311 fi
292 } 312 }
313 func_gl_gnulib_m4code_euidaccess ()
314 {
315 if ! $gl_gnulib_enabled_euidaccess; then
316 gl_FUNC_EUIDACCESS
317 if test $HAVE_EUIDACCESS = 0; then
318 AC_LIBOBJ([euidaccess])
319 gl_PREREQ_EUIDACCESS
320 fi
321 gl_UNISTD_MODULE_INDICATOR([euidaccess])
322 gl_gnulib_enabled_euidaccess=true
323 if test $HAVE_EUIDACCESS = 0; then
324 func_gl_gnulib_m4code_a9786850e999ae65a836a6041e8e5ed1
325 fi
326 func_gl_gnulib_m4code_6099e9737f757db36c47fa9d9f02e88c
327 if test $HAVE_EUIDACCESS = 0; then
328 func_gl_gnulib_m4code_stat
329 fi
330 fi
331 }
332 func_gl_gnulib_m4code_getgroups ()
333 {
334 if ! $gl_gnulib_enabled_getgroups; then
335 gl_FUNC_GETGROUPS
336 if test $HAVE_GETGROUPS = 0 || test $REPLACE_GETGROUPS = 1; then
337 AC_LIBOBJ([getgroups])
338 fi
339 gl_UNISTD_MODULE_INDICATOR([getgroups])
340 gl_gnulib_enabled_getgroups=true
341 fi
342 }
293 func_gl_gnulib_m4code_be453cec5eecf5731a274f2de7f2db36 () 343 func_gl_gnulib_m4code_be453cec5eecf5731a274f2de7f2db36 ()
294 { 344 {
295 if ! $gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36; then 345 if ! $gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36; then
@@ -298,6 +348,24 @@ AC_DEFUN([gl_INIT],
298 gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=true 348 gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=true
299 fi 349 fi
300 } 350 }
351 func_gl_gnulib_m4code_a9786850e999ae65a836a6041e8e5ed1 ()
352 {
353 if ! $gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1; then
354 gl_FUNC_GROUP_MEMBER
355 if test $HAVE_GROUP_MEMBER = 0; then
356 AC_LIBOBJ([group-member])
357 gl_PREREQ_GROUP_MEMBER
358 fi
359 gl_UNISTD_MODULE_INDICATOR([group-member])
360 gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=true
361 if test $HAVE_GROUP_MEMBER = 0; then
362 func_gl_gnulib_m4code_getgroups
363 fi
364 if test $HAVE_GROUP_MEMBER = 0; then
365 func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec
366 fi
367 fi
368 }
301 func_gl_gnulib_m4code_pathmax () 369 func_gl_gnulib_m4code_pathmax ()
302 { 370 {
303 if ! $gl_gnulib_enabled_pathmax; then 371 if ! $gl_gnulib_enabled_pathmax; then
@@ -305,6 +373,12 @@ AC_DEFUN([gl_INIT],
305 gl_gnulib_enabled_pathmax=true 373 gl_gnulib_enabled_pathmax=true
306 fi 374 fi
307 } 375 }
376 func_gl_gnulib_m4code_6099e9737f757db36c47fa9d9f02e88c ()
377 {
378 if ! $gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c; then
379 gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=true
380 fi
381 }
308 func_gl_gnulib_m4code_stat () 382 func_gl_gnulib_m4code_stat ()
309 { 383 {
310 if ! $gl_gnulib_enabled_stat; then 384 if ! $gl_gnulib_enabled_stat; then
@@ -356,6 +430,18 @@ AC_DEFUN([gl_INIT],
356 gl_gnulib_enabled_verify=true 430 gl_gnulib_enabled_verify=true
357 fi 431 fi
358 } 432 }
433 func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
434 {
435 if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
436 gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=true
437 fi
438 }
439 if test $HAVE_FACCESSAT = 0; then
440 func_gl_gnulib_m4code_dosname
441 fi
442 if test $HAVE_FACCESSAT = 0; then
443 func_gl_gnulib_m4code_euidaccess
444 fi
359 if test $REPLACE_GETOPT = 1; then 445 if test $REPLACE_GETOPT = 1; then
360 func_gl_gnulib_m4code_be453cec5eecf5731a274f2de7f2db36 446 func_gl_gnulib_m4code_be453cec5eecf5731a274f2de7f2db36
361 fi 447 fi
@@ -382,12 +468,17 @@ AC_DEFUN([gl_INIT],
382 fi 468 fi
383 m4_pattern_allow([^gl_GNULIB_ENABLED_]) 469 m4_pattern_allow([^gl_GNULIB_ENABLED_])
384 AM_CONDITIONAL([gl_GNULIB_ENABLED_dosname], [$gl_gnulib_enabled_dosname]) 470 AM_CONDITIONAL([gl_GNULIB_ENABLED_dosname], [$gl_gnulib_enabled_dosname])
471 AM_CONDITIONAL([gl_GNULIB_ENABLED_euidaccess], [$gl_gnulib_enabled_euidaccess])
472 AM_CONDITIONAL([gl_GNULIB_ENABLED_getgroups], [$gl_gnulib_enabled_getgroups])
385 AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36]) 473 AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36])
474 AM_CONDITIONAL([gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1], [$gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1])
386 AM_CONDITIONAL([gl_GNULIB_ENABLED_pathmax], [$gl_gnulib_enabled_pathmax]) 475 AM_CONDITIONAL([gl_GNULIB_ENABLED_pathmax], [$gl_gnulib_enabled_pathmax])
476 AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
387 AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat]) 477 AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat])
388 AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll]) 478 AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
389 AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull]) 479 AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull])
390 AM_CONDITIONAL([gl_GNULIB_ENABLED_verify], [$gl_gnulib_enabled_verify]) 480 AM_CONDITIONAL([gl_GNULIB_ENABLED_verify], [$gl_gnulib_enabled_verify])
481 AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
391 # End of code from modules 482 # End of code from modules
392 m4_ifval(gl_LIBSOURCES_LIST, [ 483 m4_ifval(gl_LIBSOURCES_LIST, [
393 m4_syscmd([test ! -d ]m4_defn([gl_LIBSOURCES_DIR])[ || 484 m4_syscmd([test ! -d ]m4_defn([gl_LIBSOURCES_DIR])[ ||
@@ -536,6 +627,7 @@ AC_DEFUN([gl_FILE_LIST], [
536 lib/alloca.in.h 627 lib/alloca.in.h
537 lib/allocator.c 628 lib/allocator.c
538 lib/allocator.h 629 lib/allocator.h
630 lib/at-func.c
539 lib/c-ctype.c 631 lib/c-ctype.c
540 lib/c-ctype.h 632 lib/c-ctype.h
541 lib/c-strcase.h 633 lib/c-strcase.h
@@ -549,14 +641,18 @@ AC_DEFUN([gl_FILE_LIST], [
549 lib/dtoastr.c 641 lib/dtoastr.c
550 lib/dtotimespec.c 642 lib/dtotimespec.c
551 lib/dup2.c 643 lib/dup2.c
644 lib/euidaccess.c
552 lib/execinfo.c 645 lib/execinfo.c
553 lib/execinfo.in.h 646 lib/execinfo.in.h
647 lib/faccessat.c
648 lib/fcntl.in.h
554 lib/filemode.c 649 lib/filemode.c
555 lib/filemode.h 650 lib/filemode.h
556 lib/fpending.c 651 lib/fpending.c
557 lib/fpending.h 652 lib/fpending.h
558 lib/ftoastr.c 653 lib/ftoastr.c
559 lib/ftoastr.h 654 lib/ftoastr.h
655 lib/getgroups.c
560 lib/getloadavg.c 656 lib/getloadavg.c
561 lib/getopt.c 657 lib/getopt.c
562 lib/getopt.in.h 658 lib/getopt.in.h
@@ -565,6 +661,7 @@ AC_DEFUN([gl_FILE_LIST], [
565 lib/gettext.h 661 lib/gettext.h
566 lib/gettime.c 662 lib/gettime.c
567 lib/gettimeofday.c 663 lib/gettimeofday.c
664 lib/group-member.c
568 lib/ignore-value.h 665 lib/ignore-value.h
569 lib/intprops.h 666 lib/intprops.h
570 lib/inttypes.in.h 667 lib/inttypes.in.h
@@ -577,6 +674,7 @@ AC_DEFUN([gl_FILE_LIST], [
577 lib/pselect.c 674 lib/pselect.c
578 lib/pthread_sigmask.c 675 lib/pthread_sigmask.c
579 lib/readlink.c 676 lib/readlink.c
677 lib/root-uid.h
580 lib/sha1.c 678 lib/sha1.c
581 lib/sha1.h 679 lib/sha1.h
582 lib/sha256.c 680 lib/sha256.c
@@ -618,6 +716,7 @@ AC_DEFUN([gl_FILE_LIST], [
618 lib/utimens.c 716 lib/utimens.c
619 lib/utimens.h 717 lib/utimens.h
620 lib/verify.h 718 lib/verify.h
719 lib/xalloc-oversized.h
621 m4/00gnulib.m4 720 m4/00gnulib.m4
622 m4/alloca.m4 721 m4/alloca.m4
623 m4/c-strtod.m4 722 m4/c-strtod.m4
@@ -625,16 +724,22 @@ AC_DEFUN([gl_FILE_LIST], [
625 m4/close-stream.m4 724 m4/close-stream.m4
626 m4/dup2.m4 725 m4/dup2.m4
627 m4/environ.m4 726 m4/environ.m4
727 m4/euidaccess.m4
628 m4/execinfo.m4 728 m4/execinfo.m4
629 m4/extensions.m4 729 m4/extensions.m4
630 m4/extern-inline.m4 730 m4/extern-inline.m4
731 m4/faccessat.m4
732 m4/fcntl-o.m4
733 m4/fcntl_h.m4
631 m4/filemode.m4 734 m4/filemode.m4
632 m4/fpending.m4 735 m4/fpending.m4
736 m4/getgroups.m4
633 m4/getloadavg.m4 737 m4/getloadavg.m4
634 m4/getopt.m4 738 m4/getopt.m4
635 m4/gettime.m4 739 m4/gettime.m4
636 m4/gettimeofday.m4 740 m4/gettimeofday.m4
637 m4/gnulib-common.m4 741 m4/gnulib-common.m4
742 m4/group-member.m4
638 m4/include_next.m4 743 m4/include_next.m4
639 m4/inttypes.m4 744 m4/inttypes.m4
640 m4/largefile.m4 745 m4/largefile.m4
diff --git a/m4/group-member.m4 b/m4/group-member.m4
new file mode 100644
index 00000000000..c393b5b1303
--- /dev/null
+++ b/m4/group-member.m4
@@ -0,0 +1,29 @@
1# serial 14
2
3# Copyright (C) 1999-2001, 2003-2007, 2009-2012 Free Software Foundation, Inc.
4
5# This file is free software; the Free Software Foundation
6# gives unlimited permission to copy and/or distribute it,
7# with or without modifications, as long as this notice is preserved.
8
9dnl Written by Jim Meyering
10
11AC_DEFUN([gl_FUNC_GROUP_MEMBER],
12[
13 AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
14
15 dnl Persuade glibc <unistd.h> to declare group_member().
16 AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
17
18 dnl Do this replacement check manually because I want the hyphen
19 dnl (not the underscore) in the filename.
20 AC_CHECK_FUNC([group_member], , [
21 HAVE_GROUP_MEMBER=0
22 ])
23])
24
25# Prerequisites of lib/group-member.c.
26AC_DEFUN([gl_PREREQ_GROUP_MEMBER],
27[
28 AC_REQUIRE([AC_FUNC_GETGROUPS])
29])
diff --git a/nt/ChangeLog b/nt/ChangeLog
index 931cb745c8b..320c9e6366e 100644
--- a/nt/ChangeLog
+++ b/nt/ChangeLog
@@ -1,3 +1,10 @@
12012-11-14 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use faccessat, not access, when checking file permissions (Bug#12632).
4 * inc/ms-w32.h (AT_FDCWD, AT_EACCESS): New symbols.
5 (access): Remove.
6 (faccessat): New macro.
7
12012-11-05 Eli Zaretskii <eliz@gnu.org> 82012-11-05 Eli Zaretskii <eliz@gnu.org>
2 9
3 * inc/unistd.h (tcgetpgrp, setsid): Provide prototypes. 10 * inc/unistd.h (tcgetpgrp, setsid): Provide prototypes.
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index dd2ae781cb8..0f6b51d3915 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -124,6 +124,10 @@ extern char *getenv ();
124#define MAXPATHLEN _MAX_PATH 124#define MAXPATHLEN _MAX_PATH
125#endif 125#endif
126 126
127/* Use values compatible with gnulib, as there's no reason to differ. */
128#define AT_FDCWD (-3041965)
129#define AT_EACCESS 4
130
127#ifdef HAVE_NTGUI 131#ifdef HAVE_NTGUI
128#define HAVE_WINDOW_SYSTEM 1 132#define HAVE_WINDOW_SYSTEM 1
129#define HAVE_MENUS 1 133#define HAVE_MENUS 1
@@ -145,8 +149,6 @@ extern char *getenv ();
145#endif 149#endif
146 150
147/* Calls that are emulated or shadowed. */ 151/* Calls that are emulated or shadowed. */
148#undef access
149#define access sys_access
150#undef chdir 152#undef chdir
151#define chdir sys_chdir 153#define chdir sys_chdir
152#undef chmod 154#undef chmod
@@ -161,6 +163,7 @@ extern char *getenv ();
161#define dup sys_dup 163#define dup sys_dup
162#undef dup2 164#undef dup2
163#define dup2 sys_dup2 165#define dup2 sys_dup2
166#define faccessat sys_faccessat
164#define fopen sys_fopen 167#define fopen sys_fopen
165#define link sys_link 168#define link sys_link
166#define localtime sys_localtime 169#define localtime sys_localtime
diff --git a/src/ChangeLog b/src/ChangeLog
index 1d94cef6577..a6b42e8a58c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,70 @@
12012-11-14 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use faccessat, not access, when checking file permissions (Bug#12632).
4 This fixes a bug that has been present in Emacs since its creation.
5 It was reported by Chris Torek in 1983 even before GNU Emacs existed,
6 which must set some sort of record. (Torek's bug report was against
7 a predecessor of GNU Emacs, but GNU Emacs happened to have the
8 same common flaw.) See Torek's Usenet posting
9 "setuid/setgid programs & Emacs" Article-I.D.: sri-arpa.858
10 Posted: Fri Apr 8 14:18:56 1983.
11 * Makefile.in (LIB_EACCESS): New macro.
12 (LIBES): Use it.
13 * callproc.c (init_callproc):
14 * charset.c (init_charset):
15 * fileio.c (check_existing, check_executable, check_writable)
16 (Ffile_readable_p):
17 * lread.c (openp, load_path_check):
18 * process.c (allocate_pty):
19 * xrdb.c (file_p):
20 Use effective UID when checking permissions, not real UID.
21 * callproc.c (init_callproc):
22 * charset.c (init_charset):
23 * lread.c (load_path_check, init_lread):
24 Test whether directories are accessible, not merely whether they exist.
25 * conf_post.h (GNULIB_SUPPORT_ONLY_AT_FDCWD): New macro.
26 * fileio.c (check_existing, check_executable, check_writable)
27 (Ffile_readable_p):
28 Use symbolic names instead of integers for the flags, as they're
29 portable now.
30 (check_writable): New arg AMODE. All uses changed.
31 Set errno on failure.
32 (Ffile_readable_p): Use faccessat, not stat + open + close.
33 (Ffile_writable_p): No need to call check_existing + check_writable.
34 Just call check_writable and then look at errno. This saves a syscall.
35 dir should never be nil; replace an unnecessary runtime check
36 with an eassert. When checking the parent directory of a nonexistent
37 file, check that the directory is searchable as well as writable, as
38 we can't create files in unsearchable directories.
39 (file_directory_p): New function, which uses 'stat' on most platforms
40 but faccessat with D_OK (for efficiency) if WINDOWSNT.
41 (Ffile_directory_p, Fset_file_times): Use it.
42 (file_accessible_directory_p): New function, which uses a single
43 syscall for efficiency.
44 (Ffile_accessible_directory_p): Use it.
45 * xrdb.c (file_p): Use file_directory_p.
46 * lisp.h (file_directory_p, file_accessible_directory_p): New decls.
47 * lread.c (openp): When opening a file, use fstat rather than
48 stat, as that avoids a permissions race. When not opening a file,
49 use file_directory_p rather than stat.
50 (dir_warning): First arg is now a usage string, not a format.
51 Use errno. All uses changed.
52 * nsterm.m (ns_term_init): Remove unnecessary call to file-readable
53 that merely introduced a race.
54 * process.c, sysdep.c, term.c: All uses of '#ifdef O_NONBLOCK'
55 changed to '#if O_NONBLOCK', to accommodate gnulib O_* style,
56 and similarly for the other O_* flags.
57 * w32.c (sys_faccessat): Rename from sys_access and switch to
58 faccessat's API. All uses changed.
59 * xrdb.c: Do not include <sys/stat.h>; no longer needed.
60 (magic_db): Rename from magic_file_p.
61 (magic_db, search_magic_path): Return an XrmDatabase rather than a
62 char *, so that we don't have to test for file existence
63 separately from opening the file for reading. This removes a race
64 fixes a permission-checking problem, and simplifies the code.
65 All uses changed.
66 (file_p): Remove; no longer needed.
67
12012-11-13 Dmitry Antipov <dmantipov@yandex.ru> 682012-11-13 Dmitry Antipov <dmantipov@yandex.ru>
2 69
3 Omit glyphs initialization at startup. 70 Omit glyphs initialization at startup.
diff --git a/src/Makefile.in b/src/Makefile.in
index c24e421bbbc..d034ad04796 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -150,6 +150,7 @@ M17N_FLT_CFLAGS = @M17N_FLT_CFLAGS@
150M17N_FLT_LIBS = @M17N_FLT_LIBS@ 150M17N_FLT_LIBS = @M17N_FLT_LIBS@
151 151
152LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@ 152LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
153LIB_EACCESS=@LIB_EACCESS@
153LIB_TIMER_TIME=@LIB_TIMER_TIME@ 154LIB_TIMER_TIME=@LIB_TIMER_TIME@
154 155
155DBUS_CFLAGS = @DBUS_CFLAGS@ 156DBUS_CFLAGS = @DBUS_CFLAGS@
@@ -392,7 +393,7 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
392LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \ 393LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \
393 $(LIBX_OTHER) $(LIBSOUND) \ 394 $(LIBX_OTHER) $(LIBSOUND) \
394 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \ 395 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_CLOCK_GETTIME) \
395 $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 396 $(LIB_EACCESS) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
396 $(LIB_EXECINFO) \ 397 $(LIB_EXECINFO) \
397 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ 398 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
398 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 399 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
diff --git a/src/callproc.c b/src/callproc.c
index c7bbe36e605..8ecaba2b408 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1576,15 +1576,13 @@ init_callproc (void)
1576#endif 1576#endif
1577 { 1577 {
1578 tempdir = Fdirectory_file_name (Vexec_directory); 1578 tempdir = Fdirectory_file_name (Vexec_directory);
1579 if (access (SSDATA (tempdir), 0) < 0) 1579 if (! file_accessible_directory_p (SSDATA (tempdir)))
1580 dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n", 1580 dir_warning ("arch-dependent data dir", Vexec_directory);
1581 Vexec_directory);
1582 } 1581 }
1583 1582
1584 tempdir = Fdirectory_file_name (Vdata_directory); 1583 tempdir = Fdirectory_file_name (Vdata_directory);
1585 if (access (SSDATA (tempdir), 0) < 0) 1584 if (! file_accessible_directory_p (SSDATA (tempdir)))
1586 dir_warning ("Warning: arch-independent data dir (%s) does not exist.\n", 1585 dir_warning ("arch-independent data dir", Vdata_directory);
1587 Vdata_directory);
1588 1586
1589 sh = (char *) getenv ("SHELL"); 1587 sh = (char *) getenv ("SHELL");
1590 Vshell_file_name = build_string (sh ? sh : "/bin/sh"); 1588 Vshell_file_name = build_string (sh ? sh : "/bin/sh");
@@ -1593,7 +1591,7 @@ init_callproc (void)
1593 Vshared_game_score_directory = Qnil; 1591 Vshared_game_score_directory = Qnil;
1594#else 1592#else
1595 Vshared_game_score_directory = build_string (PATH_GAME); 1593 Vshared_game_score_directory = build_string (PATH_GAME);
1596 if (NILP (Ffile_directory_p (Vshared_game_score_directory))) 1594 if (NILP (Ffile_accessible_directory_p (Vshared_game_score_directory)))
1597 Vshared_game_score_directory = Qnil; 1595 Vshared_game_score_directory = Qnil;
1598#endif 1596#endif
1599} 1597}
diff --git a/src/charset.c b/src/charset.c
index 6b999824dab..c9133c780e8 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -2293,7 +2293,7 @@ init_charset (void)
2293{ 2293{
2294 Lisp_Object tempdir; 2294 Lisp_Object tempdir;
2295 tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory); 2295 tempdir = Fexpand_file_name (build_string ("charsets"), Vdata_directory);
2296 if (access (SSDATA (tempdir), 0) < 0) 2296 if (! file_accessible_directory_p (SSDATA (tempdir)))
2297 { 2297 {
2298 /* This used to be non-fatal (dir_warning), but it should not 2298 /* This used to be non-fatal (dir_warning), but it should not
2299 happen, and if it does sooner or later it will cause some 2299 happen, and if it does sooner or later it will cause some
diff --git a/src/conf_post.h b/src/conf_post.h
index 66390ddf103..b1997e79081 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -178,6 +178,10 @@ extern void _DebPrint (const char *fmt, ...);
178#endif 178#endif
179#endif 179#endif
180 180
181/* Tell gnulib to omit support for openat-related functions having a
182 first argument other than AT_FDCWD. */
183#define GNULIB_SUPPORT_ONLY_AT_FDCWD
184
181#include <string.h> 185#include <string.h>
182#include <stdlib.h> 186#include <stdlib.h>
183 187
diff --git a/src/fileio.c b/src/fileio.c
index b9541e78838..572f6d8ef83 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2425,15 +2425,7 @@ On Unix, this is a name starting with a `/' or a `~'. */)
2425bool 2425bool
2426check_existing (const char *filename) 2426check_existing (const char *filename)
2427{ 2427{
2428#ifdef DOS_NT 2428 return faccessat (AT_FDCWD, filename, F_OK, AT_EACCESS) == 0;
2429 /* The full emulation of Posix 'stat' is too expensive on
2430 DOS/Windows, when all we want to know is whether the file exists.
2431 So we use 'access' instead, which is much more lightweight. */
2432 return (access (filename, F_OK) >= 0);
2433#else
2434 struct stat st;
2435 return (stat (filename, &st) >= 0);
2436#endif
2437} 2429}
2438 2430
2439/* Return true if file FILENAME exists and can be executed. */ 2431/* Return true if file FILENAME exists and can be executed. */
@@ -2441,56 +2433,40 @@ check_existing (const char *filename)
2441static bool 2433static bool
2442check_executable (char *filename) 2434check_executable (char *filename)
2443{ 2435{
2444#ifdef DOS_NT 2436 return faccessat (AT_FDCWD, filename, X_OK, AT_EACCESS) == 0;
2445 struct stat st;
2446 if (stat (filename, &st) < 0)
2447 return 0;
2448 return ((st.st_mode & S_IEXEC) != 0);
2449#else /* not DOS_NT */
2450#ifdef HAVE_EUIDACCESS
2451 return (euidaccess (filename, 1) >= 0);
2452#else
2453 /* Access isn't quite right because it uses the real uid
2454 and we really want to test with the effective uid.
2455 But Unix doesn't give us a right way to do it. */
2456 return (access (filename, 1) >= 0);
2457#endif
2458#endif /* not DOS_NT */
2459} 2437}
2460 2438
2461/* Return true if file FILENAME exists and can be written. */ 2439/* Return true if file FILENAME exists and can be accessed
2440 according to AMODE, which should include W_OK.
2441 On failure, return false and set errno. */
2462 2442
2463static bool 2443static bool
2464check_writable (const char *filename) 2444check_writable (const char *filename, int amode)
2465{ 2445{
2466#ifdef MSDOS 2446#ifdef MSDOS
2447 /* FIXME: an faccessat implementation should be added to the
2448 DOS/Windows ports and this #ifdef branch should be removed. */
2467 struct stat st; 2449 struct stat st;
2468 if (stat (filename, &st) < 0) 2450 if (stat (filename, &st) < 0)
2469 return 0; 2451 return 0;
2452 errno = EPERM;
2470 return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode)); 2453 return (st.st_mode & S_IWRITE || S_ISDIR (st.st_mode));
2471#else /* not MSDOS */ 2454#else /* not MSDOS */
2472#ifdef HAVE_EUIDACCESS 2455 bool res = faccessat (AT_FDCWD, filename, amode, AT_EACCESS) == 0;
2473 bool res = (euidaccess (filename, 2) >= 0);
2474#ifdef CYGWIN 2456#ifdef CYGWIN
2475 /* euidaccess may have returned failure because Cygwin couldn't 2457 /* faccessat may have returned failure because Cygwin couldn't
2476 determine the file's UID or GID; if so, we return success. */ 2458 determine the file's UID or GID; if so, we return success. */
2477 if (!res) 2459 if (!res)
2478 { 2460 {
2461 int faccessat_errno = errno;
2479 struct stat st; 2462 struct stat st;
2480 if (stat (filename, &st) < 0) 2463 if (stat (filename, &st) < 0)
2481 return 0; 2464 return 0;
2482 res = (st.st_uid == -1 || st.st_gid == -1); 2465 res = (st.st_uid == -1 || st.st_gid == -1);
2466 errno = faccessat_errno;
2483 } 2467 }
2484#endif /* CYGWIN */ 2468#endif /* CYGWIN */
2485 return res; 2469 return res;
2486#else /* not HAVE_EUIDACCESS */
2487 /* Access isn't quite right because it uses the real uid
2488 and we really want to test with the effective uid.
2489 But Unix doesn't give us a right way to do it.
2490 Opening with O_WRONLY could work for an ordinary file,
2491 but would lose for directories. */
2492 return (access (filename, 2) >= 0);
2493#endif /* not HAVE_EUIDACCESS */
2494#endif /* not MSDOS */ 2470#endif /* not MSDOS */
2495} 2471}
2496 2472
@@ -2547,9 +2523,6 @@ See also `file-exists-p' and `file-attributes'. */)
2547{ 2523{
2548 Lisp_Object absname; 2524 Lisp_Object absname;
2549 Lisp_Object handler; 2525 Lisp_Object handler;
2550 int desc;
2551 int flags;
2552 struct stat statbuf;
2553 2526
2554 CHECK_STRING (filename); 2527 CHECK_STRING (filename);
2555 absname = Fexpand_file_name (filename, Qnil); 2528 absname = Fexpand_file_name (filename, Qnil);
@@ -2561,35 +2534,10 @@ See also `file-exists-p' and `file-attributes'. */)
2561 return call2 (handler, Qfile_readable_p, absname); 2534 return call2 (handler, Qfile_readable_p, absname);
2562 2535
2563 absname = ENCODE_FILE (absname); 2536 absname = ENCODE_FILE (absname);
2564 2537 return (faccessat (AT_FDCWD, SSDATA (absname), R_OK, AT_EACCESS) == 0
2565#if defined (DOS_NT) || defined (macintosh) 2538 ? Qt : Qnil);
2566 /* Under MS-DOS, Windows, and Macintosh, open does not work for
2567 directories. */
2568 if (access (SDATA (absname), 0) == 0)
2569 return Qt;
2570 return Qnil;
2571#else /* not DOS_NT and not macintosh */
2572 flags = O_RDONLY;
2573#ifdef O_NONBLOCK
2574 /* Opening a fifo without O_NONBLOCK can wait.
2575 We don't want to wait. But we don't want to mess wth O_NONBLOCK
2576 except in the case of a fifo, on a system which handles it. */
2577 desc = stat (SSDATA (absname), &statbuf);
2578 if (desc < 0)
2579 return Qnil;
2580 if (S_ISFIFO (statbuf.st_mode))
2581 flags |= O_NONBLOCK;
2582#endif
2583 desc = emacs_open (SSDATA (absname), flags, 0);
2584 if (desc < 0)
2585 return Qnil;
2586 emacs_close (desc);
2587 return Qt;
2588#endif /* not DOS_NT and not macintosh */
2589} 2539}
2590 2540
2591/* Having this before file-symlink-p mysteriously caused it to be forgotten
2592 on the RT/PC. */
2593DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0, 2541DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2594 doc: /* Return t if file FILENAME can be written or created by you. */) 2542 doc: /* Return t if file FILENAME can be written or created by you. */)
2595 (Lisp_Object filename) 2543 (Lisp_Object filename)
@@ -2607,14 +2555,15 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2607 return call2 (handler, Qfile_writable_p, absname); 2555 return call2 (handler, Qfile_writable_p, absname);
2608 2556
2609 encoded = ENCODE_FILE (absname); 2557 encoded = ENCODE_FILE (absname);
2610 if (check_existing (SSDATA (encoded))) 2558 if (check_writable (SSDATA (encoded), W_OK))
2611 return (check_writable (SSDATA (encoded)) 2559 return Qt;
2612 ? Qt : Qnil); 2560 if (errno != ENOENT)
2561 return Qnil;
2613 2562
2614 dir = Ffile_name_directory (absname); 2563 dir = Ffile_name_directory (absname);
2564 eassert (!NILP (dir));
2615#ifdef MSDOS 2565#ifdef MSDOS
2616 if (!NILP (dir)) 2566 dir = Fdirectory_file_name (dir);
2617 dir = Fdirectory_file_name (dir);
2618#endif /* MSDOS */ 2567#endif /* MSDOS */
2619 2568
2620 dir = ENCODE_FILE (dir); 2569 dir = ENCODE_FILE (dir);
@@ -2622,10 +2571,9 @@ DEFUN ("file-writable-p", Ffile_writable_p, Sfile_writable_p, 1, 1, 0,
2622 /* The read-only attribute of the parent directory doesn't affect 2571 /* The read-only attribute of the parent directory doesn't affect
2623 whether a file or directory can be created within it. Some day we 2572 whether a file or directory can be created within it. Some day we
2624 should check ACLs though, which do affect this. */ 2573 should check ACLs though, which do affect this. */
2625 return (access (SDATA (dir), D_OK) < 0) ? Qnil : Qt; 2574 return file_directory_p (SDATA (dir)) ? Qt : Qnil;
2626#else 2575#else
2627 return (check_writable (!NILP (dir) ? SSDATA (dir) : "") 2576 return check_writable (SSDATA (dir), W_OK | X_OK) ? Qt : Qnil;
2628 ? Qt : Qnil);
2629#endif 2577#endif
2630} 2578}
2631 2579
@@ -2703,8 +2651,7 @@ Symbolic links to directories count as directories.
2703See `file-symlink-p' to distinguish symlinks. */) 2651See `file-symlink-p' to distinguish symlinks. */)
2704 (Lisp_Object filename) 2652 (Lisp_Object filename)
2705{ 2653{
2706 register Lisp_Object absname; 2654 Lisp_Object absname;
2707 struct stat st;
2708 Lisp_Object handler; 2655 Lisp_Object handler;
2709 2656
2710 absname = expand_and_dir_to_file (filename, BVAR (current_buffer, directory)); 2657 absname = expand_and_dir_to_file (filename, BVAR (current_buffer, directory));
@@ -2717,9 +2664,20 @@ See `file-symlink-p' to distinguish symlinks. */)
2717 2664
2718 absname = ENCODE_FILE (absname); 2665 absname = ENCODE_FILE (absname);
2719 2666
2720 if (stat (SSDATA (absname), &st) < 0) 2667 return file_directory_p (SSDATA (absname)) ? Qt : Qnil;
2721 return Qnil; 2668}
2722 return S_ISDIR (st.st_mode) ? Qt : Qnil; 2669
2670/* Return true if FILE is a directory or a symlink to a directory. */
2671bool
2672file_directory_p (char const *file)
2673{
2674#ifdef WINDOWSNT
2675 /* This is cheaper than 'stat'. */
2676 return faccessat (AT_FDCWD, file, D_OK, AT_EACCESS) == 0;
2677#else
2678 struct stat st;
2679 return stat (file, &st) == 0 && S_ISDIR (st.st_mode);
2680#endif
2723} 2681}
2724 2682
2725DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p, 2683DEFUN ("file-accessible-directory-p", Ffile_accessible_directory_p,
@@ -2733,21 +2691,65 @@ if the directory so specified exists and really is a readable and
2733searchable directory. */) 2691searchable directory. */)
2734 (Lisp_Object filename) 2692 (Lisp_Object filename)
2735{ 2693{
2694 Lisp_Object absname;
2736 Lisp_Object handler; 2695 Lisp_Object handler;
2737 bool tem; 2696
2738 struct gcpro gcpro1; 2697 CHECK_STRING (filename);
2698 absname = Fexpand_file_name (filename, Qnil);
2739 2699
2740 /* If the file name has special constructs in it, 2700 /* If the file name has special constructs in it,
2741 call the corresponding file handler. */ 2701 call the corresponding file handler. */
2742 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); 2702 handler = Ffind_file_name_handler (absname, Qfile_accessible_directory_p);
2743 if (!NILP (handler)) 2703 if (!NILP (handler))
2744 return call2 (handler, Qfile_accessible_directory_p, filename); 2704 return call2 (handler, Qfile_accessible_directory_p, absname);
2745 2705
2746 GCPRO1 (filename); 2706 absname = ENCODE_FILE (absname);
2747 tem = (NILP (Ffile_directory_p (filename)) 2707 return file_accessible_directory_p (SSDATA (absname)) ? Qt : Qnil;
2748 || NILP (Ffile_executable_p (filename))); 2708}
2749 UNGCPRO; 2709
2750 return tem ? Qnil : Qt; 2710/* If FILE is a searchable directory or a symlink to a
2711 searchable directory, return true. Otherwise return
2712 false and set errno to an error number. */
2713bool
2714file_accessible_directory_p (char const *file)
2715{
2716#ifdef DOS_NT
2717 /* There's no need to test whether FILE is searchable, as the
2718 searchable/executable bit is invented on DOS_NT platforms. */
2719 return file_directory_p (file);
2720#else
2721 /* On POSIXish platforms, use just one system call; this avoids a
2722 race and is typically faster. */
2723 ptrdiff_t len = strlen (file);
2724 char const *dir;
2725 bool ok;
2726 int saved_errno;
2727 USE_SAFE_ALLOCA;
2728
2729 /* Normally a file "FOO" is an accessible directory if "FOO/." exists.
2730 There are three exceptions: "", "/", and "//". Leave "" alone,
2731 as it's invalid. Append only "." to the other two exceptions as
2732 "/" and "//" are distinct on some platforms, whereas "/", "///",
2733 "////", etc. are all equivalent. */
2734 if (! len)
2735 dir = file;
2736 else
2737 {
2738 /* Just check for trailing '/' when deciding whether to append '/'.
2739 That's simpler than testing the two special cases "/" and "//",
2740 and it's a safe optimization here. */
2741 char *buf = SAFE_ALLOCA (len + 3);
2742 memcpy (buf, file, len);
2743 strcpy (buf + len, "/." + (file[len - 1] == '/'));
2744 dir = buf;
2745 }
2746
2747 ok = check_existing (dir);
2748 saved_errno = errno;
2749 SAFE_FREE ();
2750 errno = saved_errno;
2751 return ok;
2752#endif
2751} 2753}
2752 2754
2753DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0, 2755DEFUN ("file-regular-p", Ffile_regular_p, Sfile_regular_p, 1, 1, 0,
@@ -3044,10 +3046,8 @@ Use the current time if TIMESTAMP is nil. TIMESTAMP is in the format of
3044 if (set_file_times (-1, SSDATA (encoded_absname), t, t)) 3046 if (set_file_times (-1, SSDATA (encoded_absname), t, t))
3045 { 3047 {
3046#ifdef MSDOS 3048#ifdef MSDOS
3047 struct stat st;
3048
3049 /* Setting times on a directory always fails. */ 3049 /* Setting times on a directory always fails. */
3050 if (stat (SSDATA (encoded_absname), &st) == 0 && S_ISDIR (st.st_mode)) 3050 if (file_directory_p (SSDATA (encoded_absname)))
3051 return Qnil; 3051 return Qnil;
3052#endif 3052#endif
3053 report_file_error ("Setting file times", Fcons (absname, Qnil)); 3053 report_file_error ("Setting file times", Fcons (absname, Qnil));
diff --git a/src/lisp.h b/src/lisp.h
index 72e38fa4653..67ae28a488f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3202,6 +3202,8 @@ extern Lisp_Object close_file_unwind (Lisp_Object);
3202extern Lisp_Object restore_point_unwind (Lisp_Object); 3202extern Lisp_Object restore_point_unwind (Lisp_Object);
3203extern _Noreturn void report_file_error (const char *, Lisp_Object); 3203extern _Noreturn void report_file_error (const char *, Lisp_Object);
3204extern void internal_delete_file (Lisp_Object); 3204extern void internal_delete_file (Lisp_Object);
3205extern bool file_directory_p (const char *);
3206extern bool file_accessible_directory_p (const char *);
3205extern void syms_of_fileio (void); 3207extern void syms_of_fileio (void);
3206extern Lisp_Object make_temp_name (Lisp_Object, bool); 3208extern Lisp_Object make_temp_name (Lisp_Object, bool);
3207extern Lisp_Object Qdelete_file; 3209extern Lisp_Object Qdelete_file;
diff --git a/src/lread.c b/src/lread.c
index 3a82e0057e2..5859a2f85a9 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1403,7 +1403,7 @@ Returns the file's name in absolute form, or nil if not found.
1403If SUFFIXES is non-nil, it should be a list of suffixes to append to 1403If SUFFIXES is non-nil, it should be a list of suffixes to append to
1404file name when searching. 1404file name when searching.
1405If non-nil, PREDICATE is used instead of `file-readable-p'. 1405If non-nil, PREDICATE is used instead of `file-readable-p'.
1406PREDICATE can also be an integer to pass to the access(2) function, 1406PREDICATE can also be an integer to pass to the faccessat(2) function,
1407in which case file-name-handlers are ignored. 1407in which case file-name-handlers are ignored.
1408This function will normally skip directories, so if you want it to find 1408This function will normally skip directories, so if you want it to find
1409directories, make sure the PREDICATE function returns `dir-ok' for them. */) 1409directories, make sure the PREDICATE function returns `dir-ok' for them. */)
@@ -1441,7 +1441,6 @@ static Lisp_Object Qdir_ok;
1441int 1441int
1442openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate) 1442openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate)
1443{ 1443{
1444 int fd;
1445 ptrdiff_t fn_size = 100; 1444 ptrdiff_t fn_size = 100;
1446 char buf[100]; 1445 char buf[100];
1447 char *fn = buf; 1446 char *fn = buf;
@@ -1496,7 +1495,6 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1496 { 1495 {
1497 ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail)); 1496 ptrdiff_t fnlen, lsuffix = SBYTES (XCAR (tail));
1498 Lisp_Object handler; 1497 Lisp_Object handler;
1499 bool exists;
1500 1498
1501 /* Concatenate path element/specified name with the suffix. 1499 /* Concatenate path element/specified name with the suffix.
1502 If the directory starts with /:, remove that. */ 1500 If the directory starts with /:, remove that. */
@@ -1520,6 +1518,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1520 handler = Ffind_file_name_handler (string, Qfile_exists_p); 1518 handler = Ffind_file_name_handler (string, Qfile_exists_p);
1521 if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) 1519 if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate))
1522 { 1520 {
1521 bool exists;
1523 if (NILP (predicate)) 1522 if (NILP (predicate))
1524 exists = !NILP (Ffile_readable_p (string)); 1523 exists = !NILP (Ffile_readable_p (string));
1525 else 1524 else
@@ -1541,37 +1540,40 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object *sto
1541 } 1540 }
1542 else 1541 else
1543 { 1542 {
1544#ifndef WINDOWSNT 1543 int fd;
1545 struct stat st;
1546#endif
1547 const char *pfn; 1544 const char *pfn;
1548 1545
1549 encoded_fn = ENCODE_FILE (string); 1546 encoded_fn = ENCODE_FILE (string);
1550 pfn = SSDATA (encoded_fn); 1547 pfn = SSDATA (encoded_fn);
1551#ifdef WINDOWSNT
1552 exists = access (pfn, F_OK) == 0 && access (pfn, D_OK) < 0;
1553#else
1554 exists = (stat (pfn, &st) == 0 && ! S_ISDIR (st.st_mode));
1555#endif
1556 if (exists)
1557 {
1558 /* Check that we can access or open it. */
1559 if (NATNUMP (predicate))
1560 fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
1561 && access (pfn, XFASTINT (predicate)) == 0)
1562 ? 1 : -1);
1563 else
1564 fd = emacs_open (pfn, O_RDONLY, 0);
1565 1548
1566 if (fd >= 0) 1549 /* Check that we can access or open it. */
1550 if (NATNUMP (predicate))
1551 fd = (((XFASTINT (predicate) & ~INT_MAX) == 0
1552 && (faccessat (AT_FDCWD, pfn, XFASTINT (predicate),
1553 AT_EACCESS)
1554 == 0)
1555 && ! file_directory_p (pfn))
1556 ? 1 : -1);
1557 else
1558 {
1559 struct stat st;
1560 fd = emacs_open (pfn, O_RDONLY, 0);
1561 if (0 <= fd
1562 && (fstat (fd, &st) != 0 || S_ISDIR (st.st_mode)))
1567 { 1563 {
1568 /* We succeeded; return this descriptor and filename. */ 1564 emacs_close (fd);
1569 if (storeptr) 1565 fd = -1;
1570 *storeptr = string;
1571 UNGCPRO;
1572 return fd;
1573 } 1566 }
1574 } 1567 }
1568
1569 if (fd >= 0)
1570 {
1571 /* We succeeded; return this descriptor and filename. */
1572 if (storeptr)
1573 *storeptr = string;
1574 UNGCPRO;
1575 return fd;
1576 }
1575 } 1577 }
1576 } 1578 }
1577 if (absolute) 1579 if (absolute)
@@ -4087,9 +4089,8 @@ load_path_check (void)
4087 if (STRINGP (dirfile)) 4089 if (STRINGP (dirfile))
4088 { 4090 {
4089 dirfile = Fdirectory_file_name (dirfile); 4091 dirfile = Fdirectory_file_name (dirfile);
4090 if (access (SSDATA (dirfile), 0) < 0) 4092 if (! file_accessible_directory_p (SSDATA (dirfile)))
4091 dir_warning ("Warning: Lisp directory `%s' does not exist.\n", 4093 dir_warning ("Lisp directory", XCAR (path_tail));
4092 XCAR (path_tail));
4093 } 4094 }
4094 } 4095 }
4095} 4096}
@@ -4201,11 +4202,11 @@ init_lread (void)
4201 Lisp_Object tem, tem1; 4202 Lisp_Object tem, tem1;
4202 4203
4203 /* Add to the path the lisp subdir of the installation 4204 /* Add to the path the lisp subdir of the installation
4204 dir, if it exists. Note: in out-of-tree builds, 4205 dir, if it is accessible. Note: in out-of-tree builds,
4205 this directory is empty save for Makefile. */ 4206 this directory is empty save for Makefile. */
4206 tem = Fexpand_file_name (build_string ("lisp"), 4207 tem = Fexpand_file_name (build_string ("lisp"),
4207 Vinstallation_directory); 4208 Vinstallation_directory);
4208 tem1 = Ffile_exists_p (tem); 4209 tem1 = Ffile_accessible_directory_p (tem);
4209 if (!NILP (tem1)) 4210 if (!NILP (tem1))
4210 { 4211 {
4211 if (NILP (Fmember (tem, Vload_path))) 4212 if (NILP (Fmember (tem, Vload_path)))
@@ -4222,10 +4223,10 @@ init_lread (void)
4222 Lisp dirs instead. */ 4223 Lisp dirs instead. */
4223 Vload_path = nconc2 (Vload_path, dump_path); 4224 Vload_path = nconc2 (Vload_path, dump_path);
4224 4225
4225 /* Add leim under the installation dir, if it exists. */ 4226 /* Add leim under the installation dir, if it is accessible. */
4226 tem = Fexpand_file_name (build_string ("leim"), 4227 tem = Fexpand_file_name (build_string ("leim"),
4227 Vinstallation_directory); 4228 Vinstallation_directory);
4228 tem1 = Ffile_exists_p (tem); 4229 tem1 = Ffile_accessible_directory_p (tem);
4229 if (!NILP (tem1)) 4230 if (!NILP (tem1))
4230 { 4231 {
4231 if (NILP (Fmember (tem, Vload_path))) 4232 if (NILP (Fmember (tem, Vload_path)))
@@ -4237,7 +4238,7 @@ init_lread (void)
4237 { 4238 {
4238 tem = Fexpand_file_name (build_string ("site-lisp"), 4239 tem = Fexpand_file_name (build_string ("site-lisp"),
4239 Vinstallation_directory); 4240 Vinstallation_directory);
4240 tem1 = Ffile_exists_p (tem); 4241 tem1 = Ffile_accessible_directory_p (tem);
4241 if (!NILP (tem1)) 4242 if (!NILP (tem1))
4242 { 4243 {
4243 if (NILP (Fmember (tem, Vload_path))) 4244 if (NILP (Fmember (tem, Vload_path)))
@@ -4282,7 +4283,7 @@ init_lread (void)
4282 { 4283 {
4283 tem = Fexpand_file_name (build_string ("site-lisp"), 4284 tem = Fexpand_file_name (build_string ("site-lisp"),
4284 Vsource_directory); 4285 Vsource_directory);
4285 tem1 = Ffile_exists_p (tem); 4286 tem1 = Ffile_accessible_directory_p (tem);
4286 if (!NILP (tem1)) 4287 if (!NILP (tem1))
4287 { 4288 {
4288 if (NILP (Fmember (tem, Vload_path))) 4289 if (NILP (Fmember (tem, Vload_path)))
@@ -4338,21 +4339,28 @@ init_lread (void)
4338 Vloads_in_progress = Qnil; 4339 Vloads_in_progress = Qnil;
4339} 4340}
4340 4341
4341/* Print a warning, using format string FORMAT, that directory DIRNAME 4342/* Print a warning that directory intended for use USE and with name
4342 does not exist. Print it on stderr and put it in *Messages*. */ 4343 DIRNAME cannot be accessed. On entry, errno should correspond to
4344 the access failure. Print the warning on stderr and put it in
4345 *Messages*. */
4343 4346
4344void 4347void
4345dir_warning (const char *format, Lisp_Object dirname) 4348dir_warning (char const *use, Lisp_Object dirname)
4346{ 4349{
4347 fprintf (stderr, format, SDATA (dirname)); 4350 static char const format[] = "Warning: %s `%s': %s\n";
4351 int access_errno = errno;
4352 fprintf (stderr, format, use, SSDATA (dirname), strerror (access_errno));
4348 4353
4349 /* Don't log the warning before we've initialized!! */ 4354 /* Don't log the warning before we've initialized!! */
4350 if (initialized) 4355 if (initialized)
4351 { 4356 {
4357 char const *diagnostic = emacs_strerror (access_errno);
4352 USE_SAFE_ALLOCA; 4358 USE_SAFE_ALLOCA;
4353 char *buffer = SAFE_ALLOCA (SBYTES (dirname) 4359 char *buffer = SAFE_ALLOCA (sizeof format - 3 * (sizeof "%s" - 1)
4354 + strlen (format) - (sizeof "%s" - 1) + 1); 4360 + strlen (use) + SBYTES (dirname)
4355 ptrdiff_t message_len = esprintf (buffer, format, SDATA (dirname)); 4361 + strlen (diagnostic));
4362 ptrdiff_t message_len = esprintf (buffer, format, use, SSDATA (dirname),
4363 diagnostic);
4356 message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname)); 4364 message_dolog (buffer, message_len, 0, STRING_MULTIBYTE (dirname));
4357 SAFE_FREE (); 4365 SAFE_FREE ();
4358 } 4366 }
diff --git a/src/nsterm.m b/src/nsterm.m
index 7ba1608268b..804ab825dee 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -4112,8 +4112,6 @@ ns_term_init (Lisp_Object display_name)
4112 4112
4113 color_file = Fexpand_file_name (build_string ("rgb.txt"), 4113 color_file = Fexpand_file_name (build_string ("rgb.txt"),
4114 Fsymbol_value (intern ("data-directory"))); 4114 Fsymbol_value (intern ("data-directory")));
4115 if (NILP (Ffile_readable_p (color_file)))
4116 fatal ("Could not find %s.\n", SDATA (color_file));
4117 4115
4118 color_map = Fx_load_color_file (color_file); 4116 color_map = Fx_load_color_file (color_file);
4119 if (NILP (color_map)) 4117 if (NILP (color_map))
diff --git a/src/process.c b/src/process.c
index 43f0239d301..728abebe758 100644
--- a/src/process.c
+++ b/src/process.c
@@ -208,7 +208,7 @@ static EMACS_INT update_tick;
208#ifndef NON_BLOCKING_CONNECT 208#ifndef NON_BLOCKING_CONNECT
209#ifdef HAVE_SELECT 209#ifdef HAVE_SELECT
210#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX) 210#if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX)
211#if defined (O_NONBLOCK) || defined (O_NDELAY) 211#if O_NONBLOCK || O_NDELAY
212#if defined (EWOULDBLOCK) || defined (EINPROGRESS) 212#if defined (EWOULDBLOCK) || defined (EINPROGRESS)
213#define NON_BLOCKING_CONNECT 213#define NON_BLOCKING_CONNECT
214#endif /* EWOULDBLOCK || EINPROGRESS */ 214#endif /* EWOULDBLOCK || EINPROGRESS */
@@ -655,7 +655,7 @@ allocate_pty (void)
655 PTY_OPEN; 655 PTY_OPEN;
656#else /* no PTY_OPEN */ 656#else /* no PTY_OPEN */
657 { 657 {
658# ifdef O_NONBLOCK 658# if O_NONBLOCK
659 fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0); 659 fd = emacs_open (pty_name, O_RDWR | O_NONBLOCK, 0);
660# else 660# else
661 fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0); 661 fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0);
@@ -672,7 +672,7 @@ allocate_pty (void)
672#else 672#else
673 sprintf (pty_name, "/dev/tty%c%x", c, i); 673 sprintf (pty_name, "/dev/tty%c%x", c, i);
674#endif /* no PTY_TTY_NAME_SPRINTF */ 674#endif /* no PTY_TTY_NAME_SPRINTF */
675 if (access (pty_name, 6) != 0) 675 if (faccessat (AT_FDCWD, pty_name, R_OK | W_OK, AT_EACCESS) != 0)
676 { 676 {
677 emacs_close (fd); 677 emacs_close (fd);
678# ifndef __sgi 678# ifndef __sgi
@@ -1624,7 +1624,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1624#if ! defined (USG) || defined (USG_SUBTTY_WORKS) 1624#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
1625 /* On most USG systems it does not work to open the pty's tty here, 1625 /* On most USG systems it does not work to open the pty's tty here,
1626 then close it and reopen it in the child. */ 1626 then close it and reopen it in the child. */
1627#ifdef O_NOCTTY 1627#if O_NOCTTY
1628 /* Don't let this terminal become our controlling terminal 1628 /* Don't let this terminal become our controlling terminal
1629 (in case we don't have one). */ 1629 (in case we don't have one). */
1630 forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); 1630 forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
@@ -1678,11 +1678,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1678 } 1678 }
1679#endif 1679#endif
1680 1680
1681#ifdef O_NONBLOCK 1681#if O_NONBLOCK
1682 fcntl (inchannel, F_SETFL, O_NONBLOCK); 1682 fcntl (inchannel, F_SETFL, O_NONBLOCK);
1683 fcntl (outchannel, F_SETFL, O_NONBLOCK); 1683 fcntl (outchannel, F_SETFL, O_NONBLOCK);
1684#else 1684#else
1685#ifdef O_NDELAY 1685#if O_NDELAY
1686 fcntl (inchannel, F_SETFL, O_NDELAY); 1686 fcntl (inchannel, F_SETFL, O_NDELAY);
1687 fcntl (outchannel, F_SETFL, O_NDELAY); 1687 fcntl (outchannel, F_SETFL, O_NDELAY);
1688#endif 1688#endif
@@ -1943,7 +1943,7 @@ create_pty (Lisp_Object process)
1943#if ! defined (USG) || defined (USG_SUBTTY_WORKS) 1943#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
1944 /* On most USG systems it does not work to open the pty's tty here, 1944 /* On most USG systems it does not work to open the pty's tty here,
1945 then close it and reopen it in the child. */ 1945 then close it and reopen it in the child. */
1946#ifdef O_NOCTTY 1946#if O_NOCTTY
1947 /* Don't let this terminal become our controlling terminal 1947 /* Don't let this terminal become our controlling terminal
1948 (in case we don't have one). */ 1948 (in case we don't have one). */
1949 int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); 1949 int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
@@ -1963,11 +1963,11 @@ create_pty (Lisp_Object process)
1963 } 1963 }
1964#endif /* HAVE_PTYS */ 1964#endif /* HAVE_PTYS */
1965 1965
1966#ifdef O_NONBLOCK 1966#if O_NONBLOCK
1967 fcntl (inchannel, F_SETFL, O_NONBLOCK); 1967 fcntl (inchannel, F_SETFL, O_NONBLOCK);
1968 fcntl (outchannel, F_SETFL, O_NONBLOCK); 1968 fcntl (outchannel, F_SETFL, O_NONBLOCK);
1969#else 1969#else
1970#ifdef O_NDELAY 1970#if O_NDELAY
1971 fcntl (inchannel, F_SETFL, O_NDELAY); 1971 fcntl (inchannel, F_SETFL, O_NDELAY);
1972 fcntl (outchannel, F_SETFL, O_NDELAY); 1972 fcntl (outchannel, F_SETFL, O_NDELAY);
1973#endif 1973#endif
@@ -2927,7 +2927,7 @@ usage: (make-network-process &rest ARGS) */)
2927 { 2927 {
2928 /* Don't support network sockets when non-blocking mode is 2928 /* Don't support network sockets when non-blocking mode is
2929 not available, since a blocked Emacs is not useful. */ 2929 not available, since a blocked Emacs is not useful. */
2930#if !defined (O_NONBLOCK) && !defined (O_NDELAY) 2930#if !O_NONBLOCK && !O_NDELAY
2931 error ("Network servers not supported"); 2931 error ("Network servers not supported");
2932#else 2932#else
2933 is_server = 1; 2933 is_server = 1;
@@ -3193,7 +3193,7 @@ usage: (make-network-process &rest ARGS) */)
3193#ifdef NON_BLOCKING_CONNECT 3193#ifdef NON_BLOCKING_CONNECT
3194 if (is_non_blocking_client) 3194 if (is_non_blocking_client)
3195 { 3195 {
3196#ifdef O_NONBLOCK 3196#if O_NONBLOCK
3197 ret = fcntl (s, F_SETFL, O_NONBLOCK); 3197 ret = fcntl (s, F_SETFL, O_NONBLOCK);
3198#else 3198#else
3199 ret = fcntl (s, F_SETFL, O_NDELAY); 3199 ret = fcntl (s, F_SETFL, O_NDELAY);
@@ -3410,10 +3410,10 @@ usage: (make-network-process &rest ARGS) */)
3410 3410
3411 chan_process[inch] = proc; 3411 chan_process[inch] = proc;
3412 3412
3413#ifdef O_NONBLOCK 3413#if O_NONBLOCK
3414 fcntl (inch, F_SETFL, O_NONBLOCK); 3414 fcntl (inch, F_SETFL, O_NONBLOCK);
3415#else 3415#else
3416#ifdef O_NDELAY 3416#if O_NDELAY
3417 fcntl (inch, F_SETFL, O_NDELAY); 3417 fcntl (inch, F_SETFL, O_NDELAY);
3418#endif 3418#endif
3419#endif 3419#endif
@@ -4145,10 +4145,10 @@ server_accept_connection (Lisp_Object server, int channel)
4145 4145
4146 chan_process[s] = proc; 4146 chan_process[s] = proc;
4147 4147
4148#ifdef O_NONBLOCK 4148#if O_NONBLOCK
4149 fcntl (s, F_SETFL, O_NONBLOCK); 4149 fcntl (s, F_SETFL, O_NONBLOCK);
4150#else 4150#else
4151#ifdef O_NDELAY 4151#if O_NDELAY
4152 fcntl (s, F_SETFL, O_NDELAY); 4152 fcntl (s, F_SETFL, O_NDELAY);
4153#endif 4153#endif
4154#endif 4154#endif
@@ -4849,11 +4849,11 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4849#endif 4849#endif
4850 /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK, 4850 /* ISC 4.1 defines both EWOULDBLOCK and O_NONBLOCK,
4851 and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */ 4851 and Emacs uses O_NONBLOCK, so what we get is EAGAIN. */
4852#ifdef O_NONBLOCK 4852#if O_NONBLOCK
4853 else if (nread == -1 && errno == EAGAIN) 4853 else if (nread == -1 && errno == EAGAIN)
4854 ; 4854 ;
4855#else 4855#else
4856#ifdef O_NDELAY 4856#if O_NDELAY
4857 else if (nread == -1 && errno == EAGAIN) 4857 else if (nread == -1 && errno == EAGAIN)
4858 ; 4858 ;
4859 /* Note that we cannot distinguish between no input 4859 /* Note that we cannot distinguish between no input
@@ -7348,7 +7348,7 @@ init_process_emacs (void)
7348#ifdef HAVE_GETSOCKNAME 7348#ifdef HAVE_GETSOCKNAME
7349 ADD_SUBFEATURE (QCservice, Qt); 7349 ADD_SUBFEATURE (QCservice, Qt);
7350#endif 7350#endif
7351#if defined (O_NONBLOCK) || defined (O_NDELAY) 7351#if O_NONBLOCK || O_NDELAY
7352 ADD_SUBFEATURE (QCserver, Qt); 7352 ADD_SUBFEATURE (QCserver, Qt);
7353#endif 7353#endif
7354 7354
diff --git a/src/sysdep.c b/src/sysdep.c
index aa9d0f38c3c..a7f3de2f1b1 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1287,7 +1287,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
1287 old_fcntl_owner[fileno (tty_out->input)]); 1287 old_fcntl_owner[fileno (tty_out->input)]);
1288 } 1288 }
1289#endif /* F_SETOWN */ 1289#endif /* F_SETOWN */
1290#ifdef O_NDELAY 1290#if O_NDELAY
1291 fcntl (fileno (tty_out->input), F_SETFL, 1291 fcntl (fileno (tty_out->input), F_SETFL,
1292 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY); 1292 fcntl (fileno (tty_out->input), F_GETFL, 0) & ~O_NDELAY);
1293#endif 1293#endif
@@ -2384,12 +2384,12 @@ serial_open (char *port)
2384 2384
2385 fd = emacs_open ((char*) port, 2385 fd = emacs_open ((char*) port,
2386 O_RDWR 2386 O_RDWR
2387#ifdef O_NONBLOCK 2387#if O_NONBLOCK
2388 | O_NONBLOCK 2388 | O_NONBLOCK
2389#else 2389#else
2390 | O_NDELAY 2390 | O_NDELAY
2391#endif 2391#endif
2392#ifdef O_NOCTTY 2392#if O_NOCTTY
2393 | O_NOCTTY 2393 | O_NOCTTY
2394#endif 2394#endif
2395 , 0); 2395 , 0);
diff --git a/src/term.c b/src/term.c
index 578c701858f..96549290da5 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2992,7 +2992,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
2992 int fd; 2992 int fd;
2993 FILE *file; 2993 FILE *file;
2994 2994
2995#ifdef O_IGNORE_CTTY 2995#if O_IGNORE_CTTY
2996 if (!ctty) 2996 if (!ctty)
2997 /* Open the terminal device. Don't recognize it as our 2997 /* Open the terminal device. Don't recognize it as our
2998 controlling terminal, and don't make it the controlling tty 2998 controlling terminal, and don't make it the controlling tty
@@ -3023,7 +3023,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
3023 name); 3023 name);
3024 } 3024 }
3025 3025
3026#ifndef O_IGNORE_CTTY 3026#if !O_IGNORE_CTTY
3027 if (!ctty) 3027 if (!ctty)
3028 dissociate_if_controlling_tty (fd); 3028 dissociate_if_controlling_tty (fd);
3029#endif 3029#endif
diff --git a/src/w32.c b/src/w32.c
index 5ac1bc3eb7c..0e7da449b81 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1597,7 +1597,7 @@ init_environment (char ** argv)
1597 see if it succeeds. But I think that's too much to ask. */ 1597 see if it succeeds. But I think that's too much to ask. */
1598 1598
1599 /* MSVCRT's _access crashes with D_OK. */ 1599 /* MSVCRT's _access crashes with D_OK. */
1600 if (tmp && sys_access (tmp, D_OK) == 0) 1600 if (tmp && sys_faccessat (AT_FDCWD, tmp, D_OK, AT_EACCESS) == 0)
1601 { 1601 {
1602 char * var = alloca (strlen (tmp) + 8); 1602 char * var = alloca (strlen (tmp) + 8);
1603 sprintf (var, "TMPDIR=%s", tmp); 1603 sprintf (var, "TMPDIR=%s", tmp);
@@ -2714,10 +2714,16 @@ logon_network_drive (const char *path)
2714 long file names. */ 2714 long file names. */
2715 2715
2716int 2716int
2717sys_access (const char * path, int mode) 2717sys_faccessat (int dirfd, const char * path, int mode, int flags)
2718{ 2718{
2719 DWORD attributes; 2719 DWORD attributes;
2720 2720
2721 if (dirfd != AT_FDCWD)
2722 {
2723 errno = EBADF;
2724 return -1;
2725 }
2726
2721 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its 2727 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
2722 newer versions blow up when passed D_OK. */ 2728 newer versions blow up when passed D_OK. */
2723 path = map_w32_filename (path, NULL); 2729 path = map_w32_filename (path, NULL);
@@ -2960,7 +2966,7 @@ sys_mktemp (char * template)
2960 { 2966 {
2961 int save_errno = errno; 2967 int save_errno = errno;
2962 p[0] = first_char[i]; 2968 p[0] = first_char[i];
2963 if (sys_access (template, 0) < 0) 2969 if (sys_faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0)
2964 { 2970 {
2965 errno = save_errno; 2971 errno = save_errno;
2966 return template; 2972 return template;
@@ -4011,7 +4017,7 @@ symlink (char const *filename, char const *linkname)
4011 { 4017 {
4012 /* Non-absolute FILENAME is understood as being relative to 4018 /* Non-absolute FILENAME is understood as being relative to
4013 LINKNAME's directory. We need to prepend that directory to 4019 LINKNAME's directory. We need to prepend that directory to
4014 FILENAME to get correct results from sys_access below, since 4020 FILENAME to get correct results from sys_faccessat below, since
4015 otherwise it will interpret FILENAME relative to the 4021 otherwise it will interpret FILENAME relative to the
4016 directory where the Emacs process runs. Note that 4022 directory where the Emacs process runs. Note that
4017 make-symbolic-link always makes sure LINKNAME is a fully 4023 make-symbolic-link always makes sure LINKNAME is a fully
@@ -4025,10 +4031,10 @@ symlink (char const *filename, char const *linkname)
4025 strncpy (tem, linkfn, p - linkfn); 4031 strncpy (tem, linkfn, p - linkfn);
4026 tem[p - linkfn] = '\0'; 4032 tem[p - linkfn] = '\0';
4027 strcat (tem, filename); 4033 strcat (tem, filename);
4028 dir_access = sys_access (tem, D_OK); 4034 dir_access = sys_faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
4029 } 4035 }
4030 else 4036 else
4031 dir_access = sys_access (filename, D_OK); 4037 dir_access = sys_faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
4032 4038
4033 /* Since Windows distinguishes between symlinks to directories and 4039 /* Since Windows distinguishes between symlinks to directories and
4034 to files, we provide a kludgy feature: if FILENAME doesn't 4040 to files, we provide a kludgy feature: if FILENAME doesn't
diff --git a/src/xrdb.c b/src/xrdb.c
index 9d056a607e4..59b0876ebf8 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -41,7 +41,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#ifdef HAVE_PWD_H 41#ifdef HAVE_PWD_H
42#include <pwd.h> 42#include <pwd.h>
43#endif 43#endif
44#include <sys/stat.h>
45 44
46#ifdef USE_MOTIF 45#ifdef USE_MOTIF
47/* For Vdouble_click_time. */ 46/* For Vdouble_click_time. */
@@ -50,7 +49,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
50 49
51char *x_get_string_resource (XrmDatabase rdb, const char *name, 50char *x_get_string_resource (XrmDatabase rdb, const char *name,
52 const char *class); 51 const char *class);
53static int file_p (const char *filename);
54 52
55 53
56/* X file search path processing. */ 54/* X file search path processing. */
@@ -108,7 +106,7 @@ x_get_customization_string (XrmDatabase db, const char *name,
108 database associated with display. 106 database associated with display.
109 (This is x_customization_string.) 107 (This is x_customization_string.)
110 108
111 Return the expanded file name if it exists and is readable, and 109 Return the resource database if its file was read successfully, and
112 refers to %L only when the LANG environment variable is set, or 110 refers to %L only when the LANG environment variable is set, or
113 otherwise provided by X. 111 otherwise provided by X.
114 112
@@ -117,10 +115,11 @@ x_get_customization_string (XrmDatabase db, const char *name,
117 115
118 Return NULL otherwise. */ 116 Return NULL otherwise. */
119 117
120static char * 118static XrmDatabase
121magic_file_p (const char *string, ptrdiff_t string_len, const char *class, 119magic_db (const char *string, ptrdiff_t string_len, const char *class,
122 const char *escaped_suffix) 120 const char *escaped_suffix)
123{ 121{
122 XrmDatabase db;
124 char *lang = getenv ("LANG"); 123 char *lang = getenv ("LANG");
125 124
126 ptrdiff_t path_size = 100; 125 ptrdiff_t path_size = 100;
@@ -217,14 +216,9 @@ magic_file_p (const char *string, ptrdiff_t string_len, const char *class,
217 } 216 }
218 217
219 path[path_len] = '\0'; 218 path[path_len] = '\0';
220 219 db = XrmGetFileDatabase (path);
221 if (! file_p (path)) 220 xfree (path);
222 { 221 return db;
223 xfree (path);
224 return NULL;
225 }
226
227 return path;
228} 222}
229 223
230 224
@@ -258,22 +252,11 @@ gethomedir (void)
258} 252}
259 253
260 254
261static int
262file_p (const char *filename)
263{
264 struct stat status;
265
266 return (access (filename, 4) == 0 /* exists and is readable */
267 && stat (filename, &status) == 0 /* get the status */
268 && (S_ISDIR (status.st_mode)) == 0); /* not a directory */
269}
270
271
272/* Find the first element of SEARCH_PATH which exists and is readable, 255/* Find the first element of SEARCH_PATH which exists and is readable,
273 after expanding the %-escapes. Return 0 if we didn't find any, and 256 after expanding the %-escapes. Return 0 if we didn't find any, and
274 the path name of the one we found otherwise. */ 257 the path name of the one we found otherwise. */
275 258
276static char * 259static XrmDatabase
277search_magic_path (const char *search_path, const char *class, 260search_magic_path (const char *search_path, const char *class,
278 const char *escaped_suffix) 261 const char *escaped_suffix)
279{ 262{
@@ -286,18 +269,16 @@ search_magic_path (const char *search_path, const char *class,
286 269
287 if (p > s) 270 if (p > s)
288 { 271 {
289 char *path = magic_file_p (s, p - s, class, escaped_suffix); 272 XrmDatabase db = magic_db (s, p - s, class, escaped_suffix);
290 if (path) 273 if (db)
291 return path; 274 return db;
292 } 275 }
293 else if (*p == ':') 276 else if (*p == ':')
294 { 277 {
295 char *path; 278 static char const ns[] = "%N%S";
296 279 XrmDatabase db = magic_db (ns, strlen (ns), class, escaped_suffix);
297 s = "%N%S"; 280 if (db)
298 path = magic_file_p (s, strlen (s), class, escaped_suffix); 281 return db;
299 if (path)
300 return path;
301 } 282 }
302 283
303 if (*p == ':') 284 if (*p == ':')
@@ -312,21 +293,12 @@ search_magic_path (const char *search_path, const char *class,
312static XrmDatabase 293static XrmDatabase
313get_system_app (const char *class) 294get_system_app (const char *class)
314{ 295{
315 XrmDatabase db = NULL;
316 const char *path; 296 const char *path;
317 char *p;
318 297
319 path = getenv ("XFILESEARCHPATH"); 298 path = getenv ("XFILESEARCHPATH");
320 if (! path) path = PATH_X_DEFAULTS; 299 if (! path) path = PATH_X_DEFAULTS;
321 300
322 p = search_magic_path (path, class, 0); 301 return search_magic_path (path, class, 0);
323 if (p)
324 {
325 db = XrmGetFileDatabase (p);
326 xfree (p);
327 }
328
329 return db;
330} 302}
331 303
332 304
@@ -340,35 +312,40 @@ get_fallback (Display *display)
340static XrmDatabase 312static XrmDatabase
341get_user_app (const char *class) 313get_user_app (const char *class)
342{ 314{
315 XrmDatabase db = 0;
343 const char *path; 316 const char *path;
344 char *file = 0;
345 char *free_it = 0;
346 317
347 /* Check for XUSERFILESEARCHPATH. It is a path of complete file 318 /* Check for XUSERFILESEARCHPATH. It is a path of complete file
348 names, not directories. */ 319 names, not directories. */
349 if (((path = getenv ("XUSERFILESEARCHPATH")) 320 path = getenv ("XUSERFILESEARCHPATH");
350 && (file = search_magic_path (path, class, 0))) 321 if (path)
322 db = search_magic_path (path, class, 0);
351 323
324 if (! db)
325 {
352 /* Check for APPLRESDIR; it is a path of directories. In each, 326 /* Check for APPLRESDIR; it is a path of directories. In each,
353 we have to search for LANG/CLASS and then CLASS. */ 327 we have to search for LANG/CLASS and then CLASS. */
354 || ((path = getenv ("XAPPLRESDIR")) 328 path = getenv ("XAPPLRESDIR");
355 && ((file = search_magic_path (path, class, "/%L/%N")) 329 if (path)
356 || (file = search_magic_path (path, class, "/%N")))) 330 {
331 db = search_magic_path (path, class, "/%L/%N");
332 if (!db)
333 db = search_magic_path (path, class, "/%N");
334 }
335 }
357 336
337 if (! db)
338 {
358 /* Check in the home directory. This is a bit of a hack; let's 339 /* Check in the home directory. This is a bit of a hack; let's
359 hope one's home directory doesn't contain any %-escapes. */ 340 hope one's home directory doesn't contain any %-escapes. */
360 || (free_it = gethomedir (), 341 char *home = gethomedir ();
361 ((file = search_magic_path (free_it, class, "%L/%N")) 342 db = search_magic_path (home, class, "%L/%N");
362 || (file = search_magic_path (free_it, class, "%N"))))) 343 if (! db)
363 { 344 db = search_magic_path (home, class, "%N");
364 XrmDatabase db = XrmGetFileDatabase (file); 345 xfree (home);
365 xfree (file);
366 xfree (free_it);
367 return db;
368 } 346 }
369 347
370 xfree (free_it); 348 return db;
371 return NULL;
372} 349}
373 350
374 351