1 //========================================================================
5 // Miscellaneous file and directory name manipulation.
7 // Copyright 1996 Derek B. Noonburg
9 //========================================================================
14 #include <kpathsea/win32lib.h>
24 #if defined(VMS) && (__DECCXX_VER < 50200000)
30 // Some systems don't define this, so just make it something reasonably
36 //------------------------------------------------------------------------
38 GString *getHomeDir() {
40 //---------- VMS ----------
41 return new GString("SYS$LOGIN:");
43 #elif defined(__EMX__) || defined(WIN32)
44 //---------- OS/2+EMX and Win32 ----------
48 if ((s = getenv("HOME")))
51 ret = new GString(".");
55 //---------- Unix ----------
60 if ((s = getenv("HOME"))) {
63 if ((s = getenv("USER")))
66 pw = getpwuid(getuid());
68 ret = new GString(pw->pw_dir);
70 ret = new GString(".");
76 GString *getCurrentDir() {
80 if (!_getcwd2(buf, sizeof(buf)))
82 if (!GetCurrentDirectory(sizeof(buf), buf))
84 if (!getcwd(buf, sizeof(buf)))
87 return new GString(buf);
90 GString *appendToPath(GString *path, char *fileName) {
92 //---------- VMS ----------
93 //~ this should handle everything necessary for file
94 //~ requesters, but it's certainly not complete
98 p0 = path->getCString();
99 p1 = p0 + path->getLength() - 1;
100 if (!strcmp(fileName, "-")) {
102 for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
105 path->del(p2 - p0, p1 - p2);
106 } else if (*p1 == ':') {
112 } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
114 path->insert(p1 - p0, '.');
115 path->insert(p1 - p0 + 1, fileName, q1 - fileName);
116 } else if (*p1 == ':') {
119 path->append(fileName, q1 - fileName);
122 path->append(fileName, q1 - fileName);
125 if (*p1 != ']' && *p1 != ':')
127 path->append(fileName);
132 //---------- Win32 ----------
137 tmp = new GString(path);
139 tmp->append(fileName);
140 GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
147 //---------- Unix and OS/2+EMX ----------
150 // appending "." does nothing
151 if (!strcmp(fileName, "."))
154 // appending ".." goes up one directory
155 if (!strcmp(fileName, "..")) {
156 for (i = path->getLength() - 2; i >= 0; --i) {
158 if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
159 path->getChar(i) == ':')
161 if (path->getChar(i) == '/')
167 if (path->getChar[0] == '/' || path->getChar[0] == '\\') {
168 path->del(1, path->getLength() - 1);
169 } else if (path->getLength() >= 2 && path->getChar[1] == ':') {
170 path->del(2, path->getLength() - 2);
176 if (path->getChar(0) == '/') {
177 path->del(1, path->getLength() - 1);
185 if (path->getChar(i) == ':')
188 path->del(i, path->getLength() - i);
193 // otherwise, append "/" and new path component
195 if (path->getLength() > 0 &&
196 path->getChar(path->getLength() - 1) != '/' &&
197 path->getChar(path->getLength() - 1) != '\\')
199 if (path->getLength() > 0 &&
200 path->getChar(path->getLength() - 1) != '/')
203 path->append(fileName);
208 GString *grabPath(char *fileName) {
210 //---------- VMS ----------
213 if ((p = strrchr(fileName, ']')))
214 return new GString(fileName, p + 1 - fileName);
215 if ((p = strrchr(fileName, ':')))
216 return new GString(fileName, p + 1 - fileName);
217 return new GString();
219 #elif defined(__EMX__) || defined(WIN32)
220 //---------- OS/2+EMX and Win32 ----------
223 if ((p = strrchr(fileName, '/')))
224 return new GString(fileName, p - fileName);
225 if ((p = strrchr(fileName, '\\')))
226 return new GString(fileName, p - fileName);
227 if ((p = strrchr(fileName, ':')))
228 return new GString(fileName, p + 1 - fileName);
229 return new GString();
232 //---------- Unix ----------
235 if ((p = strrchr(fileName, '/')))
236 return new GString(fileName, p - fileName);
237 return new GString();
241 GBool isAbsolutePath(char *path) {
243 //---------- VMS ----------
244 return strchr(path, ':') ||
245 (path[0] == '[' && path[1] != '.' && path[1] != '-');
247 #elif defined(__EMX__) || defined(WIN32)
248 //---------- OS/2+EMX and Win32 ----------
249 return path[0] == '/' || path[0] == '\\' || path[1] == ':';
252 //---------- Unix ----------
253 return path[0] == '/';
257 GString *makePathAbsolute(GString *path) {
259 //---------- VMS ----------
260 char buf[PATH_MAX+1];
262 if (!isAbsolutePath(path->getCString())) {
263 if (getcwd(buf, sizeof(buf))) {
264 if (path->getChar(0) == '[') {
265 if (path->getChar(1) != '.')
266 path->insert(0, '.');
267 path->insert(0, buf);
269 path->insert(0, '[');
270 path->insert(1, ']');
271 path->insert(1, buf);
278 //---------- Win32 ----------
283 if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) {
292 //---------- Unix and OS/2+EMX ----------
294 char buf[PATH_MAX+1];
299 if (path->getChar(0) == '~') {
300 if (path->getChar(1) == '/' ||
302 path->getChar(1) == '\\' ||
304 path->getLength() == 1) {
310 p1 = path->getCString() + 1;
312 for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
314 for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
316 if ((n = p2 - p1) > PATH_MAX)
320 if ((pw = getpwnam(buf))) {
321 path->del(0, p2 - p1 + 1);
322 path->insert(0, pw->pw_dir);
325 } else if (!isAbsolutePath(path->getCString())) {
326 if (getcwd(buf, sizeof(buf))) {
327 path->insert(0, '/');
328 path->insert(0, buf);
335 //------------------------------------------------------------------------
336 // GDir and GDirEntry
337 //------------------------------------------------------------------------
339 GDirEntry::GDirEntry(char *dirPath, char *name1, GBool doStat) {
350 name = new GString(name1);
354 if (!strcmp(name1, "-") ||
355 ((p = strrchr(name1, '.')) && !strncmp(p, ".DIR;", 5)))
358 s = new GString(dirPath);
359 appendToPath(s, name1);
361 fa = GetFileAttributes(s->getCString());
362 dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
364 if (stat(s->getCString(), &st) == 0)
365 dir = S_ISDIR(st.st_mode);
372 GDirEntry::~GDirEntry() {
376 GDir::GDir(char *name, GBool doStat1) {
377 path = new GString(name);
384 hnd = FindFirstFile(tmp->getCString(), &ffd);
390 needParent = strchr(name, '[') != NULL;
407 GDirEntry *GDir::getNextEntry() {
413 e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
414 if (hnd && !FindNextFile(hnd, &ffd)) {
422 e = new GDirEntry(path->getCString(), "-", doStat);
429 if (ent && !strcmp(ent->d_name, "."))
433 e = new GDirEntry(path->getCString(), ent->d_name, doStat);
439 void GDir::rewind() {
447 hnd = FindFirstFile(tmp->getCString(), &ffd);
453 needParent = strchr(path->getCString(), '[') != NULL;