1 /* getcwd() - get the name of the current working directory.
6 #define closedir _closedir
8 #define opendir _opendir
9 #define readdir _readdir
10 #define rewinddir _rewinddir
12 #include <sys/types.h>
20 static int addpath(const char *path
, char **ap
, const char *entry
)
21 /* Add the name of a directory entry at the front of the path being built.
22 * Note that the result always starts with a slash.
30 while (e
> entry
&& p
> path
) *--p
= *--e
;
32 if (p
== path
) return -1;
38 static int recover(char *p
)
39 /* Undo all those chdir("..")'s that have been recorded by addpath. This
40 * has to be done entry by entry, because the whole pathname may be too long.
49 do p
++; while (*p
!= 0 && *p
!= '/');
52 if (chdir(p0
) < 0) return -1;
59 char *getcwd(char *path
, size_t size
)
61 struct stat above
, current
, tmp
;
64 char *p
, *up
, *dotdot
;
67 if (path
== NULL
|| size
<= 1) { errno
= EINVAL
; return NULL
; }
72 if (stat(".", ¤t
) < 0) return NULL
;
76 if (stat(dotdot
, &above
) < 0) { recover(p
); return NULL
; }
78 if (above
.st_dev
== current
.st_dev
79 && above
.st_ino
== current
.st_ino
)
80 break; /* Root dir found */
82 if ((d
= opendir(dotdot
)) == NULL
) { recover(p
); return NULL
; }
84 /* Cycle is 0 for a simple inode nr search, or 1 for a search
85 * for inode *and* device nr.
87 cycle
= above
.st_dev
== current
.st_dev
? 0 : 1;
90 char name
[3 + NAME_MAX
+ 1];
93 if ((entry
= readdir(d
)) == NULL
) {
105 if (strcmp(entry
->d_name
, ".") == 0) continue;
106 if (strcmp(entry
->d_name
, "..") == 0) continue;
110 /* Simple test on inode nr. */
111 if (entry
->d_ino
!= current
.st_ino
) continue;
115 /* Current is mounted. */
117 strcpy(name
+3, entry
->d_name
);
118 if (stat(name
, &tmp
) < 0) continue;
121 } while (tmp
.st_ino
!= current
.st_ino
122 || tmp
.st_dev
!= current
.st_dev
);
125 if (addpath(path
, &up
, entry
->d_name
) < 0) {
133 if (chdir(dotdot
) < 0) { recover(p
); return NULL
; }
138 if (recover(p
) < 0) return NULL
; /* Undo all those chdir("..")'s. */
139 if (*p
== 0) *--p
= '/'; /* Cwd is "/" if nothing added */
140 if (p
> path
) strcpy(path
, p
); /* Move string to start of path. */