bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-gnulib] new getcwd module for gnulib, from coreutils


From: Paul Eggert
Subject: [Bug-gnulib] new getcwd module for gnulib, from coreutils
Date: Thu, 05 Aug 2004 23:33:16 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

I installed this:

2004-08-05  Paul Eggert  <address@hidden>

        * lib/getcwd.c, m4/getcwd.m4, modules/getcwd: New files.

--- /dev/null   2003-03-18 13:55:57 -0800
+++ modules/getcwd      2004-08-05 23:24:09 -0700
@@ -0,0 +1,21 @@
+Description:
+Return the current working directory.
+
+Files:
+lib/getcwd.c
+m4/getcwd-path-max.m4
+
+Depends-on:
+pathmax
+same
+
+configure.ac:
+GL_FUNC_GETCWD_PATH_MAX
+
+Makefile.am:
+
+Include:
+
+Maintainer:
+Jim Meyering
+
--- /dev/null   2003-03-18 13:55:57 -0800
+++ lib/getcwd.c        2004-08-04 23:22:39 -0700
@@ -0,0 +1,69 @@
+/* Provide a replacement for the POSIX getcwd function.
+   Copyright (C) 2003, 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "pathmax.h"
+#include "same.h"
+
+/* Guess high, because that makes the test below more conservative.
+   But this is a kludge, because we should really use
+   pathconf (".", _PC_NAME_MAX).  But it's probably not worth the cost.  */
+#define KLUDGE_POSIX_NAME_MAX 255
+
+#define MAX_SAFE_LEN (PATH_MAX - 1 - KLUDGE_POSIX_NAME_MAX - 1)
+
+/* Undefine getcwd here, as near the use as possible, in case any
+   of the files included above define it to rpl_getcwd.  */
+#undef getcwd
+
+/* Any declaration of getcwd from headers included above has
+   been changed to a declaration of rpl_getcwd.  Declare it here.  */
+extern char *getcwd (char *buf, size_t size);
+
+/* This is a wrapper for getcwd.
+   Some implementations (at least GNU libc 2.3.1 + linux-2.4.20) return
+   non-NULL for a working directory name longer than PATH_MAX, yet the
+   returned string is a strict prefix of the desired directory name.
+   Upon such a failure, free the offending string, set errno to
+   ENAMETOOLONG, and return NULL.
+
+   I've heard that this is a Linux kernel bug, and that it has
+   been fixed between 2.4.21-pre3 and 2.4.21-pre4.  */
+
+char *
+rpl_getcwd (char *buf, size_t size)
+{
+  char *cwd = getcwd (buf, size);
+
+  if (cwd == NULL)
+    return NULL;
+
+  if (strlen (cwd) <= MAX_SAFE_LEN || same_name (cwd, "."))
+    return cwd;
+
+  free (cwd);
+  errno = ENAMETOOLONG;
+  return NULL;
+}
--- /dev/null   2003-03-18 13:55:57 -0800
+++ m4/getcwd-path-max.m4       2004-08-05 23:26:34 -0700
@@ -0,0 +1,150 @@
+#serial 4
+# Check whether getcwd has the bug that it succeeds for a working directory
+# longer than PATH_MAX, yet returns a truncated directory name.
+# If so, arrange to compile the wrapper function.
+
+# This is necessary for at least GNU libc on linux-2.4.19 and 2.4.20.
+# I've heard that this is due to a Linux kernel bug, and that it has
+# been fixed between 2.4.21-pre3 and 2.4.21-pre4.  */
+
+# Copyright (C) 2003, 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.
+
+# From Jim Meyering
+
+AC_DEFUN([GL_FUNC_GETCWD_PATH_MAX],
+[
+  AC_CHECK_DECLS([getcwd])
+  AC_CACHE_CHECK([whether getcwd properly handles paths longer than PATH_MAX],
+                 gl_cv_func_getcwd_vs_path_max,
+  [
+  # Arrange for deletion of the temporary directory this test creates.
+  ac_clean_files="$ac_clean_files confdir3"
+  AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+/* Don't get link errors because mkdir is redefined to rpl_mkdir.  */
+#undef mkdir
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+/* The extra casts work around common compiler bugs.  */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
+   It is necessary at least when t == time_t.  */
+#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+                             ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
+#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+
+#ifndef INT_MAX
+# define INT_MAX TYPE_MAXIMUM (int)
+#endif
+
+/* The length of this name must be 8.  */
+#define DIR_NAME "confdir3"
+
+int
+main ()
+{
+#ifndef PATH_MAX
+  /* The Hurd doesn't define this, so getcwd can't exhibit the bug --
+     at least not on a local file system.  And if we were to start worrying
+     about remote file systems, we'd have to enable the wrapper function
+     all of the time, just to be safe.  That's not worth the cost.  */
+  exit (0);
+#elif INT_MAX - 9 <= PATH_MAX
+  /* The '9', above, comes from strlen (DIR_NAME) + 1.  */
+  /* FIXME: Assuming there's a system for which this is true,
+     this should be done in a compile test.  */
+  exit (0);
+#else
+  char buf[PATH_MAX + 20];
+  char *cwd = getcwd (buf, PATH_MAX);
+  size_t cwd_len;
+  int fail = 0;
+  size_t n_chdirs = 0;
+
+  if (cwd == NULL)
+    exit (1);
+
+  cwd_len = strlen (cwd);
+
+  while (1)
+    {
+      char *c;
+      size_t len;
+
+      cwd_len += 1 + strlen (DIR_NAME);
+      /* If mkdir or chdir fails, be pessimistic and consider that
+        as a failure, too.  */
+      if (mkdir (DIR_NAME, 0700) < 0 || chdir (DIR_NAME) < 0)
+       {
+         fail = 1;
+         break;
+       }
+      if ((c = getcwd (buf, PATH_MAX)) == NULL)
+        {
+         /* This allows any failure to indicate there is no bug.
+            FIXME: check errno?  */
+         break;
+       }
+      if ((len = strlen (c)) != cwd_len)
+       {
+         fail = 1;
+         break;
+       }
+      ++n_chdirs;
+      if (PATH_MAX < len)
+       break;
+    }
+
+  /* Leaving behind such a deep directory is not polite.
+     So clean up here, right away, even though the driving
+     shell script would also clean up.  */
+  {
+    size_t i;
+
+    /* Unlink first, in case the chdir failed.  */
+    unlink (DIR_NAME);
+    for (i = 0; i <= n_chdirs; i++)
+      {
+       if (chdir ("..") < 0)
+         break;
+       rmdir (DIR_NAME);
+      }
+  }
+
+  exit (fail);
+#endif
+}
+  ]])],
+       [gl_cv_func_getcwd_vs_path_max=yes],
+       [gl_cv_func_getcwd_vs_path_max=no],
+       [gl_cv_func_getcwd_vs_path_max=no])])
+
+  if test $gl_cv_func_getcwd_vs_path_max = no; then
+    AC_LIBOBJ(getcwd)
+    AC_DEFINE(getcwd, rpl_getcwd,
+      [Define to rpl_getcwd if the wrapper function should be used.])
+  fi
+])




reply via email to

[Prev in Thread] Current Thread [Next in Thread]