(no message)
[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)
36226ba7 19static char sccsid[] = "@(#)getcwd.c 5.7 (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>
36226ba7
KB
25#include <string.h>
26
27#define ISDOT(dp) \
28 (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
29 dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
9b6e6036
SL
30
31char *
8a4b7e23
KB
32getwd(store)
33 char *store;
9b6e6036 34{
8a4b7e23 35 extern int errno;
8a4b7e23 36 register struct dirent *dp;
36226ba7
KB
37 register DIR *dir;
38 register ino_t ino;
8a4b7e23 39 register char *pp, *pu;
36226ba7
KB
40 register int first;
41 struct stat s;
42 dev_t root_dev, dev;
8a4b7e23 43 ino_t root_ino;
1f8e47f9 44 int save_errno, found;
36226ba7 45 char path[MAXPATHLEN], up[MAXPATHLEN], *file;
9b6e6036 46
36226ba7 47 /* save root values */
1f8e47f9
MK
48 if (stat("/", &s)) {
49 file = "/";
8a4b7e23 50 goto err;
1f8e47f9 51 }
8a4b7e23
KB
52 root_dev = s.st_dev;
53 root_ino = s.st_ino;
36226ba7
KB
54
55 /* init path pointer; built from the end of the buffer */
8a4b7e23
KB
56 pp = path + sizeof(path) - 1;
57 *pp = '\0';
36226ba7
KB
58
59 /* special case first stat, it's ".", not ".." */
60 up[0] = '.';
61 up[1] = '\0';
62
8a4b7e23 63 for (pu = up, first = 1;; first = 0) {
36226ba7
KB
64 /* stat current level */
65 if (lstat(up, &s)) {
66 file = up;
67 goto err;
68 }
69
70 /* save current node values */
71 ino = s.st_ino;
72 dev = s.st_dev;
73
74 /* check for root */
75 if (root_dev == dev && root_ino == ino) {
8a4b7e23 76 *store = '/';
1f8e47f9
MK
77 (void) strcpy(store + 1, pp);
78 return (store);
90432f68 79 }
36226ba7 80
8a4b7e23
KB
81 *pu++ = '.';
82 *pu++ = '.';
83 *pu = '\0';
36226ba7
KB
84
85 /* open and stat parent */
86 if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) {
1f8e47f9
MK
87 file = up;
88 goto err;
8a4b7e23 89 }
36226ba7
KB
90 found = save_errno = 0;
91
8a4b7e23 92 *pu++ = '/';
36226ba7
KB
93
94 /*
95 * if it's a mount point you have to stat each element because
96 * the inode number in the directory is for the entry in the
97 * parent directory, not the inode number of the mounted file.
98 */
99 if (s.st_dev == dev) {
100 while (dp = readdir(dir))
101 if (dp->d_fileno == ino)
102 goto hit;
103 } else {
104 while (dp = readdir(dir)) {
105 if (ISDOT(dp))
106 continue;
107 bcopy(dp->d_name, pu, dp->d_namlen + 1);
108 if (lstat(up, &s)) {
109 file = dp->d_name;
110 save_errno = errno;
111 errno = 0;
112 continue;
113 }
114 if (s.st_dev == dev && s.st_ino == ino) {
115hit: if (!first)
116 *--pp = '/';
117 pp -= dp->d_namlen;
118 bcopy(dp->d_name, pp, dp->d_namlen);
119 found = 1;
120 break;
121 }
1f8e47f9 122 }
36226ba7
KB
123 if (errno) {
124 file = up;
125 save_errno = errno;
90432f68 126 }
8a4b7e23 127 }
36226ba7
KB
128 (void) closedir(dir);
129
8a4b7e23 130 *pu = '\0';
36226ba7 131
1f8e47f9
MK
132 if (!found) {
133 /*
134 * We didn't find the current level in its parent
135 * directory; figure out what to complain about.
136 */
36226ba7 137 if (save_errno) {
1f8e47f9
MK
138 errno = save_errno;
139 goto err;
140 }
141 (void) sprintf(store, "%s not found in %s?\n",
142 first ? "." : pp, up);
143 return ((char *)NULL);
144 }
90432f68 145 }
1f8e47f9
MK
146err:
147 (void) sprintf(store, "getwd: %s: %s", file, strerror(errno));
148 return ((char *)NULL);
9b6e6036 149}