1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)getcwd.c 5.8 (Berkeley) 06/01/90"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 #include <sys/param.h> 13 #include <sys/stat.h> 14 #include <dirent.h> 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')) 20 21 char * 22 getwd(store) 23 char *store; 24 { 25 extern int errno; 26 register struct dirent *dp; 27 register DIR *dir; 28 register ino_t ino; 29 register char *pp, *pu; 30 register int first; 31 struct stat s; 32 dev_t root_dev, dev; 33 ino_t root_ino; 34 int save_errno, found; 35 char path[MAXPATHLEN], up[MAXPATHLEN], *file; 36 37 /* save root values */ 38 if (stat("/", &s)) { 39 file = "/"; 40 goto err; 41 } 42 root_dev = s.st_dev; 43 root_ino = s.st_ino; 44 45 /* init path pointer; built from the end of the buffer */ 46 pp = path + sizeof(path) - 1; 47 *pp = '\0'; 48 49 /* special case first stat, it's ".", not ".." */ 50 up[0] = '.'; 51 up[1] = '\0'; 52 53 for (pu = up, first = 1;; first = 0) { 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) { 66 *store = '/'; 67 (void) strcpy(store + 1, pp); 68 return (store); 69 } 70 71 *pu++ = '.'; 72 *pu++ = '.'; 73 *pu = '\0'; 74 75 /* open and stat parent */ 76 if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) { 77 file = up; 78 goto err; 79 } 80 found = save_errno = 0; 81 82 *pu++ = '/'; 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) { 105 hit: if (!first) 106 *--pp = '/'; 107 pp -= dp->d_namlen; 108 bcopy(dp->d_name, pp, dp->d_namlen); 109 found = 1; 110 break; 111 } 112 } 113 if (errno) { 114 file = up; 115 save_errno = errno; 116 } 117 } 118 (void) closedir(dir); 119 120 *pu = '\0'; 121 122 if (!found) { 123 /* 124 * We didn't find the current level in its parent 125 * directory; figure out what to complain about. 126 */ 127 if (save_errno) { 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 } 135 } 136 err: 137 (void) sprintf(store, "getwd: %s: %s", file, strerror(errno)); 138 return ((char *)NULL); 139 } 140