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