add Berkeley specific copyright notices
[unix-history] / usr / src / lib / libc / gen / getcwd.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#if defined(LIBC_SCCS) && !defined(lint)
8static char sccsid[] = "@(#)getcwd.c 5.3 (Berkeley) %G%";
9#endif LIBC_SCCS and not lint
10
11/*
12 * getwd() returns the pathname of the current working directory. On error
13 * an error message is copied to pathname and null pointer is returned.
14 */
15#include <sys/param.h>
16#include <sys/stat.h>
17#include <sys/dir.h>
18
19#define GETWDERR(s) strcpy(pathname, (s));
20
21char *strcpy();
22static int pathsize; /* pathname length */
23
24char *
25getwd(pathname)
26 char *pathname;
27{
28 char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */
29 char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
30 char curdir[MAXPATHLEN]; /* current directory buffer */
31 char *dptr = curdir; /* directory pointer */
32 char *prepend(); /* prepend dirname to pathname */
33 dev_t cdev, rdev; /* current & root device number */
34 ino_t cino, rino; /* current & root inode number */
35 DIR *dirp; /* directory stream */
36 struct direct *dir; /* directory entry struct */
37 struct stat d, dd; /* file status struct */
38
39 pathsize = 0;
40 *pnptr = '\0';
41 if (stat("/", &d) < 0) {
42 GETWDERR("getwd: can't stat /");
43 return (NULL);
44 }
45 rdev = d.st_dev;
46 rino = d.st_ino;
47 strcpy(dptr, "./");
48 dptr += 2;
49 if (stat(curdir, &d) < 0) {
50 GETWDERR("getwd: can't stat .");
51 return (NULL);
52 }
53 for (;;) {
54 if (d.st_ino == rino && d.st_dev == rdev)
55 break; /* reached root directory */
56 cino = d.st_ino;
57 cdev = d.st_dev;
58 strcpy(dptr, "../");
59 dptr += 3;
60 if ((dirp = opendir(curdir)) == NULL) {
61 GETWDERR("getwd: can't open ..");
62 return (NULL);
63 }
64 fstat(dirp->dd_fd, &d);
65 if (cdev == d.st_dev) {
66 if (cino == d.st_ino) {
67 /* reached root directory */
68 closedir(dirp);
69 break;
70 }
71 do {
72 if ((dir = readdir(dirp)) == NULL) {
73 closedir(dirp);
74 GETWDERR("getwd: read error in ..");
75 return (NULL);
76 }
77 } while (dir->d_ino != cino);
78 } else
79 do {
80 if ((dir = readdir(dirp)) == NULL) {
81 closedir(dirp);
82 GETWDERR("getwd: read error in ..");
83 return (NULL);
84 }
85 strcpy(dptr, dir->d_name);
86 lstat(curdir, &dd);
87 } while(dd.st_ino != cino || dd.st_dev != cdev);
88 pnptr = prepend("/", prepend(dir->d_name, pnptr));
89 closedir(dirp);
90 }
91 if (*pnptr == '\0') /* current dir == root dir */
92 strcpy(pathname, "/");
93 else
94 strcpy(pathname, pnptr);
95 return (pathname);
96}
97
98/*
99 * prepend() tacks a directory name onto the front of a pathname.
100 */
101static char *
102prepend(dirname, pathname)
103 register char *dirname;
104 register char *pathname;
105{
106 register int i; /* directory name size counter */
107
108 for (i = 0; *dirname != '\0'; i++, dirname++)
109 continue;
110 if ((pathsize += i) < MAXPATHLEN)
111 while (i-- > 0)
112 *--pathname = *--dirname;
113 return (pathname);
114}