POSIX 1003.1: sigsetjmp, siglongjmp, function prototypes
[unix-history] / usr / src / lib / libc / gen / getcwd.c
CommitLineData
bb0cfa24 1/*
8a4b7e23
KB
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
bb0cfa24
DF
16 */
17
2ce81398 18#if defined(LIBC_SCCS) && !defined(lint)
1f8e47f9 19static char sccsid[] = "@(#)getcwd.c 5.6 (Berkeley) %G%";
8a4b7e23 20#endif /* LIBC_SCCS and not lint */
9b6e6036 21
87dccba9
SL
22#include <sys/param.h>
23#include <sys/stat.h>
8a4b7e23 24#include <dirent.h>
9b6e6036
SL
25
26char *
8a4b7e23
KB
27getwd(store)
28 char *store;
9b6e6036 29{
8a4b7e23
KB
30 extern int errno;
31 register DIR *dir;
32 register struct dirent *dp;
33 register int first;
34 register char *pp, *pu;
35 struct stat s, tmp;
36 dev_t root_dev;
37 ino_t root_ino;
1f8e47f9
MK
38 int save_errno, found;
39 char path[MAXPATHLEN], up[MAXPATHLEN], *file, *strerror();
9b6e6036 40
1f8e47f9
MK
41 if (stat("/", &s)) {
42 file = "/";
8a4b7e23 43 goto err;
1f8e47f9 44 }
8a4b7e23
KB
45 root_dev = s.st_dev;
46 root_ino = s.st_ino;
1f8e47f9
MK
47 if (stat(".", &s)) {
48 file = ".";
8a4b7e23 49 goto err;
1f8e47f9 50 }
8a4b7e23
KB
51 pp = path + sizeof(path) - 1;
52 *pp = '\0';
53 for (pu = up, first = 1;; first = 0) {
54 if (root_dev == s.st_dev && root_ino == s.st_ino) {
55 *store = '/';
1f8e47f9
MK
56 (void) strcpy(store + 1, pp);
57 return (store);
90432f68 58 }
8a4b7e23
KB
59 *pu++ = '.';
60 *pu++ = '.';
61 *pu = '\0';
62 if (!(dir = opendir(up))) {
1f8e47f9
MK
63 file = up;
64 goto err;
8a4b7e23
KB
65 }
66 *pu++ = '/';
1f8e47f9
MK
67 found = 0;
68 file = NULL;
69 while (errno = 0, dp = readdir(dir)) {
70 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
71 dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
8a4b7e23
KB
72 continue;
73 bcopy(dp->d_name, pu, dp->d_namlen + 1);
1f8e47f9
MK
74 if (lstat(up, &tmp)) {
75 file = dp->d_name;
76 save_errno = errno;
77 continue;
78 }
8a4b7e23
KB
79 if (tmp.st_dev == s.st_dev && tmp.st_ino == s.st_ino) {
80 if (!first)
81 *--pp = '/';
82 pp -= dp->d_namlen;
83 bcopy(dp->d_name, pp, dp->d_namlen);
1f8e47f9 84 found = 1;
90432f68
SL
85 break;
86 }
8a4b7e23 87 }
1f8e47f9
MK
88 if (errno) {
89 save_errno = errno;
90 file = up;
91 }
8a4b7e23
KB
92 closedir(dir);
93 *pu = '\0';
1f8e47f9
MK
94 if (!found) {
95 /*
96 * We didn't find the current level in its parent
97 * directory; figure out what to complain about.
98 */
99 if (file) {
100 errno = save_errno;
101 goto err;
102 }
103 (void) sprintf(store, "%s not found in %s?\n",
104 first ? "." : pp, up);
105 return ((char *)NULL);
106 }
107
108 /* stat "." at current level, then ascend */
8a4b7e23 109 if (lstat(up, &s)) {
1f8e47f9
MK
110 file = up;
111 goto err;
8a4b7e23 112 }
90432f68 113 }
1f8e47f9
MK
114
115err:
116 (void) sprintf(store, "getwd: %s: %s", file, strerror(errno));
117 return ((char *)NULL);
9b6e6036 118}