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