|
|
1.1 root 1: /*
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: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #if defined(LIBC_SCCS) && !defined(lint)
21: static char sccsid[] = "@(#)getwd.c 5.8 (Berkeley) 6/1/90";
22: #endif /* LIBC_SCCS and not lint */
23:
24: #include <sys/param.h>
25: #include <sys/stat.h>
26: #include <dirent.h>
27: #include <string.h>
28:
29: #define ISDOT(dp) \
30: (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
31: dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
32:
33: char *
34: getwd(store)
35: char *store;
36: {
37: extern int errno;
38: register struct dirent *dp;
39: register DIR *dir;
40: register ino_t ino;
41: register char *pp, *pu;
42: register int first;
43: struct stat s;
44: dev_t root_dev, dev;
45: ino_t root_ino;
46: int save_errno, found;
47: char path[MAXPATHLEN], up[MAXPATHLEN], *file;
48:
49: /* save root values */
50: if (stat("/", &s)) {
51: file = "/";
52: goto err;
53: }
54: root_dev = s.st_dev;
55: root_ino = s.st_ino;
56:
57: /* init path pointer; built from the end of the buffer */
58: pp = path + sizeof(path) - 1;
59: *pp = '\0';
60:
61: /* special case first stat, it's ".", not ".." */
62: up[0] = '.';
63: up[1] = '\0';
64:
65: for (pu = up, first = 1;; first = 0) {
66: /* stat current level */
67: if (lstat(up, &s)) {
68: file = up;
69: goto err;
70: }
71:
72: /* save current node values */
73: ino = s.st_ino;
74: dev = s.st_dev;
75:
76: /* check for root */
77: if (root_dev == dev && root_ino == ino) {
78: *store = '/';
79: (void) strcpy(store + 1, pp);
80: return (store);
81: }
82:
83: *pu++ = '.';
84: *pu++ = '.';
85: *pu = '\0';
86:
87: /* open and stat parent */
88: if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) {
89: file = up;
90: goto err;
91: }
92: found = save_errno = 0;
93:
94: *pu++ = '/';
95:
96: /*
97: * if it's a mount point you have to stat each element because
98: * the inode number in the directory is for the entry in the
99: * parent directory, not the inode number of the mounted file.
100: */
101: if (s.st_dev == dev) {
102: while (dp = readdir(dir))
103: if (dp->d_fileno == ino)
104: goto hit;
105: } else {
106: while (dp = readdir(dir)) {
107: if (ISDOT(dp))
108: continue;
109: bcopy(dp->d_name, pu, dp->d_namlen + 1);
110: if (lstat(up, &s)) {
111: file = dp->d_name;
112: save_errno = errno;
113: errno = 0;
114: continue;
115: }
116: if (s.st_dev == dev && s.st_ino == ino) {
117: hit: if (!first)
118: *--pp = '/';
119: pp -= dp->d_namlen;
120: bcopy(dp->d_name, pp, dp->d_namlen);
121: found = 1;
122: break;
123: }
124: }
125: if (errno) {
126: file = up;
127: save_errno = errno;
128: }
129: }
130: (void) closedir(dir);
131:
132: *pu = '\0';
133:
134: if (!found) {
135: /*
136: * We didn't find the current level in its parent
137: * directory; figure out what to complain about.
138: */
139: if (save_errno) {
140: errno = save_errno;
141: goto err;
142: }
143: (void) sprintf(store, "%s not found in %s?\n",
144: first ? "." : pp, up);
145: return ((char *)NULL);
146: }
147: }
148: err:
149: (void) sprintf(store, "getwd: %s: %s", file, strerror(errno));
150: return ((char *)NULL);
151: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.