|
|
1.1 ! root 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: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #if defined(LIBC_SCCS) && !defined(lint) ! 21: static char sccsid[] = "@(#)getwd.c 5.8 (Berkeley) 6/1/90"; ! 22: #endif /* LIBC_SCCS and not lint */ ! 23: ! 24: #include <sys/param.h> ! 25: #include <sys/stat.h> ! 26: #include <dirent.h> ! 27: #include <string.h> ! 28: ! 29: #define ISDOT(dp) \ ! 30: (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \ ! 31: dp->d_name[1] == '.' && dp->d_name[2] == '\0')) ! 32: ! 33: char * ! 34: getwd(store) ! 35: char *store; ! 36: { ! 37: extern int errno; ! 38: register struct dirent *dp; ! 39: register DIR *dir; ! 40: register ino_t ino; ! 41: register char *pp, *pu; ! 42: register int first; ! 43: struct stat s; ! 44: dev_t root_dev, dev; ! 45: ino_t root_ino; ! 46: int save_errno, found; ! 47: char path[MAXPATHLEN], up[MAXPATHLEN], *file; ! 48: ! 49: /* save root values */ ! 50: if (stat("/", &s)) { ! 51: file = "/"; ! 52: goto err; ! 53: } ! 54: root_dev = s.st_dev; ! 55: root_ino = s.st_ino; ! 56: ! 57: /* init path pointer; built from the end of the buffer */ ! 58: pp = path + sizeof(path) - 1; ! 59: *pp = '\0'; ! 60: ! 61: /* special case first stat, it's ".", not ".." */ ! 62: up[0] = '.'; ! 63: up[1] = '\0'; ! 64: ! 65: for (pu = up, first = 1;; first = 0) { ! 66: /* stat current level */ ! 67: if (lstat(up, &s)) { ! 68: file = up; ! 69: goto err; ! 70: } ! 71: ! 72: /* save current node values */ ! 73: ino = s.st_ino; ! 74: dev = s.st_dev; ! 75: ! 76: /* check for root */ ! 77: if (root_dev == dev && root_ino == ino) { ! 78: *store = '/'; ! 79: (void) strcpy(store + 1, pp); ! 80: return (store); ! 81: } ! 82: ! 83: *pu++ = '.'; ! 84: *pu++ = '.'; ! 85: *pu = '\0'; ! 86: ! 87: /* open and stat parent */ ! 88: if (!(dir = opendir(up)) || fstat(dirfd(dir), &s)) { ! 89: file = up; ! 90: goto err; ! 91: } ! 92: found = save_errno = 0; ! 93: ! 94: *pu++ = '/'; ! 95: ! 96: /* ! 97: * if it's a mount point you have to stat each element because ! 98: * the inode number in the directory is for the entry in the ! 99: * parent directory, not the inode number of the mounted file. ! 100: */ ! 101: if (s.st_dev == dev) { ! 102: while (dp = readdir(dir)) ! 103: if (dp->d_fileno == ino) ! 104: goto hit; ! 105: } else { ! 106: while (dp = readdir(dir)) { ! 107: if (ISDOT(dp)) ! 108: continue; ! 109: bcopy(dp->d_name, pu, dp->d_namlen + 1); ! 110: if (lstat(up, &s)) { ! 111: file = dp->d_name; ! 112: save_errno = errno; ! 113: errno = 0; ! 114: continue; ! 115: } ! 116: if (s.st_dev == dev && s.st_ino == ino) { ! 117: hit: if (!first) ! 118: *--pp = '/'; ! 119: pp -= dp->d_namlen; ! 120: bcopy(dp->d_name, pp, dp->d_namlen); ! 121: found = 1; ! 122: break; ! 123: } ! 124: } ! 125: if (errno) { ! 126: file = up; ! 127: save_errno = errno; ! 128: } ! 129: } ! 130: (void) closedir(dir); ! 131: ! 132: *pu = '\0'; ! 133: ! 134: if (!found) { ! 135: /* ! 136: * We didn't find the current level in its parent ! 137: * directory; figure out what to complain about. ! 138: */ ! 139: if (save_errno) { ! 140: errno = save_errno; ! 141: goto err; ! 142: } ! 143: (void) sprintf(store, "%s not found in %s?\n", ! 144: first ? "." : pp, up); ! 145: return ((char *)NULL); ! 146: } ! 147: } ! 148: err: ! 149: (void) sprintf(store, "getwd: %s: %s", file, strerror(errno)); ! 150: return ((char *)NULL); ! 151: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.