121345Sdist /* 237209Sbostic * Copyright (c) 1989 The Regents of the University of California. 337209Sbostic * All rights reserved. 437209Sbostic * 5*42625Sbostic * %sccs.include.redist.c% 621345Sdist */ 79986Ssam 826565Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*42625Sbostic static char sccsid[] = "@(#)getcwd.c 5.8 (Berkeley) 06/01/90"; 1037209Sbostic #endif /* LIBC_SCCS and not lint */ 1121345Sdist 1210088Ssam #include <sys/param.h> 1310088Ssam #include <sys/stat.h> 1437209Sbostic #include <dirent.h> 1542396Sbostic #include <string.h> 169986Ssam 1742396Sbostic #define ISDOT(dp) \ 1842396Sbostic (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ 1942396Sbostic dp->d_name[1] == '.' && dp->d_name[2] == '\0')) 2042396Sbostic 219986Ssam char * 2237209Sbostic getwd(store) 2337209Sbostic char *store; 249986Ssam { 2537209Sbostic extern int errno; 2642396Sbostic register struct dirent *dp; 2737209Sbostic register DIR *dir; 2842396Sbostic register ino_t ino; 2942396Sbostic register char *pp, *pu; 3037209Sbostic register int first; 3142396Sbostic struct stat s; 3242396Sbostic dev_t root_dev, dev; 3337209Sbostic ino_t root_ino; 3440556Skarels int save_errno, found; 3542396Sbostic char path[MAXPATHLEN], up[MAXPATHLEN], *file; 369986Ssam 3742396Sbostic /* save root values */ 3840556Skarels if (stat("/", &s)) { 3940556Skarels file = "/"; 4037209Sbostic goto err; 4140556Skarels } 4237209Sbostic root_dev = s.st_dev; 4337209Sbostic root_ino = s.st_ino; 4442396Sbostic 4542396Sbostic /* init path pointer; built from the end of the buffer */ 4637209Sbostic pp = path + sizeof(path) - 1; 4737209Sbostic *pp = '\0'; 4842396Sbostic 4942396Sbostic /* special case first stat, it's ".", not ".." */ 5042396Sbostic up[0] = '.'; 5142396Sbostic up[1] = '\0'; 5242396Sbostic 5337209Sbostic for (pu = up, first = 1;; first = 0) { 5442396Sbostic /* stat current level */ 5542396Sbostic if (lstat(up, &s)) { 5642396Sbostic file = up; 5742396Sbostic goto err; 5842396Sbostic } 5942396Sbostic 6042396Sbostic /* save current node values */ 6142396Sbostic ino = s.st_ino; 6242396Sbostic dev = s.st_dev; 6342396Sbostic 6442396Sbostic /* check for root */ 6542396Sbostic if (root_dev == dev && root_ino == ino) { 6637209Sbostic *store = '/'; 6740556Skarels (void) strcpy(store + 1, pp); 6840556Skarels return (store); 6910155Ssam } 7042396Sbostic 7137209Sbostic *pu++ = '.'; 7237209Sbostic *pu++ = '.'; 7337209Sbostic *pu = '\0'; 7442396Sbostic 7542396Sbostic /* open and stat parent */ 7642396Sbostic if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) { 7740556Skarels file = up; 7840556Skarels goto err; 7937209Sbostic } 8042396Sbostic found = save_errno = 0; 8142396Sbostic 8237209Sbostic *pu++ = '/'; 8342396Sbostic 8442396Sbostic /* 8542396Sbostic * if it's a mount point you have to stat each element because 8642396Sbostic * the inode number in the directory is for the entry in the 8742396Sbostic * parent directory, not the inode number of the mounted file. 8842396Sbostic */ 8942396Sbostic if (s.st_dev == dev) { 9042396Sbostic while (dp = readdir(dir)) 9142396Sbostic if (dp->d_fileno == ino) 9242396Sbostic goto hit; 9342396Sbostic } else { 9442396Sbostic while (dp = readdir(dir)) { 9542396Sbostic if (ISDOT(dp)) 9642396Sbostic continue; 9742396Sbostic bcopy(dp->d_name, pu, dp->d_namlen + 1); 9842396Sbostic if (lstat(up, &s)) { 9942396Sbostic file = dp->d_name; 10042396Sbostic save_errno = errno; 10142396Sbostic errno = 0; 10242396Sbostic continue; 10342396Sbostic } 10442396Sbostic if (s.st_dev == dev && s.st_ino == ino) { 10542396Sbostic hit: if (!first) 10642396Sbostic *--pp = '/'; 10742396Sbostic pp -= dp->d_namlen; 10842396Sbostic bcopy(dp->d_name, pp, dp->d_namlen); 10942396Sbostic found = 1; 11042396Sbostic break; 11142396Sbostic } 11242396Sbostic } 11342396Sbostic if (errno) { 11442396Sbostic file = up; 11540556Skarels save_errno = errno; 11640556Skarels } 11737209Sbostic } 11842396Sbostic (void) closedir(dir); 11942396Sbostic 12037209Sbostic *pu = '\0'; 12142396Sbostic 12240556Skarels if (!found) { 12340556Skarels /* 12440556Skarels * We didn't find the current level in its parent 12540556Skarels * directory; figure out what to complain about. 12640556Skarels */ 12742396Sbostic if (save_errno) { 12840556Skarels errno = save_errno; 12940556Skarels goto err; 13040556Skarels } 13140556Skarels (void) sprintf(store, "%s not found in %s?\n", 13240556Skarels first ? "." : pp, up); 13340556Skarels return ((char *)NULL); 13440556Skarels } 1359986Ssam } 13640556Skarels err: 13740556Skarels (void) sprintf(store, "getwd: %s: %s", file, strerror(errno)); 13840556Skarels return ((char *)NULL); 1399986Ssam } 140