New module 'fchdir'.
authorBruno Haible <bruno@clisp.org>
Sun, 14 Jan 2007 11:32:10 +0000 (11:32 +0000)
committerBruno Haible <bruno@clisp.org>
Sun, 14 Jan 2007 11:32:10 +0000 (11:32 +0000)
28 files changed:
ChangeLog
MODULES.html.sh
lib/backupfile.c
lib/chown.c
lib/clean-temp.c
lib/copy-file.c
lib/dirent_.h [new file with mode: 0644]
lib/dup-safer.c
lib/execute.c
lib/fchdir.c [new file with mode: 0644]
lib/fcntl_.h
lib/fsusage.c
lib/gc-gnulib.c
lib/getcwd.c
lib/glob.c
lib/javacomp.c
lib/mountlist.c
lib/openat-proc.c
lib/pagealign_alloc.c
lib/pipe.c
lib/progreloc.c
lib/savedir.c
lib/unistd_.h [new file with mode: 0644]
lib/utime.c
m4/fchdir.m4 [new file with mode: 0644]
m4/unistd_h.m4
modules/fchdir [new file with mode: 0644]
modules/unistd

index 688ac05..eff0b42 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2006-12-30  Bruno Haible  <bruno@clisp.org>
+
+       * modules/fchdir: New file.
+       * modules/unistd (Files): Add lib/unistd_.h.
+       (Makefile.am): Generate unistd.h from unistd_.h.
+       * lib/fchdir.c: New file.
+       * lib/dirent_.h: New file.
+       * lib/unistd_.h: New file.
+       * lib/fcntl_.h (open) [FCHDIR_REPLACEMENT]: New replacement.
+       * m4/fchdir.m4: New file.
+       * m4/unistd_h.m4 (gl_PREREQ_UNISTD): New macro.
+       (gl_HEADER_UNISTD): Invoke it.
+       * lib/dup-safer.c (dup_safer) [FCHDIR_REPLACEMENT]: Use the dup
+       function.
+       * lib/backupfile.c (opendir, closedir): Undefine.
+       * lib/chown.c (open, close): Undefine.
+       * lib/clean-temp.c (open, close): Undefine.
+       * lib/copy-file.c (open, close): Undefine.
+       * lib/execute.c (open, close): Undefine.
+       * lib/fsusage.c (open, close): Undefine.
+       * lib/gc-gnulib.c (open, close): Undefine.
+       * lib/getcwd.c (opendir, closedir): Undefine.
+       * lib/glob.c (opendir, closedir): Undefine.
+       * lib/javacomp.c (open, close): Undefine.
+       * lib/mountlist.c (open, close, opendir, closedir): Undefine.
+       * lib/openat-proc.c (open, close): Undefine.
+       * lib/pagealign_alloc.c (open, close): Undefine.
+       * lib/pipe.c (open, close): Undefine.
+       * lib/progreloc.c (open, close): Undefine.
+       * lib/savedir.c (opendir, closedir): Undefine.
+       * lib/utime.c (open, close): Undefine.
+       * MODULES.html.sh (Support for systems lacking POSIX:2001): Add fchdir.
+
 2007-01-10  Bruno Haible  <bruno@clisp.org>
 
        * lib/striconv.c (mem_cd_iconv): Align the temporary buffer.
index 5836e34..68a3152 100755 (executable)
@@ -1921,6 +1921,7 @@ func_all_modules ()
   func_begin_table
   func_module chown
   func_module dup2
+  func_module fchdir
   func_module ftruncate
   func_module getaddrinfo
   func_module getcwd
index 5875d3a..adfc0e5 100644 (file)
    of `digit' even when the host does not conform to POSIX.  */
 #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
 
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef opendir
+#undef closedir
+
 /* The extension added to file names to produce a simple (as opposed
    to numbered) backup file name. */
 char const *simple_backup_suffix = "~";
index 1301aa6..2da2c80 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 /* Provide a more-closely POSIX-conforming version of chown on
    systems with one or both of the following problems:
    - chown doesn't treat an ID of -1 as meaning
index aa82974..7acc688 100644 (file)
 # define uintptr_t unsigned long
 #endif
 
+#if !GNULIB_FCNTL_SAFER
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+# undef open
+# undef close
+#endif
+
 
 /* The use of 'volatile' in the types below (and ISO C 99 section 5.1.2.3.(5))
    ensure that while constructing or modifying the data structures, the field
index 4314f4c..5a5dcf7 100644 (file)
 
 #define _(str) gettext (str)
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
+
 void
 copy_file_preserving (const char *src_filename, const char *dest_filename)
 {
diff --git a/lib/dirent_.h b/lib/dirent_.h
new file mode 100644 (file)
index 0000000..cadc267
--- /dev/null
@@ -0,0 +1,42 @@
+/* Wrapper around <dirent.h>.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_DIRENT_H
+#define _GL_DIRENT_H
+
+#include @ABSOLUTE_DIRENT_H@
+
+
+/* Declare overridden functions.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef FCHDIR_REPLACEMENT
+# define opendir rpl_opendir
+extern DIR * opendir (const char *);
+# define closedir rpl_closedir
+extern int closedir (DIR *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GL_DIRENT_H */
index d0606ee..7b12b61 100644 (file)
@@ -35,7 +35,7 @@
 int
 dup_safer (int fd)
 {
-#ifdef F_DUPFD
+#if defined F_DUPFD && !defined FCHDIR_REPLACEMENT
   return fcntl (fd, F_DUPFD, STDERR_FILENO + 1);
 #else
   /* fd_safer calls us back, but eventually the recursion unwinds and
index cb72343..ea93880 100644 (file)
@@ -70,6 +70,11 @@ extern char **environ;
 # define STDERR_FILENO 2
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 
 #ifdef EINTR
 
diff --git a/lib/fchdir.c b/lib/fchdir.c
new file mode 100644 (file)
index 0000000..c05a9f3
--- /dev/null
@@ -0,0 +1,277 @@
+/* fchdir replacement.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "canonicalize.h"
+#include "dirfd.h"
+#include "strdup.h"
+
+/* This replacement assumes that a directory is not renamed while opened
+   through a file descriptor.  */
+
+/* Array of file descriptors opened.  If it points to a directory, it stores
+   info about this directory; otherwise it stores an errno value of ENOTDIR.  */
+typedef struct
+{
+  char *name;       /* Absolute name of the directory, or NULL.  */
+  int saved_errno;  /* If name == NULL: The error code describing the failure
+                      reason.  */
+} dir_info_t;
+static dir_info_t *dirs;
+static size_t dirs_allocated;
+
+/* Try to ensure dirs has enough room for a slot at index fd.  */
+static void
+ensure_dirs_slot (size_t fd)
+{
+  if (fd >= dirs_allocated)
+    {
+      size_t new_allocated;
+      dir_info_t *new_dirs;
+      size_t i;
+
+      new_allocated = 2 * dirs_allocated + 1;
+      if (new_allocated <= fd)
+       new_allocated = fd + 1;
+      new_dirs =
+       (dirs != NULL
+        ? (dir_info_t *) realloc (dirs, new_allocated * sizeof (dir_info_t))
+        : (dir_info_t *) malloc (new_allocated * sizeof (dir_info_t)));
+      if (new_dirs != NULL)
+       {
+         for (i = dirs_allocated; i < new_allocated; i++)
+           {
+             new_dirs[i].name = NULL;
+             new_dirs[i].saved_errno = ENOTDIR;
+           }
+         dirs = new_dirs;
+         dirs_allocated = new_allocated;
+       }
+    }
+}
+
+/* Override open() and close(), to keep track of the open file descriptors.  */
+
+int
+close (int fd)
+#undef close
+{
+  int retval = close (fd);
+
+  if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
+    {
+      if (dirs[fd].name != NULL)
+       free (dirs[fd].name);
+      dirs[fd].name = NULL;
+      dirs[fd].saved_errno = ENOTDIR;
+    }
+  return retval;
+}
+
+int
+open (const char *filename, int flags, ...)
+#undef open
+{
+  mode_t mode;
+  int fd;
+  struct stat statbuf;
+
+  mode = 0;
+  if (flags & O_CREAT)
+    {
+      va_list arg;
+      va_start (arg, flags);
+
+      /* If mode_t is narrower than int, use the promoted type (int),
+        not mode_t.  Use sizeof to guess whether mode_t is narrower;
+        we don't know of any practical counterexamples.  */
+      mode = (sizeof (mode_t) < sizeof (int)
+             ? va_arg (arg, int)
+             : va_arg (arg, mode_t));
+
+      va_end (arg);
+    }
+  fd = open (filename, flags, mode);
+  if (fd >= 0)
+    {
+      ensure_dirs_slot (fd);
+      if (fd < dirs_allocated
+         && fstat (fd, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode))
+       {
+         dirs[fd].name = canonicalize_file_name (filename);
+         if (dirs[fd].name == NULL)
+           dirs[fd].saved_errno = errno;
+       }
+    }
+  return fd;
+}
+
+/* Override opendir() and closedir(), to keep track of the open file
+   descriptors.  Needed because there is a function dirfd().  */
+
+int
+closedir (DIR *dp)
+#undef closedir
+{
+  int fd = dirfd (dp);
+  int retval = closedir (dp);
+
+  if (retval >= 0 && fd >= 0 && fd < dirs_allocated)
+    {
+      if (dirs[fd].name != NULL)
+       free (dirs[fd].name);
+      dirs[fd].name = NULL;
+      dirs[fd].saved_errno = ENOTDIR;
+    }
+  return retval;
+}
+
+DIR *
+opendir (const char *filename)
+#undef opendir
+{
+  DIR *dp;
+
+  dp = opendir (filename);
+  if (dp != NULL)
+    {
+      int fd = dirfd (dp);
+      if (fd >= 0)
+       {
+         ensure_dirs_slot (fd);
+         if (fd < dirs_allocated)
+           {
+             dirs[fd].name = canonicalize_file_name (filename);
+             if (dirs[fd].name == NULL)
+               dirs[fd].saved_errno = errno;
+           }
+       }
+    }
+  return dp;
+}
+
+/* Override dup() and dup2(), to keep track of open file descriptors.  */
+
+int
+dup (int oldfd)
+#undef dup
+{
+  int newfd = dup (oldfd);
+
+  if (oldfd >= 0 && newfd >= 0)
+    {
+      ensure_dirs_slot (newfd);
+      if (newfd < dirs_allocated)
+       {
+         if (oldfd < dirs_allocated)
+           {
+             if (dirs[oldfd].name != NULL)
+               {
+                 dirs[newfd].name = strdup (dirs[oldfd].name);
+                 if (dirs[newfd].name == NULL)
+                   dirs[newfd].saved_errno = ENOMEM;
+               }
+             else
+               {
+                 dirs[newfd].name = NULL;
+                 dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
+               }
+           }
+         else
+           {
+             dirs[newfd].name = NULL;
+             dirs[newfd].saved_errno = ENOMEM;
+           }
+       }
+    }
+  return newfd;
+}
+
+int
+dup2 (int oldfd, int newfd)
+#undef dup2
+{
+  int retval = dup2 (oldfd, newfd);
+
+  if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd)
+    {
+      ensure_dirs_slot (newfd);
+      if (newfd < dirs_allocated)
+       {
+         if (oldfd < dirs_allocated)
+           {
+             if (dirs[oldfd].name != NULL)
+               {
+                 dirs[newfd].name = strdup (dirs[oldfd].name);
+                 if (dirs[newfd].name == NULL)
+                   dirs[newfd].saved_errno = ENOMEM;
+               }
+             else
+               {
+                 dirs[newfd].name = NULL;
+                 dirs[newfd].saved_errno = dirs[oldfd].saved_errno;
+               }
+           }
+         else
+           {
+             dirs[newfd].name = NULL;
+             dirs[newfd].saved_errno = ENOMEM;
+           }
+       }
+    }
+  return retval;
+}
+
+/* Implement fchdir() in terms of chdir().  */
+
+int
+fchdir (int fd)
+{
+  if (fd >= 0)
+    {
+      if (fd < dirs_allocated)
+       {
+         if (dirs[fd].name != NULL)
+           return chdir (dirs[fd].name);
+         else
+           {
+             errno = dirs[fd].saved_errno;
+             return -1;
+           }
+       }
+      else
+       {
+         errno = ENOMEM;
+         return -1;
+       }
+    }
+  else
+    {
+      errno = EBADF;
+      return -1;
+    }
+}
index 5c2857c..e16ad54 100644 (file)
 #include <unistd.h>
 #include @ABSOLUTE_FCNTL_H@
 
+
+/* Declare overridden functions.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef FCHDIR_REPLACEMENT
+# define open rpl_open
+extern int open (const char *, int, ...);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* Fix up the O_* macros.  */
+
 #if !defined O_DIRECT && defined O_DIRECTIO
 /* Tru64 spells it `O_DIRECTIO'.  */
 # define O_DIRECT O_DIRECTIO
index a305979..337bf53 100644 (file)
 # include "full-read.h"
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 /* Many space usage primitives use all 1 bits to denote a value that is
    not applicable or unknown.  Propagate this information by returning
    a uintmax_t value that is all 1 bits if X is all 1 bits, even if X
index 5ce31c1..f414f43 100644 (file)
 # include "rijndael-api-fst.h"
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 Gc_rc
 gc_init (void)
 {
index 292bc19..f13da4d 100644 (file)
 # define __opendir opendir
 # define __readdir readdir
 #endif
+
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+   therefore save some unnecessary recursion in fchdir.c.  */
+#undef opendir
+#undef closedir
 \f
 /* Get the name of the current working directory, and put it in SIZE
    bytes of BUF.  Returns NULL if the directory couldn't be determined or
index 6f8641a..edef095 100644 (file)
@@ -162,6 +162,11 @@ static const char *next_brace_sub (const char *begin, int flags) __THROW;
 
 #endif /* !defined _LIBC || !defined GLOB_ONLY_P */
 
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef opendir
+#undef closedir
+
 static int glob_in_dir (const char *pattern, const char *directory,
                        int flags, int (*errfunc) (const char *, int),
                        glob_t *pglob);
index ba0f437..5d3d60b 100644 (file)
 
 #define _(str) gettext (str)
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 
 /* Survey of Java compilers.
 
index d70a1a2..bb01f91 100644 (file)
@@ -143,6 +143,16 @@ char *strstr ();
 # define SIZE_MAX ((size_t) -1)
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef opendir
+#undef closedir
+
 #ifndef ME_DUMMY
 # define ME_DUMMY(Fs_name, Fs_type)            \
     (strcmp (Fs_type, "autofs") == 0           \
index 87293a4..ff2fff0 100644 (file)
 #include "same-inode.h"
 #include "xalloc.h"
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 #define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/%s"
 
 #define PROC_SELF_FD_NAME_SIZE_BOUND(len) \
index cbbe763..c06dd0d 100644 (file)
 # endif
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 
 #if HAVE_MMAP || ! HAVE_POSIX_MEMALIGN
 
index 19feaf4..521872b 100644 (file)
@@ -69,6 +69,11 @@ extern char **environ;
 # define STDERR_FILENO 2
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 
 #ifdef EINTR
 
index e9fb647..cb97959 100644 (file)
 # define FILE_SYSTEM_PREFIX_LEN(P) 0
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 #undef set_program_name
 
 
index 12084ee..d930fb4 100644 (file)
 # define NAME_SIZE_DEFAULT 512
 #endif
 
+/* The results of opendir() in this file are not used with dirfd and fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef opendir
+#undef closedir
+
 /* Return a freshly allocated string containing the file names
    in directory DIRP, separated by '\0' characters;
    the end is marked by two '\0' characters in a row.
diff --git a/lib/unistd_.h b/lib/unistd_.h
new file mode 100644 (file)
index 0000000..36fa673
--- /dev/null
@@ -0,0 +1,52 @@
+/* Substitute for and wrapper around <unistd.h>.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_UNISTD_H
+#define _GL_UNISTD_H
+
+#if HAVE_UNISTD_H
+# include @ABSOLUTE_UNISTD_H@
+#endif
+
+
+/* Declare overridden functions.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef FCHDIR_REPLACEMENT
+
+/* Change the process' current working directory to the directory on which
+   the given file descriptor is open.  */
+extern int fchdir (int /*fd*/);
+
+# define close rpl_close
+extern int close (int);
+# define dup rpl_dup
+extern int dup (int);
+# define dup2 rpl_dup2
+extern int dup2 (int, int);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GL_UNISTD_H */
index 421a7cc..273a5fb 100644 (file)
@@ -47,6 +47,11 @@ struct utimbuf
 };
 #endif
 
+/* The results of open() in this file are not used with fchdir,
+   therefore save some unnecessary work in fchdir.c.  */
+#undef open
+#undef close
+
 /* Emulate utime (file, NULL) for systems (like 4.3BSD) that do not
    interpret it to set the access and modification times of FILE to
    the current time.  Return 0 if successful, -1 if not. */
diff --git a/m4/fchdir.m4 b/m4/fchdir.m4
new file mode 100644 (file)
index 0000000..caebfcb
--- /dev/null
@@ -0,0 +1,29 @@
+# fchdir.m4 serial 1
+dnl Copyright (C) 2006 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_FCHDIR],
+[
+  AC_CHECK_FUNCS_ONCE([fchdir])
+  if test $ac_cv_func_fchdir = no; then
+    AC_LIBOBJ([fchdir])
+    gl_PREREQ_FCHDIR
+    AC_DEFINE([FCHDIR_REPLACEMENT], 1,
+      [Define if gnulib's fchdir() replacement is used.])
+    gl_ABSOLUTE_HEADER([dirent.h])
+    ABSOLUTE_DIRENT_H=\"$gl_cv_absolute_dirent_h\"
+    DIRENT_H='dirent.h'
+    UNISTD_H2='unistd.h'
+  else
+    DIRENT_H=
+    UNISTD_H2=
+  fi
+  AC_SUBST([ABSOLUTE_DIRENT_H])
+  AC_SUBST([DIRENT_H])
+  AC_SUBST([UNISTD_H2])
+])
+
+# Prerequisites of lib/fchdir.c.
+AC_DEFUN([gl_PREREQ_FCHDIR], [:])
index 9c77f9b..9d499df 100644 (file)
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 2
+# unistd_h.m4 serial 3
 dnl Copyright (C) 2006 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,11 +8,25 @@ dnl Written by Simon Josefsson
 
 AC_DEFUN([gl_HEADER_UNISTD],
 [
-  dnl Prerequisites of lib/unistd.h.
   AC_CHECK_HEADERS([unistd.h], [
     UNISTD_H=''
   ], [
     UNISTD_H='unistd.h'
   ])
   AC_SUBST(UNISTD_H)
+  dnl This module decides to build unistd.h if it is missing.
+  dnl The fchdir module decides to build unistd.h if fchdir() is missing.
+  dnl Therefore check for the prerequisites of lib/unistd.h always.
+  gl_PREREQ_UNISTD
+])
+
+dnl Prerequisites of lib/unistd.h.
+AC_DEFUN([gl_PREREQ_UNISTD],
+[
+  AC_CHECK_HEADERS_ONCE([unistd.h])
+  if test $ac_cv_header_unistd_h = yes; then
+    gl_ABSOLUTE_HEADER([unistd.h])
+    ABSOLUTE_UNISTD_H=\"$gl_cv_absolute_unistd_h\"
+  fi
+  AC_SUBST([ABSOLUTE_UNISTD_H])
 ])
diff --git a/modules/fchdir b/modules/fchdir
new file mode 100644 (file)
index 0000000..b8fa651
--- /dev/null
@@ -0,0 +1,41 @@
+Description:
+fchdir() function: change current directory, given an open file descriptor.
+
+Files:
+lib/fchdir.c
+lib/dirent_.h
+m4/fchdir.m4
+
+Depends-on:
+fcntl
+unistd
+canonicalize-lgpl
+dirfd
+strdup
+
+configure.ac:
+gl_FUNC_FCHDIR
+
+Makefile.am:
+BUILT_SOURCES += $(DIRENT_H) $(UNISTD_H2)
+
+# We need the following in order to create <dirent.h> when the system
+# doesn't have one that works with the given compiler.
+dirent.h: dirent_.h
+       rm -f $@-t $@
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         sed -e 's|@''ABSOLUTE_DIRENT_H''@|$(ABSOLUTE_DIRENT_H)|g' \
+             < $(srcdir)/dirent_.h; \
+       } > $@-t
+       mv $@-t $@
+MOSTLYCLEANFILES += dirent.h dirent.h-t
+
+Include:
+#include <unistd.h>
+
+License:
+LGPL
+
+Maintainer:
+Bruno Haible
+
index 177b95c..d04c80c 100644 (file)
@@ -3,6 +3,7 @@ A <unistd.h> for systems lacking it.
 
 Files:
 m4/unistd_h.m4
+lib/unistd_.h
 
 Depends-on:
 
@@ -14,11 +15,14 @@ BUILT_SOURCES += $(UNISTD_H)
 
 # We need the following in order to create an empty placeholder for
 # <unistd.h> when the system doesn't have one.
-unistd.h:
+unistd.h: unistd_.h
+       rm -f $@-t $@
        { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
-         echo '/* Empty placeholder for $@.  */'; \
-       } > $@
-MOSTLYCLEANFILES += unistd.h
+         sed -e 's|@''ABSOLUTE_UNISTD_H''@|$(ABSOLUTE_UNISTD_H)|g' \
+             < $(srcdir)/unistd_.h; \
+       } > $@-t
+       mv $@-t $@
+MOSTLYCLEANFILES += unistd.h unistd.h-t
 
 Include:
 #include <unistd.h>