1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)getcwd.c 5.6 (Berkeley) 03/20/90"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/param.h> 23 #include <sys/stat.h> 24 #include <dirent.h> 25 26 char * 27 getwd(store) 28 char *store; 29 { 30 extern int errno; 31 register DIR *dir; 32 register struct dirent *dp; 33 register int first; 34 register char *pp, *pu; 35 struct stat s, tmp; 36 dev_t root_dev; 37 ino_t root_ino; 38 int save_errno, found; 39 char path[MAXPATHLEN], up[MAXPATHLEN], *file, *strerror(); 40 41 if (stat("/", &s)) { 42 file = "/"; 43 goto err; 44 } 45 root_dev = s.st_dev; 46 root_ino = s.st_ino; 47 if (stat(".", &s)) { 48 file = "."; 49 goto err; 50 } 51 pp = path + sizeof(path) - 1; 52 *pp = '\0'; 53 for (pu = up, first = 1;; first = 0) { 54 if (root_dev == s.st_dev && root_ino == s.st_ino) { 55 *store = '/'; 56 (void) strcpy(store + 1, pp); 57 return (store); 58 } 59 *pu++ = '.'; 60 *pu++ = '.'; 61 *pu = '\0'; 62 if (!(dir = opendir(up))) { 63 file = up; 64 goto err; 65 } 66 *pu++ = '/'; 67 found = 0; 68 file = NULL; 69 while (errno = 0, dp = readdir(dir)) { 70 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || 71 dp->d_name[1] == '.' && dp->d_name[2] == '\0')) 72 continue; 73 bcopy(dp->d_name, pu, dp->d_namlen + 1); 74 if (lstat(up, &tmp)) { 75 file = dp->d_name; 76 save_errno = errno; 77 continue; 78 } 79 if (tmp.st_dev == s.st_dev && tmp.st_ino == s.st_ino) { 80 if (!first) 81 *--pp = '/'; 82 pp -= dp->d_namlen; 83 bcopy(dp->d_name, pp, dp->d_namlen); 84 found = 1; 85 break; 86 } 87 } 88 if (errno) { 89 save_errno = errno; 90 file = up; 91 } 92 closedir(dir); 93 *pu = '\0'; 94 if (!found) { 95 /* 96 * We didn't find the current level in its parent 97 * directory; figure out what to complain about. 98 */ 99 if (file) { 100 errno = save_errno; 101 goto err; 102 } 103 (void) sprintf(store, "%s not found in %s?\n", 104 first ? "." : pp, up); 105 return ((char *)NULL); 106 } 107 108 /* stat "." at current level, then ascend */ 109 if (lstat(up, &s)) { 110 file = up; 111 goto err; 112 } 113 } 114 115 err: 116 (void) sprintf(store, "getwd: %s: %s", file, strerror(errno)); 117 return ((char *)NULL); 118 } 119