xref: /csrg-svn/lib/libc/gen/getcwd.c (revision 10126)
1 /*	@(#)getcwd.c	4.3	(Berkeley)	01/04/83	*/
2 
3 /*
4  * Getwd
5  */
6 #include <sys/param.h>
7 #include <sys/stat.h>
8 #include <sys/dir.h>
9 
10 #define	dot	"."
11 #define	dotdot	".."
12 
13 static	char *name;
14 
15 static	DIR *file;
16 static	int off;
17 static	struct stat d, dd;
18 static	struct direct *dir;
19 
20 char *
21 getwd(np)
22 	char *np;
23 {
24 	dev_t rdev;
25 	ino_t rino;
26 
27 	off = -1;
28 	*np++ = '/';
29 	name = np;
30 	stat("/", &d);
31 	rdev = d.st_dev;
32 	rino = d.st_ino;
33 	for (;;) {
34 		stat(dot, &d);
35 		if (d.st_ino==rino && d.st_dev==rdev)
36 			goto done;
37 		if ((file = opendir(dotdot)) == NULL)
38 			prexit("getwd: cannot open ..\n");
39 		fstat(file->dd_fd, &dd);
40 		if (chdir(dotdot) < 0)
41 			prexit("getwd: cannot chdir to ..\n");
42 		if (d.st_dev == dd.st_dev) {
43 			if(d.st_ino == dd.st_ino)
44 				goto done;
45 			do
46 				if ((dir = readdir(file)) == NULL)
47 					prexit("getwd: read error in ..\n");
48 			while (dir->d_ino != d.st_ino);
49 		} else
50 			do {
51 				if ((dir = readdir(file)) == NULL)
52 					prexit("getwd: read error in ..\n");
53 				stat(dir->d_name, &dd);
54 			} while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
55 		closedir(file);
56 		cat();
57 	}
58 done:
59 	name--;
60 	if (chdir(name) < 0)
61 		prexit("getwd: can't change back\n");
62 	return (name);
63 }
64 
65 cat()
66 {
67 	register i, j;
68 
69 	i = -1;
70 	while (dir->d_name[++i] != 0);
71 	if ((off+i+2) > 1024-1)
72 		return;
73 	for(j=off+1; j>=0; --j)
74 		name[j+i+1] = name[j];
75 	if (off >= 0)
76 		name[i] = '/';
77 	off=i+off+1;
78 	name[off] = 0;
79 	for(--i; i>=0; --i)
80 		name[i] = dir->d_name[i];
81 }
82 
83 prexit(cp)
84 	char *cp;
85 {
86 	write(2, cp, strlen(cp));
87 	exit(1);
88 }
89