1 /* @(#)getcwd.c 4.7 (Berkeley) 01/05/83 */ 2 3 /* 4 * getwd() returns the pathname of the current working directory. On error 5 * an error message is copied to pathname and null pointer is returned. 6 */ 7 #include <sys/param.h> 8 #include <sys/stat.h> 9 #include <sys/dir.h> 10 11 #define CURDIR "." 12 #define GETWDERR(s) strcpy(pathname, (s)); 13 #define PARENTDIR ".." 14 #define PATHSEP "/" 15 #define ROOTDIR "/" 16 17 static int pathsize; /* pathname length */ 18 19 char * 20 getwd(pathname) 21 char *pathname; 22 { 23 char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ 24 char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ 25 char *prepend(); /* prepend dirname to pathname */ 26 dev_t rdev; /* root device number */ 27 DIR *dirp; /* directory stream */ 28 ino_t rino; /* root inode number */ 29 struct direct *dir; /* directory entry struct */ 30 struct stat d ,dd; /* file status struct */ 31 32 pathsize = 0; 33 *pnptr = '\0'; 34 stat(ROOTDIR, &d); 35 rdev = d.st_dev; 36 rino = d.st_ino; 37 for (;;) { 38 stat(CURDIR, &d); 39 if (d.st_ino == rino && d.st_dev == rdev) 40 break; /* reached root directory */ 41 if ((dirp = opendir(PARENTDIR)) == NULL) { 42 GETWDERR("getwd: can't open .."); 43 goto fail; 44 } 45 if (chdir(PARENTDIR) < 0) { 46 GETWDERR("getwd: can't chdir to .."); 47 goto fail; 48 } 49 fstat(dirp->dd_fd, &dd); 50 if (d.st_dev == dd.st_dev) { 51 if (d.st_ino == dd.st_ino) { 52 /* reached root directory */ 53 closedir(dirp); 54 break; 55 } 56 do { 57 if ((dir = readdir(dirp)) == NULL) { 58 closedir(dirp); 59 GETWDERR("getwd: read error in .."); 60 goto fail; 61 } 62 } while (dir->d_ino != d.st_ino); 63 } else 64 do { 65 if((dir = readdir(dirp)) == NULL) { 66 closedir(dirp); 67 GETWDERR("getwd: read error in .."); 68 goto fail; 69 } 70 stat(dir->d_name, &dd); 71 } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev); 72 closedir(dirp); 73 pnptr = prepend(PATHSEP, prepend(dir->d_name, pnptr)); 74 } 75 if (*pnptr == '\0') /* current dir == root dir */ 76 strcpy(pathname, ROOTDIR); 77 else { 78 strcpy(pathname, pnptr); 79 if (chdir(pnptr) < 0) { 80 GETWDERR("getwd: can't change back to ."); 81 return (NULL); 82 } 83 } 84 return (pathname); 85 86 fail: 87 chdir(prepend(CURDIR, pnptr)); 88 return (NULL); 89 } 90 91 /* 92 * prepend() tacks a directory name onto the front of a pathname. 93 */ 94 static char * 95 prepend(dirname, pathname) 96 register char *dirname; 97 register char *pathname; 98 { 99 register int i; /* directory name size counter */ 100 101 for (i = 0; *dirname != '\0'; i++, dirname++) 102 continue; 103 if ((pathsize += i) < MAXPATHLEN) 104 while (i-- > 0) 105 *--pathname = *--dirname; 106 return (pathname); 107 } 108