xref: /netbsd-src/external/gpl3/gcc/dist/libiberty/getpwd.c (revision 4fee23f98c45552038ad6b5bd05124a41302fb01)
1*4fee23f9Smrg /* getpwd.c - get the working directory */
2*4fee23f9Smrg 
3*4fee23f9Smrg /*
4*4fee23f9Smrg 
5*4fee23f9Smrg @deftypefn Supplemental char* getpwd (void)
6*4fee23f9Smrg 
7*4fee23f9Smrg Returns the current working directory.  This implementation caches the
8*4fee23f9Smrg result on the assumption that the process will not call @code{chdir}
9*4fee23f9Smrg between calls to @code{getpwd}.
10*4fee23f9Smrg 
11*4fee23f9Smrg @end deftypefn
12*4fee23f9Smrg 
13*4fee23f9Smrg */
14*4fee23f9Smrg 
15*4fee23f9Smrg #ifdef HAVE_CONFIG_H
16*4fee23f9Smrg #include "config.h"
17*4fee23f9Smrg #endif
18*4fee23f9Smrg 
19*4fee23f9Smrg #include <sys/types.h>
20*4fee23f9Smrg 
21*4fee23f9Smrg #include <errno.h>
22*4fee23f9Smrg #ifndef errno
23*4fee23f9Smrg extern int errno;
24*4fee23f9Smrg #endif
25*4fee23f9Smrg 
26*4fee23f9Smrg #ifdef HAVE_STDLIB_H
27*4fee23f9Smrg #include <stdlib.h>
28*4fee23f9Smrg #endif
29*4fee23f9Smrg #ifdef HAVE_UNISTD_H
30*4fee23f9Smrg #include <unistd.h>
31*4fee23f9Smrg #endif
32*4fee23f9Smrg #ifdef HAVE_SYS_PARAM_H
33*4fee23f9Smrg #include <sys/param.h>
34*4fee23f9Smrg #endif
35*4fee23f9Smrg #if HAVE_SYS_STAT_H
36*4fee23f9Smrg #include <sys/stat.h>
37*4fee23f9Smrg #endif
38*4fee23f9Smrg #if HAVE_LIMITS_H
39*4fee23f9Smrg #include <limits.h>
40*4fee23f9Smrg #endif
41*4fee23f9Smrg 
42*4fee23f9Smrg #include "libiberty.h"
43*4fee23f9Smrg 
44*4fee23f9Smrg /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
45*4fee23f9Smrg    BSD systems) now provides getcwd as called for by POSIX.  Allow for
46*4fee23f9Smrg    the few exceptions to the general rule here.  */
47*4fee23f9Smrg 
48*4fee23f9Smrg #if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
49*4fee23f9Smrg /* Prototype in case the system headers doesn't provide it. */
50*4fee23f9Smrg extern char *getwd ();
51*4fee23f9Smrg #define getcwd(buf,len) getwd(buf)
52*4fee23f9Smrg #endif
53*4fee23f9Smrg 
54*4fee23f9Smrg #ifdef MAXPATHLEN
55*4fee23f9Smrg #define GUESSPATHLEN (MAXPATHLEN + 1)
56*4fee23f9Smrg #else
57*4fee23f9Smrg #define GUESSPATHLEN 100
58*4fee23f9Smrg #endif
59*4fee23f9Smrg 
60*4fee23f9Smrg #if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
61*4fee23f9Smrg 
62*4fee23f9Smrg /* Get the working directory.  Use the PWD environment variable if it's
63*4fee23f9Smrg    set correctly, since this is faster and gives more uniform answers
64*4fee23f9Smrg    to the user.  Yield the working directory if successful; otherwise,
65*4fee23f9Smrg    yield 0 and set errno.  */
66*4fee23f9Smrg 
67*4fee23f9Smrg char *
getpwd(void)68*4fee23f9Smrg getpwd (void)
69*4fee23f9Smrg {
70*4fee23f9Smrg   static char *pwd;
71*4fee23f9Smrg   static int failure_errno;
72*4fee23f9Smrg 
73*4fee23f9Smrg   char *p = pwd;
74*4fee23f9Smrg   size_t s;
75*4fee23f9Smrg   struct stat dotstat, pwdstat;
76*4fee23f9Smrg 
77*4fee23f9Smrg   if (!p && !(errno = failure_errno))
78*4fee23f9Smrg     {
79*4fee23f9Smrg       if (! ((p = getenv ("PWD")) != 0
80*4fee23f9Smrg 	     && *p == '/'
81*4fee23f9Smrg 	     && stat (p, &pwdstat) == 0
82*4fee23f9Smrg 	     && stat (".", &dotstat) == 0
83*4fee23f9Smrg 	     && dotstat.st_ino == pwdstat.st_ino
84*4fee23f9Smrg 	     && dotstat.st_dev == pwdstat.st_dev))
85*4fee23f9Smrg 
86*4fee23f9Smrg 	/* The shortcut didn't work.  Try the slow, ``sure'' way.  */
87*4fee23f9Smrg 	for (s = GUESSPATHLEN;  !getcwd (p = XNEWVEC (char, s), s);  s *= 2)
88*4fee23f9Smrg 	  {
89*4fee23f9Smrg 	    int e = errno;
90*4fee23f9Smrg 	    free (p);
91*4fee23f9Smrg #ifdef ERANGE
92*4fee23f9Smrg 	    if (e != ERANGE)
93*4fee23f9Smrg #endif
94*4fee23f9Smrg 	      {
95*4fee23f9Smrg 		errno = failure_errno = e;
96*4fee23f9Smrg 		p = 0;
97*4fee23f9Smrg 		break;
98*4fee23f9Smrg 	      }
99*4fee23f9Smrg 	  }
100*4fee23f9Smrg 
101*4fee23f9Smrg       /* Cache the result.  This assumes that the program does
102*4fee23f9Smrg 	 not invoke chdir between calls to getpwd.  */
103*4fee23f9Smrg       pwd = p;
104*4fee23f9Smrg     }
105*4fee23f9Smrg   return p;
106*4fee23f9Smrg }
107*4fee23f9Smrg 
108*4fee23f9Smrg #else	/* VMS || _WIN32 && !__CYGWIN__ */
109*4fee23f9Smrg 
110*4fee23f9Smrg #ifndef MAXPATHLEN
111*4fee23f9Smrg #define MAXPATHLEN 255
112*4fee23f9Smrg #endif
113*4fee23f9Smrg 
114*4fee23f9Smrg char *
getpwd(void)115*4fee23f9Smrg getpwd (void)
116*4fee23f9Smrg {
117*4fee23f9Smrg   static char *pwd = 0;
118*4fee23f9Smrg 
119*4fee23f9Smrg   if (!pwd)
120*4fee23f9Smrg     pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
121*4fee23f9Smrg #ifdef VMS
122*4fee23f9Smrg 		  , 0
123*4fee23f9Smrg #endif
124*4fee23f9Smrg 		  );
125*4fee23f9Smrg   return pwd;
126*4fee23f9Smrg }
127*4fee23f9Smrg 
128*4fee23f9Smrg #endif	/* VMS || _WIN32 && !__CYGWIN__ */
129