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