121345Sdist /* 237209Sbostic * Copyright (c) 1989 The Regents of the University of California. 337209Sbostic * All rights reserved. 437209Sbostic * 537209Sbostic * Redistribution and use in source and binary forms are permitted 637209Sbostic * provided that the above copyright notice and this paragraph are 737209Sbostic * duplicated in all such forms and that any documentation, 837209Sbostic * advertising materials, and other materials related to such 937209Sbostic * distribution and use acknowledge that the software was developed 1037209Sbostic * by the University of California, Berkeley. The name of the 1137209Sbostic * University may not be used to endorse or promote products derived 1237209Sbostic * from this software without specific prior written permission. 1337209Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437209Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537209Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621345Sdist */ 179986Ssam 1826565Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*40556Skarels static char sccsid[] = "@(#)getcwd.c 5.6 (Berkeley) 03/20/90"; 2037209Sbostic #endif /* LIBC_SCCS and not lint */ 2121345Sdist 2210088Ssam #include <sys/param.h> 2310088Ssam #include <sys/stat.h> 2437209Sbostic #include <dirent.h> 259986Ssam 269986Ssam char * 2737209Sbostic getwd(store) 2837209Sbostic char *store; 299986Ssam { 3037209Sbostic extern int errno; 3137209Sbostic register DIR *dir; 3237209Sbostic register struct dirent *dp; 3337209Sbostic register int first; 3437209Sbostic register char *pp, *pu; 3537209Sbostic struct stat s, tmp; 3637209Sbostic dev_t root_dev; 3737209Sbostic ino_t root_ino; 38*40556Skarels int save_errno, found; 39*40556Skarels char path[MAXPATHLEN], up[MAXPATHLEN], *file, *strerror(); 409986Ssam 41*40556Skarels if (stat("/", &s)) { 42*40556Skarels file = "/"; 4337209Sbostic goto err; 44*40556Skarels } 4537209Sbostic root_dev = s.st_dev; 4637209Sbostic root_ino = s.st_ino; 47*40556Skarels if (stat(".", &s)) { 48*40556Skarels file = "."; 4937209Sbostic goto err; 50*40556Skarels } 5137209Sbostic pp = path + sizeof(path) - 1; 5237209Sbostic *pp = '\0'; 5337209Sbostic for (pu = up, first = 1;; first = 0) { 5437209Sbostic if (root_dev == s.st_dev && root_ino == s.st_ino) { 5537209Sbostic *store = '/'; 56*40556Skarels (void) strcpy(store + 1, pp); 57*40556Skarels return (store); 5810155Ssam } 5937209Sbostic *pu++ = '.'; 6037209Sbostic *pu++ = '.'; 6137209Sbostic *pu = '\0'; 6237209Sbostic if (!(dir = opendir(up))) { 63*40556Skarels file = up; 64*40556Skarels goto err; 6537209Sbostic } 6637209Sbostic *pu++ = '/'; 67*40556Skarels found = 0; 68*40556Skarels file = NULL; 69*40556Skarels while (errno = 0, dp = readdir(dir)) { 70*40556Skarels if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || 71*40556Skarels dp->d_name[1] == '.' && dp->d_name[2] == '\0')) 7237209Sbostic continue; 7337209Sbostic bcopy(dp->d_name, pu, dp->d_namlen + 1); 74*40556Skarels if (lstat(up, &tmp)) { 75*40556Skarels file = dp->d_name; 76*40556Skarels save_errno = errno; 77*40556Skarels continue; 78*40556Skarels } 7937209Sbostic if (tmp.st_dev == s.st_dev && tmp.st_ino == s.st_ino) { 8037209Sbostic if (!first) 8137209Sbostic *--pp = '/'; 8237209Sbostic pp -= dp->d_namlen; 8337209Sbostic bcopy(dp->d_name, pp, dp->d_namlen); 84*40556Skarels found = 1; 8510155Ssam break; 8610155Ssam } 8737209Sbostic } 88*40556Skarels if (errno) { 89*40556Skarels save_errno = errno; 90*40556Skarels file = up; 91*40556Skarels } 9237209Sbostic closedir(dir); 9337209Sbostic *pu = '\0'; 94*40556Skarels if (!found) { 95*40556Skarels /* 96*40556Skarels * We didn't find the current level in its parent 97*40556Skarels * directory; figure out what to complain about. 98*40556Skarels */ 99*40556Skarels if (file) { 100*40556Skarels errno = save_errno; 101*40556Skarels goto err; 102*40556Skarels } 103*40556Skarels (void) sprintf(store, "%s not found in %s?\n", 104*40556Skarels first ? "." : pp, up); 105*40556Skarels return ((char *)NULL); 106*40556Skarels } 107*40556Skarels 108*40556Skarels /* stat "." at current level, then ascend */ 10937209Sbostic if (lstat(up, &s)) { 110*40556Skarels file = up; 111*40556Skarels goto err; 11237209Sbostic } 1139986Ssam } 114*40556Skarels 115*40556Skarels err: 116*40556Skarels (void) sprintf(store, "getwd: %s: %s", file, strerror(errno)); 117*40556Skarels return ((char *)NULL); 1189986Ssam } 119