1 /* getcwd() - get the name of the current working directory.
10 #include <sys/types.h>
18 /* libc-private interface */
19 int __getcwd(char *, size_t);
21 static int addpath(const char *path
, char **ap
, const char *entry
)
22 /* Add the name of a directory entry at the front of the path being built.
23 * Note that the result always starts with a slash.
31 while (e
> entry
&& p
> path
) *--p
= *--e
;
33 if (p
== path
) return -1;
39 static int recover(char *p
)
40 /* Undo all those chdir("..")'s that have been recorded by addpath. This
41 * has to be done entry by entry, because the whole pathname may be too long.
50 do p
++; while (*p
!= 0 && *p
!= '/');
53 if (chdir(p0
) < 0) return -1;
60 int __getcwd(char *path
, size_t size
)
62 struct stat above
, current
, tmp
;
66 const char *dotdot
= "..";
69 if (path
== NULL
|| size
<= 1) { errno
= EINVAL
; return -1; }
74 if (stat(".", ¤t
) < 0) return -1;
77 if (stat(dotdot
, &above
) < 0) { recover(p
); return -1; }
79 if (above
.st_dev
== current
.st_dev
80 && above
.st_ino
== current
.st_ino
)
81 break; /* Root dir found */
83 if ((d
= opendir(dotdot
)) == NULL
) { recover(p
); return -1; }
85 /* Cycle is 0 for a simple inode nr search, or 1 for a search
86 * for inode *and* device nr.
88 cycle
= above
.st_dev
== current
.st_dev
? 0 : 1;
91 char name
[3 + NAME_MAX
+ 1];
94 if ((entry
= readdir(d
)) == NULL
) {
106 if (strcmp(entry
->d_name
, ".") == 0) continue;
107 if (strcmp(entry
->d_name
, "..") == 0) continue;
111 /* Simple test on inode nr. */
112 if (entry
->d_ino
!= current
.st_ino
) continue;
116 /* Current is mounted. */
118 strcpy(name
+3, entry
->d_name
);
119 if (stat(name
, &tmp
) < 0) continue;
122 } while (tmp
.st_ino
!= current
.st_ino
123 || tmp
.st_dev
!= current
.st_dev
);
126 if (addpath(path
, &up
, entry
->d_name
) < 0) {
134 if (chdir(dotdot
) < 0) { recover(p
); return -1; }
139 if (recover(p
) < 0) return -1; /* Undo all those chdir("..")'s. */
140 if (*p
== 0) *--p
= '/'; /* Cwd is "/" if nothing added */
141 if (p
> path
) strcpy(path
, p
); /* Move string to start of path. */