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