1*10155Ssam /* @(#)getcwd.c 4.6 (Berkeley) 01/05/83 */ 29986Ssam 39986Ssam /* 4*10155Ssam * getwd() returns the pathname of the current working directory. On error 5*10155Ssam * 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 11*10155Ssam #define CURDIR "." 12*10155Ssam #define GETWDERR(s) strcpy(pathname, (s)); 13*10155Ssam #define PARENTDIR ".." 14*10155Ssam #define PATHSEP "/" 15*10155Ssam #define PATHSIZE 1024 16*10155Ssam #define ROOTDIR "/" 179986Ssam 18*10155Ssam static int pathsize; /* pathname length */ 1910127Ssam 209986Ssam char * 21*10155Ssam getwd(pathname) 22*10155Ssam char *pathname; 239986Ssam { 24*10155Ssam char pathbuf[PATHSIZE]; /* temporary pathname buffer */ 25*10155Ssam char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ 26*10155Ssam char *prepend(); /* prepend dirname to pathname */ 27*10155Ssam dev_t rdev; /* root device number */ 28*10155Ssam DIR *dirp; /* directory stream */ 29*10155Ssam ino_t rino; /* root inode number */ 30*10155Ssam struct direct *dir; /* directory entry struct */ 31*10155Ssam struct stat d ,dd; /* file status struct */ 329986Ssam 33*10155Ssam pathsize = 0; 34*10155Ssam *pnptr = '\0'; 35*10155Ssam stat(ROOTDIR, &d); 369986Ssam rdev = d.st_dev; 379986Ssam rino = d.st_ino; 389986Ssam for (;;) { 39*10155Ssam stat(CURDIR, &d); 40*10155Ssam if (d.st_ino == rino && d.st_dev == rdev) 41*10155Ssam break; /* reached root directory */ 42*10155Ssam if ((dirp = opendir(PARENTDIR)) == NULL) { 43*10155Ssam GETWDERR("getwd: can't open .."); 44*10155Ssam goto fail; 45*10155Ssam } 46*10155Ssam if (chdir(PARENTDIR) < 0) { 47*10155Ssam GETWDERR("getwd: can't chdir to .."); 48*10155Ssam goto fail; 49*10155Ssam } 50*10155Ssam fstat(dirp->dd_fd, &dd); 5110126Ssam if (d.st_dev == dd.st_dev) { 52*10155Ssam if (d.st_ino == dd.st_ino) { 53*10155Ssam /* reached root directory */ 54*10155Ssam closedir(dirp); 55*10155Ssam break; 56*10155Ssam } 5710140Ssam do { 58*10155Ssam if ((dir = readdir(dirp)) == NULL) { 59*10155Ssam closedir(dirp); 60*10155Ssam GETWDERR("getwd: read error in .."); 61*10155Ssam goto fail; 62*10155Ssam } 6310140Ssam } while (dir->d_ino != d.st_ino); 6410126Ssam } else 6510126Ssam do { 66*10155Ssam if((dir = readdir(dirp)) == NULL) { 67*10155Ssam closedir(dirp); 68*10155Ssam GETWDERR("getwd: read error in .."); 69*10155Ssam goto fail; 70*10155Ssam } 719986Ssam stat(dir->d_name, &dd); 729986Ssam } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev); 73*10155Ssam closedir(dirp); 74*10155Ssam pnptr = prepend(PATHSEP, prepend(dir->d_name, pnptr)); 759986Ssam } 76*10155Ssam if (*pnptr == '\0') /* current dir == root dir */ 77*10155Ssam strcpy(pathname, ROOTDIR); 78*10155Ssam else { 79*10155Ssam strcpy(pathname, pnptr); 80*10155Ssam if (chdir(pnptr) < 0) { 81*10155Ssam GETWDERR("getwd: can't change back to ."); 82*10155Ssam return (NULL); 83*10155Ssam } 84*10155Ssam } 85*10155Ssam return (pathname); 86*10155Ssam 87*10155Ssam fail: 88*10155Ssam chdir(prepend(CURDIR, pnptr)); 89*10155Ssam return (NULL); 909986Ssam } 919986Ssam 92*10155Ssam /* 93*10155Ssam * prepend() tacks a directory name onto the front of a pathname. 94*10155Ssam */ 95*10155Ssam static char * 96*10155Ssam prepend(dirname, pathname) 97*10155Ssam register char *dirname; 98*10155Ssam register char *pathname; 999986Ssam { 100*10155Ssam register int i; /* directory name size counter */ 1019986Ssam 102*10155Ssam for (i = 0; *dirname != '\0'; i++, dirname++) 103*10155Ssam continue; 104*10155Ssam if ((pathsize += i) < PATHSIZE) 105*10155Ssam while (i-- > 0) 106*10155Ssam *--pathname = *--dirname; 107*10155Ssam return (pathname); 1089986Ssam } 109