+2010-09-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ fcntl-h, etc.: prefer O_SEARCH to O_RDONLY when applicable
+
+ POSIX 2008 specifies a new 'open' flag O_SEARCH, which can be used
+ when one needs search access to a directory but not read access.
+ On systems where it is available, it works in some cases where
+ O_RDONLY does not, namely on directories that are searchable but
+ not readable, and which need only to be searchable. If O_SEARCH
+ is not available, fall back to the traditional method of using
+ O_RDONLY.
+
+ * lib/fcntl.in.h (O_SEARCH): #define to O_RDONLY if not defined.
+ * lib/chdir-long.c (cdb_advance_fd): Use O_SEARCH, not O_RDONLY,
+ when opening a directory that needs only to be searchable.
+ * lib/chdir-safer.c (chdir_no_follow): Likewise.
+ * lib/fts.c (diropen, fts_open, fd_ring_check): Likewise.
+ * lib/openat-proc.c (openat_proc_name): Likewise.
+ * lib/openat.c (openat_needs_fchdir): Likewise.
+ * lib/save-cwd.c (save_cwd): Likewise.
+ * lib/savewd.c (savewd_save, savewd_chdir): Likewise.
+
2010-08-28 Bruno Haible <bruno@clisp.org>
New module 'host-cpu-c-abi'.
cdb_advance_fd (struct cd_buf *cdb, char const *dir)
{
int new_fd = openat (cdb->fd, dir,
- O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
+ O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK);
if (new_fd < 0)
return -1;
#endif
/* Like chdir, but fail if DIR is a symbolic link to a directory (or
- similar funny business), or if DIR is not readable. This avoids a
- minor race condition between when a directory is created or statted
- and when the process chdirs into it. */
+ similar funny business). This avoids a minor race condition
+ between when a directory is created or statted and when the process
+ chdirs into it.
+
+ On older systems lacking full support for O_SEARCH, this function
+ can also fail if DIR is not readable. */
int
chdir_no_follow (char const *dir)
{
int result = 0;
int saved_errno;
int fd = open (dir,
- O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK);
+ O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NOFOLLOW | O_NONBLOCK);
if (fd < 0)
return -1;
# define O_RSYNC 0
#endif
+#ifndef O_SEARCH
+# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */
+#endif
+
#ifndef O_SYNC
# define O_SYNC 0
#endif
internal_function
diropen (FTS const *sp, char const *dir)
{
- int open_flags = (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+ int open_flags = (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
| (ISSET (FTS_PHYSICAL) ? O_NOFOLLOW : 0));
int fd = (ISSET (FTS_CWDFD)
early, doing it here saves us the trouble of ensuring
later (where it'd be messier) that "." can in fact
be opened. If not, revert to FTS_NOCHDIR mode. */
- int fd = open (".", O_RDONLY);
+ int fd = open (".", O_SEARCH);
if (fd < 0)
{
/* Even if `.' is unreadable, don't revert to FTS_NOCHDIR mode
int fd = i_ring_pop (&fd_w);
if (0 <= fd)
{
- int parent_fd = openat (cwd_fd, "..", O_RDONLY);
+ int parent_fd = openat (cwd_fd, "..", O_SEARCH);
if (parent_fd < 0)
{
// Warn?
problem is exhibited on code that built on Solaris 8 and
running on Solaris 10. */
- int proc_self_fd = open ("/proc/self/fd", O_RDONLY);
+ int proc_self_fd = open ("/proc/self/fd", O_SEARCH);
if (proc_self_fd < 0)
proc_status = -1;
else
openat_needs_fchdir (void)
{
bool needs_fchdir = true;
- int fd = open ("/", O_RDONLY);
+ int fd = open ("/", O_SEARCH);
if (0 <= fd)
{
{
cwd->name = NULL;
- cwd->desc = open (".", O_RDONLY);
+ cwd->desc = open (".", O_SEARCH);
if (!GNULIB_FCNTL_SAFER)
cwd->desc = fd_safer (cwd->desc);
if (cwd->desc < 0)
case INITIAL_STATE:
/* Save the working directory, or prepare to fall back if possible. */
{
- int fd = open_safer (".", O_RDONLY);
+ int fd = open_safer (".", O_SEARCH);
if (0 <= fd)
{
wd->state = FD_STATE;
|| (options & (HAVE_WORKING_O_NOFOLLOW ? SAVEWD_CHDIR_NOFOLLOW : 0)))
{
fd = open (dir,
- (O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
+ (O_SEARCH | O_DIRECTORY | O_NOCTTY | O_NONBLOCK
| (options & SAVEWD_CHDIR_NOFOLLOW ? O_NOFOLLOW : 0)));
if (open_result)