1*17867Sralph /* @(#)getcwd.c 4.10 (Berkeley) 01/24/85 */ 29986Ssam 39986Ssam /* 410155Ssam * getwd() returns the pathname of the current working directory. On error 510155Ssam * an error message is copied to pathname and null pointer is returned. 69986Ssam */ 710088Ssam #include <sys/param.h> 810088Ssam #include <sys/stat.h> 910088Ssam #include <sys/dir.h> 109986Ssam 1110155Ssam #define GETWDERR(s) strcpy(pathname, (s)); 129986Ssam 1311370Snicklin char *strcpy(); 1410155Ssam static int pathsize; /* pathname length */ 1510127Ssam 169986Ssam char * 1710155Ssam getwd(pathname) 1810155Ssam char *pathname; 199986Ssam { 2010156Ssam char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ 2110155Ssam char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ 22*17867Sralph char curdir[MAXPATHLEN]; /* current directory buffer */ 23*17867Sralph char *dptr = curdir; /* directory pointer */ 2410155Ssam char *prepend(); /* prepend dirname to pathname */ 25*17867Sralph dev_t cdev, rdev; /* current & root device number */ 26*17867Sralph ino_t cino, rino; /* current & root inode number */ 2710155Ssam DIR *dirp; /* directory stream */ 2810155Ssam struct direct *dir; /* directory entry struct */ 29*17867Sralph struct stat d, dd; /* file status struct */ 309986Ssam 3110155Ssam pathsize = 0; 3210155Ssam *pnptr = '\0'; 33*17867Sralph if (stat("/", &d) < 0) { 34*17867Sralph GETWDERR("getwd: can't stat /"); 35*17867Sralph return (NULL); 36*17867Sralph } 379986Ssam rdev = d.st_dev; 389986Ssam rino = d.st_ino; 39*17867Sralph strcpy(dptr, "./"); 40*17867Sralph dptr += 2; 41*17867Sralph if (stat(curdir, &d) < 0) { 42*17867Sralph GETWDERR("getwd: can't stat ."); 43*17867Sralph return (NULL); 44*17867Sralph } 459986Ssam for (;;) { 4610155Ssam if (d.st_ino == rino && d.st_dev == rdev) 4710155Ssam break; /* reached root directory */ 48*17867Sralph cino = d.st_ino; 49*17867Sralph cdev = d.st_dev; 50*17867Sralph strcpy(dptr, "../"); 51*17867Sralph dptr += 3; 52*17867Sralph if ((dirp = opendir(curdir)) == NULL) { 5310155Ssam GETWDERR("getwd: can't open .."); 54*17867Sralph return (NULL); 5510155Ssam } 56*17867Sralph fstat(dirp->dd_fd, &d); 57*17867Sralph if (cdev == d.st_dev) { 58*17867Sralph if (cino == d.st_ino) { 5910155Ssam /* reached root directory */ 6010155Ssam closedir(dirp); 6110155Ssam break; 6210155Ssam } 6310140Ssam do { 6410155Ssam if ((dir = readdir(dirp)) == NULL) { 6510155Ssam closedir(dirp); 6610155Ssam GETWDERR("getwd: read error in .."); 67*17867Sralph return (NULL); 6810155Ssam } 69*17867Sralph } while (dir->d_ino != cino); 7010126Ssam } else 7110126Ssam do { 72*17867Sralph if ((dir = readdir(dirp)) == NULL) { 7310155Ssam closedir(dirp); 7410155Ssam GETWDERR("getwd: read error in .."); 75*17867Sralph return (NULL); 7610155Ssam } 77*17867Sralph strcpy(dptr, dir->d_name); 78*17867Sralph lstat(curdir, &dd); 79*17867Sralph } while(dd.st_ino != cino || dd.st_dev != cdev); 8010155Ssam closedir(dirp); 81*17867Sralph pnptr = prepend("/", prepend(dir->d_name, pnptr)); 829986Ssam } 8310155Ssam if (*pnptr == '\0') /* current dir == root dir */ 84*17867Sralph strcpy(pathname, "/"); 85*17867Sralph else 8610155Ssam strcpy(pathname, pnptr); 8710155Ssam return (pathname); 889986Ssam } 899986Ssam 9010155Ssam /* 9110155Ssam * prepend() tacks a directory name onto the front of a pathname. 9210155Ssam */ 9310155Ssam static char * 9410155Ssam prepend(dirname, pathname) 9510155Ssam register char *dirname; 9610155Ssam register char *pathname; 979986Ssam { 9810155Ssam register int i; /* directory name size counter */ 999986Ssam 10010155Ssam for (i = 0; *dirname != '\0'; i++, dirname++) 10110155Ssam continue; 10210156Ssam if ((pathsize += i) < MAXPATHLEN) 10310155Ssam while (i-- > 0) 10410155Ssam *--pathname = *--dirname; 10510155Ssam return (pathname); 1069986Ssam } 107