1*11370Snicklin /* @(#)getcwd.c 4.8 (Berkeley) 03/02/83 */ 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 CURDIR "." 1210155Ssam #define GETWDERR(s) strcpy(pathname, (s)); 1310155Ssam #define PARENTDIR ".." 1410155Ssam #define PATHSEP "/" 1510155Ssam #define ROOTDIR "/" 169986Ssam 17*11370Snicklin char *strcpy(); 1810155Ssam static int pathsize; /* pathname length */ 1910127Ssam 209986Ssam char * 2110155Ssam getwd(pathname) 2210155Ssam char *pathname; 239986Ssam { 2410156Ssam char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ 2510155Ssam char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ 2610155Ssam char *prepend(); /* prepend dirname to pathname */ 2710155Ssam dev_t rdev; /* root device number */ 2810155Ssam DIR *dirp; /* directory stream */ 2910155Ssam ino_t rino; /* root inode number */ 3010155Ssam struct direct *dir; /* directory entry struct */ 3110155Ssam struct stat d ,dd; /* file status struct */ 329986Ssam 3310155Ssam pathsize = 0; 3410155Ssam *pnptr = '\0'; 3510155Ssam stat(ROOTDIR, &d); 369986Ssam rdev = d.st_dev; 379986Ssam rino = d.st_ino; 389986Ssam for (;;) { 3910155Ssam stat(CURDIR, &d); 4010155Ssam if (d.st_ino == rino && d.st_dev == rdev) 4110155Ssam break; /* reached root directory */ 4210155Ssam if ((dirp = opendir(PARENTDIR)) == NULL) { 4310155Ssam GETWDERR("getwd: can't open .."); 4410155Ssam goto fail; 4510155Ssam } 4610155Ssam if (chdir(PARENTDIR) < 0) { 4710155Ssam GETWDERR("getwd: can't chdir to .."); 4810155Ssam goto fail; 4910155Ssam } 5010155Ssam fstat(dirp->dd_fd, &dd); 5110126Ssam if (d.st_dev == dd.st_dev) { 5210155Ssam if (d.st_ino == dd.st_ino) { 5310155Ssam /* reached root directory */ 5410155Ssam closedir(dirp); 5510155Ssam break; 5610155Ssam } 5710140Ssam do { 5810155Ssam if ((dir = readdir(dirp)) == NULL) { 5910155Ssam closedir(dirp); 6010155Ssam GETWDERR("getwd: read error in .."); 6110155Ssam goto fail; 6210155Ssam } 6310140Ssam } while (dir->d_ino != d.st_ino); 6410126Ssam } else 6510126Ssam do { 6610155Ssam if((dir = readdir(dirp)) == NULL) { 6710155Ssam closedir(dirp); 6810155Ssam GETWDERR("getwd: read error in .."); 6910155Ssam goto fail; 7010155Ssam } 719986Ssam stat(dir->d_name, &dd); 729986Ssam } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev); 7310155Ssam closedir(dirp); 7410155Ssam pnptr = prepend(PATHSEP, prepend(dir->d_name, pnptr)); 759986Ssam } 7610155Ssam if (*pnptr == '\0') /* current dir == root dir */ 7710155Ssam strcpy(pathname, ROOTDIR); 7810155Ssam else { 7910155Ssam strcpy(pathname, pnptr); 8010155Ssam if (chdir(pnptr) < 0) { 8110155Ssam GETWDERR("getwd: can't change back to ."); 8210155Ssam return (NULL); 8310155Ssam } 8410155Ssam } 8510155Ssam return (pathname); 8610155Ssam 8710155Ssam fail: 8810155Ssam chdir(prepend(CURDIR, pnptr)); 8910155Ssam return (NULL); 909986Ssam } 919986Ssam 9210155Ssam /* 9310155Ssam * prepend() tacks a directory name onto the front of a pathname. 9410155Ssam */ 9510155Ssam static char * 9610155Ssam prepend(dirname, pathname) 9710155Ssam register char *dirname; 9810155Ssam register char *pathname; 999986Ssam { 10010155Ssam register int i; /* directory name size counter */ 1019986Ssam 10210155Ssam for (i = 0; *dirname != '\0'; i++, dirname++) 10310155Ssam continue; 10410156Ssam if ((pathsize += i) < MAXPATHLEN) 10510155Ssam while (i-- > 0) 10610155Ssam *--pathname = *--dirname; 10710155Ssam return (pathname); 1089986Ssam } 109