summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chdir-long.c338
-rw-r--r--lib/chdir-long.h35
-rw-r--r--lib/openat.c91
-rw-r--r--lib/openat.h35
-rw-r--r--lib/save-cwd.c57
-rw-r--r--m4/chdir-long.m441
-rw-r--r--m4/openat.m428
-rw-r--r--m4/save-cwd.m46
-rw-r--r--modules/chdir-long25
-rw-r--r--modules/openat27
-rw-r--r--modules/save-cwd2
11 files changed, 653 insertions, 32 deletions
diff --git a/lib/chdir-long.c b/lib/chdir-long.c
new file mode 100644
index 0000000000..7e7fd97182
--- /dev/null
+++ b/lib/chdir-long.c
@@ -0,0 +1,338 @@
+/* provide a chdir function that tries not to fail due to ENAMETOOLONG
+ Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "chdir-long.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+
+#include "mempcpy.h"
+#include "openat.h"
+
+#ifndef O_DIRECTORY
+# define O_DIRECTORY 0
+#endif
+
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef PATH_MAX
+# error "compile this file only if your system defines PATH_MAX"
+#endif
+
+/* FIXME: this use of `MIN' is our sole concession to arbitrary limitations.
+ If, for some system, PATH_MAX is larger than 8191 and you call
+ chdir_long with a directory name that is longer than PATH_MAX,
+ yet that contains a single component that is more than 8191 bytes
+ long, then this function will fail. */
+#define MAX_COMPONENT_LENGTH MIN (PATH_MAX - 1, 8 * 1024)
+
+struct cd_buf
+{
+ /* FIXME maybe allocate this via malloc, rather than using the stack.
+ But that would be the sole use of malloc. Is it worth it to
+ let chdir_long fail due to a low-memory condition?
+ But when using malloc, and assuming we remove the `concession'
+ above, we'll still have to avoid allocating 2^31 bytes on
+ systems that define PATH_MAX to very large number.
+ Ideally, we'd allocate enough to deal with most names, and
+ dynamically increase the buffer size only when necessary. */
+ char buffer[MAX_COMPONENT_LENGTH + 1];
+ char *avail;
+ int fd;
+};
+
+/* Like memchr, but return the number of bytes from MEM
+ to the first occurrence of C thereafter. Search only
+ LEN bytes. Return LEN if C is not found. */
+static inline size_t
+memchrcspn (char const *mem, int c, size_t len)
+{
+ char const *found = memchr (mem, c, len);
+ if (!found)
+ return len;
+
+ len = found - mem;
+ return len;
+}
+
+static void
+cdb_init (struct cd_buf *cdb)
+{
+ cdb->avail = cdb->buffer;
+ cdb->fd = AT_FDCWD;
+}
+
+static inline bool
+cdb_empty (struct cd_buf const *cdb)
+{
+ return cdb->avail == cdb->buffer;
+}
+
+static inline int
+cdb_fchdir (struct cd_buf const *cdb)
+{
+ return fchdir (cdb->fd);
+}
+
+static int
+cdb_advance_fd (struct cd_buf *cdb, char const *dir)
+{
+ int new_fd = openat (cdb->fd, dir, O_RDONLY | O_DIRECTORY);
+ if (new_fd < 0)
+ {
+ new_fd = openat (cdb->fd, dir, O_WRONLY | O_DIRECTORY);
+ if (new_fd < 0)
+ return -1;
+ }
+
+ if (cdb->fd != AT_FDCWD)
+ close (cdb->fd);
+ cdb->fd = new_fd;
+
+ return 0;
+}
+
+static int
+cdb_flush (struct cd_buf *cdb)
+{
+ if (cdb_empty (cdb))
+ return 0;
+
+ cdb->avail[0] = '\0';
+ if (cdb_advance_fd (cdb, cdb->buffer) != 0)
+ return -1;
+
+ cdb->avail = cdb->buffer;
+
+ return 0;
+}
+
+static void
+cdb_free (struct cd_buf *cdb)
+{
+ if (0 <= cdb->fd && close (cdb->fd) != 0)
+ abort ();
+}
+
+static int
+cdb_append (struct cd_buf *cdb, char const *s, size_t len)
+{
+ char const *end = cdb->buffer + sizeof cdb->buffer;
+
+ /* Insert a slash separator if there is a preceding byte
+ and it's not a slash. */
+ bool need_slash = (cdb->buffer < cdb->avail && cdb->avail[-1] != '/');
+ size_t n_free;
+
+ if (sizeof cdb->buffer < len + 1)
+ {
+ /* This single component is too long. */
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ /* See if there's enough room for the `/', the new component and
+ a trailing NUL. */
+ n_free = end - cdb->avail;
+ if (n_free < need_slash + len + 1)
+ {
+ if (cdb_flush (cdb) != 0)
+ return -1;
+ need_slash = false;
+ }
+
+ if (need_slash)
+ *(cdb->avail)++ = '/';
+
+ cdb->avail = mempcpy (cdb->avail, s, len);
+ return 0;
+}
+
+/* This is a wrapper around chdir that works even on PATH_MAX-limited
+ systems. It handles an arbitrarily long directory name by extracting
+ and processing manageable portions of the name. On systems without
+ the openat syscall, this means changing the working directory to
+ more and more `distant' points along the long directory name and
+ then restoring the working directory.
+ If any of those attempts to change or restore the working directory
+ fails, this function exits nonzero.
+
+ Note that this function may still fail with errno == ENAMETOOLONG,
+ but only if the specified directory name contains a component that
+ is long enough to provoke such a failure all by itself (e.g. if the
+ component is longer than PATH_MAX on systems that define PATH_MAX). */
+
+int
+chdir_long (char const *dir)
+{
+ int e = chdir (dir);
+ if (e == 0 || errno != ENAMETOOLONG)
+ return e;
+
+ {
+ size_t len = strlen (dir);
+ char const *dir_end = dir + len;
+ char const *d;
+ struct cd_buf cdb;
+
+ cdb_init (&cdb);
+
+ /* If DIR is the empty string, then the chdir above
+ must have failed and set errno to ENOENT. */
+ assert (0 < len);
+
+ if (*dir == '/')
+ {
+ /* Names starting with exactly two slashes followed by at least
+ one non-slash are special --
+ for example, in some environments //Hostname/file may
+ denote a file on a different host.
+ Preserve those two leading slashes. Treat all other
+ sequences of slashes like a single one. */
+ if (3 <= len && dir[1] == '/' && dir[2] != '/')
+ {
+ size_t name_len = 1 + strcspn (dir + 3, "/");
+ if (cdb_append (&cdb, dir, 2 + name_len) != 0)
+ goto Fail;
+ /* Advance D to next slash or to end of string. */
+ d = dir + 2 + name_len;
+ assert (*d == '/' || *d == '\0');
+ }
+ else
+ {
+ if (cdb_append (&cdb, "/", 1) != 0)
+ goto Fail;
+ d = dir + 1;
+ }
+ }
+ else
+ {
+ d = dir;
+ }
+
+ while (1)
+ {
+ /* Skip any slashes to find start of next component --
+ or the end of DIR. */
+ char const *start = d + strspn (d, "/");
+ if (*start == '\0')
+ {
+ if (cdb_flush (&cdb) != 0)
+ goto Fail;
+ break;
+ }
+ /* If the remaining portion is no longer than PATH_MAX, then
+ flush anything that is buffered and do the rest in one chunk. */
+ if (dir_end - start <= PATH_MAX)
+ {
+ if (cdb_flush (&cdb) != 0
+ || cdb_advance_fd (&cdb, start) != 0)
+ goto Fail;
+ break;
+ }
+
+ len = memchrcspn (start, '/', dir_end - start);
+ assert (len == strcspn (start, "/"));
+ d = start + len;
+ if (cdb_append (&cdb, start, len) != 0)
+ goto Fail;
+ }
+
+ if (cdb_fchdir (&cdb) != 0)
+ goto Fail;
+
+ cdb_free (&cdb);
+ return 0;
+
+ Fail:
+ {
+ int saved_errno = errno;
+ cdb_free (&cdb);
+ errno = saved_errno;
+ return -1;
+ }
+ }
+}
+
+#if TEST_CHDIR
+
+# include <stdio.h>
+# include "closeout.h"
+# include "error.h"
+
+char *program_name;
+
+int
+main (int argc, char *argv[])
+{
+ char *line = NULL;
+ size_t n = 0;
+ int len;
+
+ program_name = argv[0];
+ atexit (close_stdout);
+
+ len = getline (&line, &n, stdin);
+ if (len < 0)
+ {
+ int saved_errno = errno;
+ if (feof (stdin))
+ exit (0);
+
+ error (EXIT_FAILURE, saved_errno,
+ "reading standard input");
+ }
+ else if (len == 0)
+ exit (0);
+
+ if (line[len-1] == '\n')
+ line[len-1] = '\0';
+
+ if (chdir_long (line) != 0)
+ error (EXIT_FAILURE, errno,
+ "chdir_long failed: %s", line);
+
+ {
+ /* Using `pwd' here makes sense only if it is a robust implementation,
+ like the one in coreutils after the 2004-04-19 changes. */
+ char const *cmd = "pwd";
+ execlp (cmd, (char *) NULL);
+ error (EXIT_FAILURE, errno, "%s", cmd);
+ }
+
+ /* not reached */
+ abort ();
+}
+#endif
+
+/*
+Local Variables:
+compile-command: "gcc -DTEST_CHDIR=1 -DHAVE_CONFIG_H -I.. -g -O -W -Wall chdir-long.c libfetish.a"
+End:
+*/
diff --git a/lib/chdir-long.h b/lib/chdir-long.h
new file mode 100644
index 0000000000..47fa791607
--- /dev/null
+++ b/lib/chdir-long.h
@@ -0,0 +1,35 @@
+/* provide a chdir function that tries not to fail due to ENAMETOOLONG
+ Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Jim Meyering. */
+
+#include <unistd.h>
+#include <limits.h>
+
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+# endif
+#endif
+
+/* On systems without PATH_MAX, presume that chdir accepts
+ arbitrarily long directory names. */
+#ifndef PATH_MAX
+# define chdir_long(Dir) chdir (Dir)
+#else
+int chdir_long (char const *dir);
+#endif
diff --git a/lib/openat.c b/lib/openat.c
new file mode 100644
index 0000000000..fa617b807f
--- /dev/null
+++ b/lib/openat.c
@@ -0,0 +1,91 @@
+/* provide a replacement openat function
+ Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#include <config.h>
+
+#include "openat.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "error.h"
+#include "exitfail.h"
+#include "save-cwd.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/* Replacement for Solaris' openat function.
+ <http://www.google.com/search?q=openat+site:docs.sun.com>
+ Simulate it by doing save_cwd/fchdir/open/restore_cwd.
+ If either the save_cwd or the restore_cwd fails (relatively unlikely,
+ and usually indicative of a problem that deserves close attention),
+ then give a diagnostic and exit nonzero.
+ Otherwise, upon failure, set errno and return -1, as openat does.
+ Upon successful completion, return a file descriptor. */
+int
+rpl_openat (int fd, char const *filename, int flags, ...)
+{
+ struct saved_cwd saved_cwd;
+ int saved_errno;
+ int new_fd;
+ mode_t mode = 0;
+
+ if (flags & O_CREAT)
+ {
+ va_list arg;
+ va_start (arg, flags);
+
+ /* Assume that mode_t is passed compatibly with mode_t's type
+ after argument promotion. */
+ mode = va_arg (arg, mode_t);
+
+ va_end (arg);
+ }
+
+ if (fd == AT_FDCWD || *filename == '/')
+ return open (filename, flags, mode);
+
+ if (save_cwd (&saved_cwd) != 0)
+ error (exit_failure, errno,
+ _("openat: unable to record current working directory"));
+
+ if (fchdir (fd) != 0)
+ {
+ saved_errno = errno;
+ free_cwd (&saved_cwd);
+ errno = saved_errno;
+ return -1;
+ }
+
+ new_fd = open (filename, flags, mode);
+ saved_errno = errno;
+
+ if (restore_cwd (&saved_cwd) != 0)
+ error (exit_failure, errno,
+ _("openat: unable to restore working directory"));
+
+ free_cwd (&saved_cwd);
+
+ errno = saved_errno;
+ return new_fd;
+}
diff --git a/lib/openat.h b/lib/openat.h
new file mode 100644
index 0000000000..74f5508db9
--- /dev/null
+++ b/lib/openat.h
@@ -0,0 +1,35 @@
+/* provide a replacement openat function
+ Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifndef AT_FDCWD
+# define AT_FDCWD (-3041965) /* same value as Solaris 9 */
+
+# ifdef __OPENAT_PREFIX
+# undef openat
+# define __OPENAT_CONCAT(x, y) x ## y
+# define __OPENAT_XCONCAT(x, y) __OPENAT_CONCAT (x, y)
+# define __OPENAT_ID(y) __OPENAT_XCONCAT (__OPENAT_PREFIX, y)
+# define openat __OPENAT_ID (openat)
+int openat (int fd, char const *filename, int flags, /* mode_t mode */ ...);
+# endif
+#endif
diff --git a/lib/save-cwd.c b/lib/save-cwd.c
index 93b1fe85ca..272f7421e9 100644
--- a/lib/save-cwd.c
+++ b/lib/save-cwd.c
@@ -21,6 +21,8 @@
# include "config.h"
#endif
+#include "save-cwd.h"
+
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -37,11 +39,7 @@
#include <errno.h>
-#ifndef O_DIRECTORY
-# define O_DIRECTORY 0
-#endif
-
-#include "save-cwd.h"
+#include "chdir-long.h"
#include "xgetcwd.h"
/* Record the location of the current working directory in CWD so that
@@ -64,48 +62,49 @@
int
save_cwd (struct saved_cwd *cwd)
{
+#if !HAVE_FCHDIR
+# undef fchdir
+# define fchdir(x) (abort (), 0)
+ bool have_working_fchdir = false;
+ bool fchdir_needs_testing = false;
+#elif (__sgi || __sun)
static bool have_working_fchdir = true;
+ bool fchdir_needs_testing = true;
+#else
+ bool have_working_fchdir = true;
+ bool fchdir_needs_testing = false;
+#endif
cwd->desc = -1;
cwd->name = NULL;
if (have_working_fchdir)
{
-#if HAVE_FCHDIR
- cwd->desc = open (".", O_RDONLY | O_DIRECTORY);
- if (cwd->desc < 0)
- cwd->desc = open (".", O_WRONLY | O_DIRECTORY);
+ cwd->desc = open (".", O_RDONLY);
if (cwd->desc < 0)
{
- cwd->name = xgetcwd ();
- return cwd->name ? 0 : -1;
+ cwd->desc = open (".", O_WRONLY);
+ if (cwd->desc < 0)
+ {
+ cwd->name = xgetcwd ();
+ return cwd->name ? 0 : -1;
+ }
}
-# if __sun__ || sun
/* On SunOS 4 and IRIX 5.3, fchdir returns EINVAL when auditing
is enabled, so we have to fall back to chdir. */
- if (fchdir (cwd->desc))
+ if (fchdir_needs_testing && fchdir (cwd->desc) != 0)
{
- if (errno == EINVAL)
- {
- close (cwd->desc);
- cwd->desc = -1;
- have_working_fchdir = false;
- }
- else
+ int saved_errno = errno;
+ close (cwd->desc);
+ cwd->desc = -1;
+ if (saved_errno != EINVAL)
{
- int saved_errno = errno;
- close (cwd->desc);
- cwd->desc = -1;
errno = saved_errno;
return -1;
}
+ have_working_fchdir = false;
}
-# endif /* __sun__ || sun */
-#else
-# define fchdir(x) (abort (), 0)
- have_working_fchdir = false;
-#endif
}
if (!have_working_fchdir)
@@ -127,7 +126,7 @@ restore_cwd (const struct saved_cwd *cwd)
if (0 <= cwd->desc)
return fchdir (cwd->desc);
else
- return chdir (cwd->name);
+ return chdir_long (cwd->name);
}
void
diff --git a/m4/chdir-long.m4 b/m4/chdir-long.m4
new file mode 100644
index 0000000000..eef75d7677
--- /dev/null
+++ b/m4/chdir-long.m4
@@ -0,0 +1,41 @@
+#serial 4
+
+# Use Gnulib's robust chdir function.
+# It can handle arbitrarily long directory names, which means
+# that when it is given the name of an existing directory, it
+# never fails with ENAMETOOLONG.
+# Arrange to compile chdir-long.c only on systems that define PATH_MAX.
+
+dnl Copyright (C) 2004 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.
+
+# Written by Jim Meyering.
+
+AC_DEFUN([gl_FUNC_CHDIR_LONG],
+[
+ AC_LIBSOURCES([chdir-long.c, chdir-long.h])
+ AC_CACHE_CHECK([whether this system has a definition of PATH_MAX],
+ gl_have_path_max_definition,
+ [AC_EGREP_CPP([have_path_max_definition],
+ [#include <unistd.h>
+#include <limits.h>
+#ifdef PATH_MAX
+have_path_max_definition
+#endif],
+ gl_have_path_max_definition=yes,
+ gl_have_path_max_definition=no)])
+
+ if test $gl_have_path_max_definition; then
+ AC_LIBOBJ([chdir-long])
+ gl_PREREQ_CHDIR_LONG
+ fi
+])
+
+AC_DEFUN([gl_PREREQ_CHDIR_LONG],
+[
+ AM_STDBOOL_H
+ gl_FUNC_MEMPCPY
+ gl_FUNC_OPENAT
+])
diff --git a/m4/openat.m4 b/m4/openat.m4
new file mode 100644
index 0000000000..27b0e59e6e
--- /dev/null
+++ b/m4/openat.m4
@@ -0,0 +1,28 @@
+#serial 3
+# See if we need to use our replacement for Solaris' openat function.
+
+dnl Copyright (C) 2004 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.
+
+# Written by Jim Meyering.
+
+AC_DEFUN([gl_FUNC_OPENAT],
+[
+ AC_LIBSOURCES([openat.c, openat.h])
+ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+ AC_REPLACE_FUNCS(openat)
+ case $ac_cv_func_openat in
+ yes) ;;
+ *)
+ AC_DEFINE([__OPENAT_PREFIX], [[rpl_]],
+ [Define to rpl_ if the openat replacement function should be used.])
+ gl_PREREQ_OPENAT;;
+ esac
+])
+
+AC_DEFUN([gl_PREREQ_OPENAT],
+[
+ AC_REQUIRE([gl_SAVE_CWD])
+])
diff --git a/m4/save-cwd.m4 b/m4/save-cwd.m4
index f127222813..79173c212c 100644
--- a/m4/save-cwd.m4
+++ b/m4/save-cwd.m4
@@ -1,5 +1,5 @@
-# save-cwd.m4 serial 2
-dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+# save-cwd.m4 serial 3
+dnl Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
@@ -8,6 +8,8 @@ dnl the same distribution terms as the rest of that program.
AC_DEFUN([gl_SAVE_CWD],
[
+ AC_LIBSOURCES([save-cwd.c, save-cwd.h])
+ AC_LIBOBJ([save-cwd])
dnl Prerequisites for lib/save-cwd.c.
AC_CHECK_HEADERS_ONCE(fcntl.h unistd.h)
AC_CHECK_FUNCS(fchdir)
diff --git a/modules/chdir-long b/modules/chdir-long
new file mode 100644
index 0000000000..2e6d823dd7
--- /dev/null
+++ b/modules/chdir-long
@@ -0,0 +1,25 @@
+Description:
+chdir-like function that tries not to fail due to ENAMETOOLONG
+
+Files:
+lib/chdir-long.h
+lib/chdir-long.c
+m4/chdir-long.m4
+
+Depends-on:
+openat
+mempcpy
+
+configure.ac:
+gl_FUNC_CHDIR_LONG
+
+Makefile.am:
+
+Include:
+"chdir-long.h"
+
+License:
+GPL
+
+Maintainer:
+Jim Meyering
diff --git a/modules/openat b/modules/openat
new file mode 100644
index 0000000000..7366aec5db
--- /dev/null
+++ b/modules/openat
@@ -0,0 +1,27 @@
+Description:
+Open a file at a directory.
+
+Files:
+lib/openat.c
+lib/openat.h
+m4/openat.m4
+
+Depends-on:
+save-cwd
+gettext
+error
+exitfail
+
+configure.ac:
+gl_FUNC_OPENAT
+
+Makefile.am:
+
+Include:
+"openat.h"
+
+License:
+GPL
+
+Maintainer:
+Jim Meyering
diff --git a/modules/save-cwd b/modules/save-cwd
index 67f226df32..405ead8ed3 100644
--- a/modules/save-cwd
+++ b/modules/save-cwd
@@ -7,13 +7,13 @@ lib/save-cwd.c
m4/save-cwd.m4
Depends-on:
+chdir-long
xgetcwd
configure.ac:
gl_SAVE_CWD
Makefile.am:
-lib_SOURCES += save-cwd.h save-cwd.c
Include:
"save-cwd.h"