1*10156Ssam /* @(#)getcwd.c 4.7 (Berkeley) 01/05/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 1710155Ssam static int pathsize; /* pathname length */ 1810127Ssam 199986Ssam char * 2010155Ssam getwd(pathname) 2110155Ssam char *pathname; 229986Ssam { 23*10156Ssam char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ 2410155Ssam char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ 2510155Ssam char *prepend(); /* prepend dirname to pathname */ 2610155Ssam dev_t rdev; /* root device number */ 2710155Ssam DIR *dirp; /* directory stream */ 2810155Ssam ino_t rino; /* root inode number */ 2910155Ssam struct direct *dir; /* directory entry struct */ 3010155Ssam struct stat d ,dd; /* file status struct */ 319986Ssam 3210155Ssam pathsize = 0; 3310155Ssam *pnptr = '\0'; 3410155Ssam stat(ROOTDIR, &d); 359986Ssam rdev = d.st_dev; 369986Ssam rino = d.st_ino; 379986Ssam for (;;) { 3810155Ssam stat(CURDIR, &d); 3910155Ssam if (d.st_ino == rino && d.st_dev == rdev) 4010155Ssam break; /* reached root directory */ 4110155Ssam if ((dirp = opendir(PARENTDIR)) == NULL) { 4210155Ssam GETWDERR("getwd: can't open .."); 4310155Ssam goto fail; 4410155Ssam } 4510155Ssam if (chdir(PARENTDIR) < 0) { 4610155Ssam GETWDERR("getwd: can't chdir to .."); 4710155Ssam goto fail; 4810155Ssam } 4910155Ssam fstat(dirp->dd_fd, &dd); 5010126Ssam if (d.st_dev == dd.st_dev) { 5110155Ssam if (d.st_ino == dd.st_ino) { 5210155Ssam /* reached root directory */ 5310155Ssam closedir(dirp); 5410155Ssam break; 5510155Ssam } 5610140Ssam do { 5710155Ssam if ((dir = readdir(dirp)) == NULL) { 5810155Ssam closedir(dirp); 5910155Ssam GETWDERR("getwd: read error in .."); 6010155Ssam goto fail; 6110155Ssam } 6210140Ssam } while (dir->d_ino != d.st_ino); 6310126Ssam } else 6410126Ssam do { 6510155Ssam if((dir = readdir(dirp)) == NULL) { 6610155Ssam closedir(dirp); 6710155Ssam GETWDERR("getwd: read error in .."); 6810155Ssam goto fail; 6910155Ssam } 709986Ssam stat(dir->d_name, &dd); 719986Ssam } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev); 7210155Ssam closedir(dirp); 7310155Ssam pnptr = prepend(PATHSEP, prepend(dir->d_name, pnptr)); 749986Ssam } 7510155Ssam if (*pnptr == '\0') /* current dir == root dir */ 7610155Ssam strcpy(pathname, ROOTDIR); 7710155Ssam else { 7810155Ssam strcpy(pathname, pnptr); 7910155Ssam if (chdir(pnptr) < 0) { 8010155Ssam GETWDERR("getwd: can't change back to ."); 8110155Ssam return (NULL); 8210155Ssam } 8310155Ssam } 8410155Ssam return (pathname); 8510155Ssam 8610155Ssam fail: 8710155Ssam chdir(prepend(CURDIR, pnptr)); 8810155Ssam return (NULL); 899986Ssam } 909986Ssam 9110155Ssam /* 9210155Ssam * prepend() tacks a directory name onto the front of a pathname. 9310155Ssam */ 9410155Ssam static char * 9510155Ssam prepend(dirname, pathname) 9610155Ssam register char *dirname; 9710155Ssam register char *pathname; 989986Ssam { 9910155Ssam register int i; /* directory name size counter */ 1009986Ssam 10110155Ssam for (i = 0; *dirname != '\0'; i++, dirname++) 10210155Ssam continue; 103*10156Ssam if ((pathsize += i) < MAXPATHLEN) 10410155Ssam while (i-- > 0) 10510155Ssam *--pathname = *--dirname; 10610155Ssam return (pathname); 1079986Ssam } 108