Commit | Line | Data |
---|---|---|
bb0cfa24 DF |
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 | ||
2ce81398 | 7 | #if defined(LIBC_SCCS) && !defined(lint) |
2293f07e | 8 | static char sccsid[] = "@(#)getcwd.c 5.3 (Berkeley) %G%"; |
2ce81398 | 9 | #endif LIBC_SCCS and not lint |
9b6e6036 SL |
10 | |
11 | /* | |
90432f68 SL |
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. | |
9b6e6036 | 14 | */ |
87dccba9 SL |
15 | #include <sys/param.h> |
16 | #include <sys/stat.h> | |
17 | #include <sys/dir.h> | |
9b6e6036 | 18 | |
90432f68 | 19 | #define GETWDERR(s) strcpy(pathname, (s)); |
9b6e6036 | 20 | |
e8b0aeda | 21 | char *strcpy(); |
90432f68 | 22 | static int pathsize; /* pathname length */ |
9b6e6036 SL |
23 | |
24 | char * | |
90432f68 SL |
25 | getwd(pathname) |
26 | char *pathname; | |
9b6e6036 | 27 | { |
34b028a5 | 28 | char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */ |
90432f68 | 29 | char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */ |
762ac285 RC |
30 | char curdir[MAXPATHLEN]; /* current directory buffer */ |
31 | char *dptr = curdir; /* directory pointer */ | |
90432f68 | 32 | char *prepend(); /* prepend dirname to pathname */ |
762ac285 RC |
33 | dev_t cdev, rdev; /* current & root device number */ |
34 | ino_t cino, rino; /* current & root inode number */ | |
90432f68 | 35 | DIR *dirp; /* directory stream */ |
90432f68 | 36 | struct direct *dir; /* directory entry struct */ |
762ac285 | 37 | struct stat d, dd; /* file status struct */ |
9b6e6036 | 38 | |
90432f68 SL |
39 | pathsize = 0; |
40 | *pnptr = '\0'; | |
762ac285 RC |
41 | if (stat("/", &d) < 0) { |
42 | GETWDERR("getwd: can't stat /"); | |
43 | return (NULL); | |
44 | } | |
9b6e6036 SL |
45 | rdev = d.st_dev; |
46 | rino = d.st_ino; | |
762ac285 RC |
47 | strcpy(dptr, "./"); |
48 | dptr += 2; | |
49 | if (stat(curdir, &d) < 0) { | |
50 | GETWDERR("getwd: can't stat ."); | |
51 | return (NULL); | |
52 | } | |
9b6e6036 | 53 | for (;;) { |
90432f68 SL |
54 | if (d.st_ino == rino && d.st_dev == rdev) |
55 | break; /* reached root directory */ | |
762ac285 RC |
56 | cino = d.st_ino; |
57 | cdev = d.st_dev; | |
58 | strcpy(dptr, "../"); | |
59 | dptr += 3; | |
60 | if ((dirp = opendir(curdir)) == NULL) { | |
90432f68 | 61 | GETWDERR("getwd: can't open .."); |
762ac285 | 62 | return (NULL); |
90432f68 | 63 | } |
762ac285 RC |
64 | fstat(dirp->dd_fd, &d); |
65 | if (cdev == d.st_dev) { | |
66 | if (cino == d.st_ino) { | |
90432f68 SL |
67 | /* reached root directory */ |
68 | closedir(dirp); | |
69 | break; | |
70 | } | |
07fbd99b | 71 | do { |
90432f68 SL |
72 | if ((dir = readdir(dirp)) == NULL) { |
73 | closedir(dirp); | |
74 | GETWDERR("getwd: read error in .."); | |
762ac285 | 75 | return (NULL); |
90432f68 | 76 | } |
762ac285 | 77 | } while (dir->d_ino != cino); |
829e7c26 SL |
78 | } else |
79 | do { | |
762ac285 | 80 | if ((dir = readdir(dirp)) == NULL) { |
90432f68 SL |
81 | closedir(dirp); |
82 | GETWDERR("getwd: read error in .."); | |
762ac285 | 83 | return (NULL); |
90432f68 | 84 | } |
762ac285 RC |
85 | strcpy(dptr, dir->d_name); |
86 | lstat(curdir, &dd); | |
87 | } while(dd.st_ino != cino || dd.st_dev != cdev); | |
762ac285 | 88 | pnptr = prepend("/", prepend(dir->d_name, pnptr)); |
2293f07e | 89 | closedir(dirp); |
90432f68 SL |
90 | } |
91 | if (*pnptr == '\0') /* current dir == root dir */ | |
762ac285 RC |
92 | strcpy(pathname, "/"); |
93 | else | |
90432f68 | 94 | strcpy(pathname, pnptr); |
90432f68 | 95 | return (pathname); |
9b6e6036 SL |
96 | } |
97 | ||
90432f68 SL |
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; | |
9b6e6036 | 105 | { |
90432f68 | 106 | register int i; /* directory name size counter */ |
9b6e6036 | 107 | |
90432f68 SL |
108 | for (i = 0; *dirname != '\0'; i++, dirname++) |
109 | continue; | |
34b028a5 | 110 | if ((pathsize += i) < MAXPATHLEN) |
90432f68 SL |
111 | while (i-- > 0) |
112 | *--pathname = *--dirname; | |
113 | return (pathname); | |
9b6e6036 | 114 | } |