xref: /csrg-svn/lib/libc/gen/getcwd.c (revision 40556)
121345Sdist /*
237209Sbostic  * Copyright (c) 1989 The Regents of the University of California.
337209Sbostic  * All rights reserved.
437209Sbostic  *
537209Sbostic  * Redistribution and use in source and binary forms are permitted
637209Sbostic  * provided that the above copyright notice and this paragraph are
737209Sbostic  * duplicated in all such forms and that any documentation,
837209Sbostic  * advertising materials, and other materials related to such
937209Sbostic  * distribution and use acknowledge that the software was developed
1037209Sbostic  * by the University of California, Berkeley.  The name of the
1137209Sbostic  * University may not be used to endorse or promote products derived
1237209Sbostic  * from this software without specific prior written permission.
1337209Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1437209Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1537209Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621345Sdist  */
179986Ssam 
1826565Sdonn #if defined(LIBC_SCCS) && !defined(lint)
19*40556Skarels static char sccsid[] = "@(#)getcwd.c	5.6 (Berkeley) 03/20/90";
2037209Sbostic #endif /* LIBC_SCCS and not lint */
2121345Sdist 
2210088Ssam #include <sys/param.h>
2310088Ssam #include <sys/stat.h>
2437209Sbostic #include <dirent.h>
259986Ssam 
269986Ssam char *
2737209Sbostic getwd(store)
2837209Sbostic 	char *store;
299986Ssam {
3037209Sbostic 	extern int errno;
3137209Sbostic 	register DIR *dir;
3237209Sbostic 	register struct dirent *dp;
3337209Sbostic 	register int first;
3437209Sbostic 	register char *pp, *pu;
3537209Sbostic 	struct stat s, tmp;
3637209Sbostic 	dev_t root_dev;
3737209Sbostic 	ino_t root_ino;
38*40556Skarels 	int save_errno, found;
39*40556Skarels 	char path[MAXPATHLEN], up[MAXPATHLEN], *file, *strerror();
409986Ssam 
41*40556Skarels 	if (stat("/", &s)) {
42*40556Skarels 		file = "/";
4337209Sbostic 		goto err;
44*40556Skarels 	}
4537209Sbostic 	root_dev = s.st_dev;
4637209Sbostic 	root_ino = s.st_ino;
47*40556Skarels 	if (stat(".", &s)) {
48*40556Skarels 		file = ".";
4937209Sbostic 		goto err;
50*40556Skarels 	}
5137209Sbostic 	pp = path + sizeof(path) - 1;
5237209Sbostic 	*pp = '\0';
5337209Sbostic 	for (pu = up, first = 1;; first = 0) {
5437209Sbostic 		if (root_dev == s.st_dev && root_ino == s.st_ino) {
5537209Sbostic 			*store = '/';
56*40556Skarels 			(void) strcpy(store + 1, pp);
57*40556Skarels 			return (store);
5810155Ssam 		}
5937209Sbostic 		*pu++ = '.';
6037209Sbostic 		*pu++ = '.';
6137209Sbostic 		*pu = '\0';
6237209Sbostic 		if (!(dir = opendir(up))) {
63*40556Skarels 			file = up;
64*40556Skarels 			goto err;
6537209Sbostic 		}
6637209Sbostic 		*pu++ = '/';
67*40556Skarels 		found = 0;
68*40556Skarels 		file = NULL;
69*40556Skarels 		while (errno = 0, dp = readdir(dir)) {
70*40556Skarels 			if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
71*40556Skarels 			    dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
7237209Sbostic 				continue;
7337209Sbostic 			bcopy(dp->d_name, pu, dp->d_namlen + 1);
74*40556Skarels 			if (lstat(up, &tmp)) {
75*40556Skarels 				file = dp->d_name;
76*40556Skarels 				save_errno = errno;
77*40556Skarels 				continue;
78*40556Skarels 			}
7937209Sbostic 			if (tmp.st_dev == s.st_dev && tmp.st_ino == s.st_ino) {
8037209Sbostic 				if (!first)
8137209Sbostic 					*--pp = '/';
8237209Sbostic 				pp -= dp->d_namlen;
8337209Sbostic 				bcopy(dp->d_name, pp, dp->d_namlen);
84*40556Skarels 				found = 1;
8510155Ssam 				break;
8610155Ssam 			}
8737209Sbostic 		}
88*40556Skarels 		if (errno) {
89*40556Skarels 			save_errno = errno;
90*40556Skarels 			file = up;
91*40556Skarels 		}
9237209Sbostic 		closedir(dir);
9337209Sbostic 		*pu = '\0';
94*40556Skarels 		if (!found) {
95*40556Skarels 			/*
96*40556Skarels 			 * We didn't find the current level in its parent
97*40556Skarels 			 * directory; figure out what to complain about.
98*40556Skarels 			 */
99*40556Skarels 			if (file) {
100*40556Skarels 				errno = save_errno;
101*40556Skarels 				goto err;
102*40556Skarels 			}
103*40556Skarels 			(void) sprintf(store, "%s not found in %s?\n",
104*40556Skarels 				first ? "." : pp, up);
105*40556Skarels 			return ((char *)NULL);
106*40556Skarels 		}
107*40556Skarels 
108*40556Skarels 		/* stat "." at current level, then ascend */
10937209Sbostic 		if (lstat(up, &s)) {
110*40556Skarels 			file = up;
111*40556Skarels 			goto err;
11237209Sbostic 		}
1139986Ssam 	}
114*40556Skarels 
115*40556Skarels err:
116*40556Skarels 	(void) sprintf(store, "getwd: %s: %s", file, strerror(errno));
117*40556Skarels 	return ((char *)NULL);
1189986Ssam }
119