00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042
00043 #if HAVE_DIRENT_H
00044 # include <dirent.h>
00045 # define NAMLEN(dirent) strlen((dirent)->d_name)
00046 #else
00047 # define dirent direct
00048 # define NAMLEN(dirent) (dirent)->d_namlen
00049 # if HAVE_SYS_NDIR_H
00050 # include <sys/ndir.h>
00051 # endif
00052 # if HAVE_SYS_DIR_H
00053 # include <sys/dir.h>
00054 # endif
00055 # if HAVE_NDIR_H
00056 # include <ndir.h>
00057 # endif
00058 #endif
00059
00060 #include <errno.h>
00061 #include <stdio.h>
00062 #include <stdlib.h>
00063 #include <string.h>
00064 #include <unistd.h>
00065
00066 #ifndef HAVE_GETCWD
00067
00068 #define ISDOT(dp) \
00069 (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
00070 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
00071
00072 #ifndef dirfd
00073 #define dirfd(dirp) ((dirp)->dd_fd)
00074 #endif
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 char *
00085 getcwd(pt, size)
00086 char *pt;
00087 size_t size;
00088 {
00089 register struct dirent *dp;
00090 register DIR *dir;
00091 register dev_t dev;
00092 register ino_t ino;
00093 register int first;
00094 register char *bpt, *bup;
00095 struct stat s;
00096 dev_t root_dev;
00097 ino_t root_ino;
00098 size_t ptsize, upsize;
00099 int ret, save_errno;
00100 char *ept, *eup, *up;
00101
00102
00103
00104
00105
00106
00107 if (pt) {
00108 ptsize = 0;
00109 if (!size) {
00110 __os_set_errno(EINVAL);
00111 return (NULL);
00112 }
00113 if (size == 1) {
00114 __os_set_errno(ERANGE);
00115 return (NULL);
00116 }
00117 ept = pt + size;
00118 } else {
00119 if ((ret = __os_malloc(ptsize = 1024 - 4, NULL, &pt)) != 0) {
00120 __os_set_errno(ret);
00121 return (NULL);
00122 }
00123 ept = pt + ptsize;
00124 }
00125 bpt = ept - 1;
00126 *bpt = '\0';
00127
00128
00129
00130
00131
00132
00133 if ((ret = __os_malloc(upsize = 1024 - 4, NULL, &up)) != 0)
00134 goto err;
00135 eup = up + 1024;
00136 bup = up;
00137 up[0] = '.';
00138 up[1] = '\0';
00139
00140
00141 if (stat("/", &s))
00142 goto err;
00143 root_dev = s.st_dev;
00144 root_ino = s.st_ino;
00145
00146 __os_set_errno(0);
00147
00148 for (first = 1;; first = 0) {
00149
00150 if (lstat(up, &s))
00151 goto err;
00152
00153
00154 ino = s.st_ino;
00155 dev = s.st_dev;
00156
00157
00158 if (root_dev == dev && root_ino == ino) {
00159 *--bpt = PATH_SEPARATOR[0];
00160
00161
00162
00163
00164
00165 bcopy(bpt, pt, ept - bpt);
00166 __os_free(up, upsize);
00167 return (pt);
00168 }
00169
00170
00171
00172
00173
00174
00175 if (bup + 3 + MAXNAMLEN + 1 >= eup) {
00176 if (__os_realloc(upsize *= 2, NULL, &up) != 0)
00177 goto err;
00178 bup = up;
00179 eup = up + upsize;
00180 }
00181 *bup++ = '.';
00182 *bup++ = '.';
00183 *bup = '\0';
00184
00185
00186 if (!(dir = opendir(up)) || fstat(dirfd(dir), &s))
00187 goto err;
00188
00189
00190 *bup++ = PATH_SEPARATOR[0];
00191
00192
00193
00194
00195
00196
00197 save_errno = 0;
00198 if (s.st_dev == dev) {
00199 for (;;) {
00200 if (!(dp = readdir(dir)))
00201 goto notfound;
00202 if (dp->d_fileno == ino)
00203 break;
00204 }
00205 } else
00206 for (;;) {
00207 if (!(dp = readdir(dir)))
00208 goto notfound;
00209 if (ISDOT(dp))
00210 continue;
00211 bcopy(dp->d_name, bup, dp->d_namlen + 1);
00212
00213
00214 if (lstat(up, &s)) {
00215 if (save_errno == 0)
00216 save_errno = __os_get_errno();
00217 __os_set_errno(0);
00218 continue;
00219 }
00220 if (s.st_dev == dev && s.st_ino == ino)
00221 break;
00222 }
00223
00224
00225
00226
00227
00228 if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
00229 size_t len, off;
00230
00231 if (!ptsize) {
00232 __os_set_errno(ERANGE);
00233 goto err;
00234 }
00235 off = bpt - pt;
00236 len = ept - bpt;
00237 if (__os_realloc(ptsize *= 2, NULL, &pt) != 0)
00238 goto err;
00239 bpt = pt + off;
00240 ept = pt + ptsize;
00241 bcopy(bpt, ept - len, len);
00242 bpt = ept - len;
00243 }
00244 if (!first)
00245 *--bpt = PATH_SEPARATOR[0];
00246 bpt -= dp->d_namlen;
00247 bcopy(dp->d_name, bpt, dp->d_namlen);
00248 (void)closedir(dir);
00249
00250
00251 *bup = '\0';
00252 }
00253
00254 notfound:
00255
00256
00257
00258
00259
00260 if (__os_get_errno() == 0)
00261 __os_set_errno(save_errno == 0 ? ENOENT : save_errno);
00262
00263 err:
00264 if (ptsize)
00265 __os_free(pt, ptsize);
00266 __os_free(up, upsize);
00267 return (NULL);
00268 }
00269 #endif