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