1#serial 1 2# Determine whether getcwd aborts when the length of the working directory 3# name is unusually large. Any length between 4k and 16k trigger the bug 4# when using glibc-2.4.90-9 or older. 5 6# Copyright (C) 2006 Free Software Foundation, Inc. 7# This file is free software; the Free Software Foundation 8# gives unlimited permission to copy and/or distribute it, 9# with or without modifications, as long as this notice is preserved. 10 11# From Jim Meyering 12 13# gl_FUNC_GETCWD_ABORT_BUG([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) 14AC_DEFUN([gl_FUNC_GETCWD_ABORT_BUG], 15[ 16 AC_CHECK_DECLS_ONCE(getcwd) 17 AC_CHECK_FUNCS(getpagesize) 18 AC_CACHE_CHECK([whether getcwd aborts when 4k < cwd_length < 16k], 19 gl_cv_func_getcwd_abort_bug, 20 [# Remove any remnants of a previous test. 21 rm -rf confdir-14B--- 22 # Arrange for deletion of the temporary directory this test creates. 23 ac_clean_files="$ac_clean_files confdir-14B---" 24 AC_RUN_IFELSE( 25 [AC_LANG_SOURCE( 26 [[ 27#include <stdlib.h> 28#include <unistd.h> 29#include <limits.h> 30#include <string.h> 31#include <sys/stat.h> 32 33/* Don't get link errors because mkdir is redefined to rpl_mkdir. */ 34#undef mkdir 35 36#ifndef S_IRWXU 37# define S_IRWXU 0700 38#endif 39 40/* FIXME: skip the run-test altogether on systems without getpagesize. */ 41#if ! HAVE_GETPAGESIZE 42# define getpagesize() 0 43#endif 44 45/* This size is chosen to be larger than PATH_MAX (4k), yet smaller than 46 the 16kB pagesize on ia64 linux. Those conditions make the code below 47 trigger a bug in glibc's getcwd implementation before 2.4.90-10. */ 48#define TARGET_LEN (5 * 1024) 49 50int 51main () 52{ 53 char const *dir_name = "confdir-14B---"; 54 char *cwd; 55 size_t initial_cwd_len; 56 int fail = 0; 57 size_t desired_depth; 58 size_t d; 59 60 /* The bug is triggered when PATH_MAX < getpagesize (), so skip 61 this relative expensive and invasive test if that's not true. */ 62 if (getpagesize () <= PATH_MAX) 63 return 0; 64 65 cwd = getcwd (NULL, 0); 66 if (cwd == NULL) 67 return 0; 68 69 initial_cwd_len = strlen (cwd); 70 free (cwd); 71 desired_depth = ((TARGET_LEN - 1 - initial_cwd_len) 72 / (1 + strlen (dir_name))); 73 for (d = 0; d < desired_depth; d++) 74 { 75 if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0) 76 { 77 fail = 3; /* Unable to construct deep hierarchy. */ 78 break; 79 } 80 } 81 82 /* If libc has the bug in question, this invocation of getcwd 83 results in a failed assertion. */ 84 cwd = getcwd (NULL, 0); 85 if (cwd == NULL) 86 fail = 4; /* getcwd failed. This is ok, and expected. */ 87 free (cwd); 88 89 /* Call rmdir first, in case the above chdir failed. */ 90 rmdir (dir_name); 91 while (0 < d--) 92 { 93 if (chdir ("..") < 0) 94 break; 95 rmdir (dir_name); 96 } 97 98 return 0; 99} 100 ]])], 101 [gl_cv_func_getcwd_abort_bug=no], 102 [gl_cv_func_getcwd_abort_bug=yes], 103 [gl_cv_func_getcwd_abort_bug=yes]) 104 ]) 105 AS_IF([test $gl_cv_func_getcwd_abort_bug = yes], [$1], [$2]) 106]) 107