getcwd: break fdopendir + save_cwd recursive loop (Bug#13516)
[gnulib.git] / m4 / getcwd-abort-bug.m4
index a6ee6cd..9b3b563 100644 (file)
@@ -58,16 +58,18 @@ AC_DEFUN([gl_FUNC_GETCWD_ABORT_BUG],
 int
 main ()
 {
-  char const *dir_name = "confdir-14B---";
   char *cwd;
   size_t initial_cwd_len;
   int fail = 0;
-  size_t desired_depth;
-  size_t d;
 
   /* The bug is triggered when PATH_MAX < getpagesize (), so skip
      this relatively expensive and invasive test if that's not true.  */
-  if (getpagesize () <= PATH_MAX)
+#ifdef PATH_MAX
+  int bug_possible = PATH_MAX < getpagesize ();
+#else
+  int bug_possible = 0;
+#endif
+  if (! bug_possible)
     return 0;
 
   cwd = getcwd (NULL, 0);
@@ -76,35 +78,43 @@ main ()
 
   initial_cwd_len = strlen (cwd);
   free (cwd);
-  desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
-                   / (1 + strlen (dir_name)));
-  for (d = 0; d < desired_depth; d++)
+
+  if (1)
     {
-      if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
+      static char const dir_name[] = "confdir-14B---";
+      size_t desired_depth = ((TARGET_LEN - 1 - initial_cwd_len)
+                              / sizeof dir_name);
+      size_t d;
+      for (d = 0; d < desired_depth; d++)
         {
-          fail = 3; /* Unable to construct deep hierarchy.  */
-          break;
+          if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0)
+            {
+              if (! (errno == ERANGE || errno == ENAMETOOLONG
+                     || errno == ENOENT))
+                fail = 3; /* Unable to construct deep hierarchy.  */
+              break;
+            }
         }
-    }
 
-  /* If libc has the bug in question, this invocation of getcwd
-     results in a failed assertion.  */
-  cwd = getcwd (NULL, 0);
-  if (cwd == NULL)
-    fail = 4; /* getcwd failed: it refuses to return a string longer
-                 than PATH_MAX.  */
-  free (cwd);
+      /* If libc has the bug in question, this invocation of getcwd
+         results in a failed assertion.  */
+      cwd = getcwd (NULL, 0);
+      if (cwd == NULL)
+        fail = 4; /* getcwd didn't assert, but it failed for a long name
+                     where the answer could have been learned.  */
+      free (cwd);
 
-  /* Call rmdir first, in case the above chdir failed.  */
-  rmdir (dir_name);
-  while (0 < d--)
-    {
-      if (chdir ("..") < 0)
+      /* Call rmdir first, in case the above chdir failed.  */
+      rmdir (dir_name);
+      while (0 < d--)
         {
-          fail = 5;
-          break;
+          if (chdir ("..") < 0)
+            {
+              fail = 5;
+              break;
+            }
+          rmdir (dir_name);
         }
-      rmdir (dir_name);
     }
 
   return fail;