xref: /csrg-svn/lib/libc/gen/getcwd.c (revision 37209)
121345Sdist /*
2*37209Sbostic  * Copyright (c) 1989 The Regents of the University of California.
3*37209Sbostic  * All rights reserved.
4*37209Sbostic  *
5*37209Sbostic  * Redistribution and use in source and binary forms are permitted
6*37209Sbostic  * provided that the above copyright notice and this paragraph are
7*37209Sbostic  * duplicated in all such forms and that any documentation,
8*37209Sbostic  * advertising materials, and other materials related to such
9*37209Sbostic  * distribution and use acknowledge that the software was developed
10*37209Sbostic  * by the University of California, Berkeley.  The name of the
11*37209Sbostic  * University may not be used to endorse or promote products derived
12*37209Sbostic  * from this software without specific prior written permission.
13*37209Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*37209Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*37209Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621345Sdist  */
179986Ssam 
1826565Sdonn #if defined(LIBC_SCCS) && !defined(lint)
19*37209Sbostic static char sccsid[] = "@(#)getcwd.c	5.4 (Berkeley) 03/18/89";
20*37209Sbostic #endif /* LIBC_SCCS and not lint */
2121345Sdist 
2210088Ssam #include <sys/param.h>
2310088Ssam #include <sys/stat.h>
24*37209Sbostic #include <dirent.h>
259986Ssam 
269986Ssam char *
27*37209Sbostic getwd(store)
28*37209Sbostic 	char *store;
299986Ssam {
30*37209Sbostic 	extern int errno;
31*37209Sbostic 	register DIR *dir;
32*37209Sbostic 	register struct dirent *dp;
33*37209Sbostic 	register int first;
34*37209Sbostic 	register char *pp, *pu;
35*37209Sbostic 	struct stat s, tmp;
36*37209Sbostic 	dev_t root_dev;
37*37209Sbostic 	ino_t root_ino;
38*37209Sbostic 	char path[MAXPATHLEN], up[MAXPATHLEN], *strerror();
399986Ssam 
40*37209Sbostic 	if (stat("/", &s))
41*37209Sbostic 		goto err;
42*37209Sbostic 	root_dev = s.st_dev;
43*37209Sbostic 	root_ino = s.st_ino;
44*37209Sbostic 	if (stat(".", &s))
45*37209Sbostic 		goto err;
46*37209Sbostic 	pp = path + sizeof(path) - 1;
47*37209Sbostic 	*pp = '\0';
48*37209Sbostic 	for (pu = up, first = 1;; first = 0) {
49*37209Sbostic 		if (root_dev == s.st_dev && root_ino == s.st_ino) {
50*37209Sbostic 			*store = '/';
51*37209Sbostic 			(void)strcpy(store + 1, pp);
52*37209Sbostic 			return(store);
5310155Ssam 		}
54*37209Sbostic 		*pu++ = '.';
55*37209Sbostic 		*pu++ = '.';
56*37209Sbostic 		*pu = '\0';
57*37209Sbostic 		if (!(dir = opendir(up))) {
58*37209Sbostic 			(void)strcpy(path, "getwd: opendir failed.");
59*37209Sbostic 			return((char *)NULL);
60*37209Sbostic 		}
61*37209Sbostic 		*pu++ = '/';
62*37209Sbostic 		while (dp = readdir(dir)) {
63*37209Sbostic 			if (dp->d_name[0] == '.' && (!dp->d_name[1] ||
64*37209Sbostic 			    dp->d_name[1] == '.' && !dp->d_name[2]))
65*37209Sbostic 				continue;
66*37209Sbostic 			bcopy(dp->d_name, pu, dp->d_namlen + 1);
67*37209Sbostic 			if (lstat(up, &tmp))
68*37209Sbostic 				goto err;
69*37209Sbostic 			if (tmp.st_dev == s.st_dev && tmp.st_ino == s.st_ino) {
70*37209Sbostic 				if (!first)
71*37209Sbostic 					*--pp = '/';
72*37209Sbostic 				pp -= dp->d_namlen;
73*37209Sbostic 				bcopy(dp->d_name, pp, dp->d_namlen);
7410155Ssam 				break;
7510155Ssam 			}
76*37209Sbostic 		}
77*37209Sbostic 		closedir(dir);
78*37209Sbostic 		*pu = '\0';
79*37209Sbostic 		if (lstat(up, &s)) {
80*37209Sbostic err:			(void)sprintf(path, "getwd: %s", strerror(errno));
81*37209Sbostic 			return((char *)NULL);
82*37209Sbostic 		}
839986Ssam 	}
849986Ssam }
85