ANSI C; sprintf now returns an int.
[unix-history] / usr / src / lib / libc / gen / getcwd.c
CommitLineData
bb0cfa24
DF
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
2ce81398
DS
7#if defined(LIBC_SCCS) && !defined(lint)
8static char sccsid[] = "@(#)getcwd.c 5.2 (Berkeley) %G%";
9#endif LIBC_SCCS and not lint
9b6e6036
SL
10
11/*
90432f68
SL
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.
9b6e6036 14 */
87dccba9
SL
15#include <sys/param.h>
16#include <sys/stat.h>
17#include <sys/dir.h>
9b6e6036 18
90432f68 19#define GETWDERR(s) strcpy(pathname, (s));
9b6e6036 20
e8b0aeda 21char *strcpy();
90432f68 22static int pathsize; /* pathname length */
9b6e6036
SL
23
24char *
90432f68
SL
25getwd(pathname)
26 char *pathname;
9b6e6036 27{
34b028a5 28 char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */
90432f68 29 char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
762ac285
RC
30 char curdir[MAXPATHLEN]; /* current directory buffer */
31 char *dptr = curdir; /* directory pointer */
90432f68 32 char *prepend(); /* prepend dirname to pathname */
762ac285
RC
33 dev_t cdev, rdev; /* current & root device number */
34 ino_t cino, rino; /* current & root inode number */
90432f68 35 DIR *dirp; /* directory stream */
90432f68 36 struct direct *dir; /* directory entry struct */
762ac285 37 struct stat d, dd; /* file status struct */
9b6e6036 38
90432f68
SL
39 pathsize = 0;
40 *pnptr = '\0';
762ac285
RC
41 if (stat("/", &d) < 0) {
42 GETWDERR("getwd: can't stat /");
43 return (NULL);
44 }
9b6e6036
SL
45 rdev = d.st_dev;
46 rino = d.st_ino;
762ac285
RC
47 strcpy(dptr, "./");
48 dptr += 2;
49 if (stat(curdir, &d) < 0) {
50 GETWDERR("getwd: can't stat .");
51 return (NULL);
52 }
9b6e6036 53 for (;;) {
90432f68
SL
54 if (d.st_ino == rino && d.st_dev == rdev)
55 break; /* reached root directory */
762ac285
RC
56 cino = d.st_ino;
57 cdev = d.st_dev;
58 strcpy(dptr, "../");
59 dptr += 3;
60 if ((dirp = opendir(curdir)) == NULL) {
90432f68 61 GETWDERR("getwd: can't open ..");
762ac285 62 return (NULL);
90432f68 63 }
762ac285
RC
64 fstat(dirp->dd_fd, &d);
65 if (cdev == d.st_dev) {
66 if (cino == d.st_ino) {
90432f68
SL
67 /* reached root directory */
68 closedir(dirp);
69 break;
70 }
07fbd99b 71 do {
90432f68
SL
72 if ((dir = readdir(dirp)) == NULL) {
73 closedir(dirp);
74 GETWDERR("getwd: read error in ..");
762ac285 75 return (NULL);
90432f68 76 }
762ac285 77 } while (dir->d_ino != cino);
829e7c26
SL
78 } else
79 do {
762ac285 80 if ((dir = readdir(dirp)) == NULL) {
90432f68
SL
81 closedir(dirp);
82 GETWDERR("getwd: read error in ..");
762ac285 83 return (NULL);
90432f68 84 }
762ac285
RC
85 strcpy(dptr, dir->d_name);
86 lstat(curdir, &dd);
87 } while(dd.st_ino != cino || dd.st_dev != cdev);
90432f68 88 closedir(dirp);
762ac285 89 pnptr = prepend("/", prepend(dir->d_name, pnptr));
90432f68
SL
90 }
91 if (*pnptr == '\0') /* current dir == root dir */
762ac285
RC
92 strcpy(pathname, "/");
93 else
90432f68 94 strcpy(pathname, pnptr);
90432f68 95 return (pathname);
9b6e6036
SL
96}
97
90432f68
SL
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;
9b6e6036 105{
90432f68 106 register int i; /* directory name size counter */
9b6e6036 107
90432f68
SL
108 for (i = 0; *dirname != '\0'; i++, dirname++)
109 continue;
34b028a5 110 if ((pathsize += i) < MAXPATHLEN)
90432f68
SL
111 while (i-- > 0)
112 *--pathname = *--dirname;
113 return (pathname);
9b6e6036 114}