1 //========================================================================
5 // Miscellaneous file and directory name manipulation.
7 // Copyright 1996 Derek B. Noonburg
9 //========================================================================
13 # include <sys/stat.h>
15 # include <kpathsea/win32lib.h>
19 # include <sys/types.h>
20 # include <sys/stat.h>
24 # if !defined(VMS) && !defined(ACORN)
27 # if defined(VMS) && (__DECCXX_VER < 50200000)
35 // Some systems don't define this, so just make it something reasonably
41 //------------------------------------------------------------------------
43 GString *getHomeDir() {
45 //---------- VMS ----------
46 return new GString("SYS$LOGIN:");
48 #elif defined(__EMX__) || defined(WIN32)
49 //---------- OS/2+EMX and Win32 ----------
53 if ((s = getenv("HOME")))
56 ret = new GString(".");
60 //---------- RISCOS ----------
61 return new GString("@");
64 //---------- Unix ----------
69 if ((s = getenv("HOME"))) {
72 if ((s = getenv("USER")))
75 pw = getpwuid(getuid());
77 ret = new GString(pw->pw_dir);
79 ret = new GString(".");
85 GString *getCurrentDir() {
89 if (_getcwd2(buf, sizeof(buf)))
91 if (GetCurrentDirectory(sizeof(buf), buf))
95 if (getcwd(buf, sizeof(buf)))
97 return new GString(buf);
101 GString *appendToPath(GString *path, char *fileName) {
103 //---------- VMS ----------
104 //~ this should handle everything necessary for file
105 //~ requesters, but it's certainly not complete
109 p0 = path->getCString();
110 p1 = p0 + path->getLength() - 1;
111 if (!strcmp(fileName, "-")) {
113 for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
116 path->del(p2 - p0, p1 - p2);
117 } else if (*p1 == ':') {
123 } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
125 path->insert(p1 - p0, '.');
126 path->insert(p1 - p0 + 1, fileName, q1 - fileName);
127 } else if (*p1 == ':') {
130 path->append(fileName, q1 - fileName);
133 path->append(fileName, q1 - fileName);
136 if (*p1 != ']' && *p1 != ':')
138 path->append(fileName);
143 //---------- Win32 ----------
148 tmp = new GString(path);
150 tmp->append(fileName);
151 GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
158 //---------- RISCOS ----------
163 i = path->getLength();
164 path->append(fileName);
165 for (p = path->getCString() + i; *p; ++p) {
168 } else if (*p == '.') {
174 #elif defined(__EMX__)
175 //---------- OS/2+EMX ----------
178 // appending "." does nothing
179 if (!strcmp(fileName, "."))
182 // appending ".." goes up one directory
183 if (!strcmp(fileName, "..")) {
184 for (i = path->getLength() - 2; i >= 0; --i) {
185 if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
186 path->getChar(i) == ':')
190 if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
191 path->del(1, path->getLength() - 1);
192 } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
193 path->del(2, path->getLength() - 2);
199 if (path->getChar(i-1) == ':')
201 path->del(i, path->getLength() - i);
206 // otherwise, append "/" and new path component
207 if (path->getLength() > 0 &&
208 path->getChar(path->getLength() - 1) != '/' &&
209 path->getChar(path->getLength() - 1) != '\\')
211 path->append(fileName);
215 //---------- Unix ----------
218 // appending "." does nothing
219 if (!strcmp(fileName, "."))
222 // appending ".." goes up one directory
223 if (!strcmp(fileName, "..")) {
224 for (i = path->getLength() - 2; i >= 0; --i) {
225 if (path->getChar(i) == '/')
229 if (path->getChar(0) == '/') {
230 path->del(1, path->getLength() - 1);
236 path->del(i, path->getLength() - i);
241 // otherwise, append "/" and new path component
242 if (path->getLength() > 0 &&
243 path->getChar(path->getLength() - 1) != '/')
245 path->append(fileName);
250 GString *grabPath(char *fileName) {
252 //---------- VMS ----------
255 if ((p = strrchr(fileName, ']')))
256 return new GString(fileName, p + 1 - fileName);
257 if ((p = strrchr(fileName, ':')))
258 return new GString(fileName, p + 1 - fileName);
259 return new GString();
261 #elif defined(__EMX__) || defined(WIN32)
262 //---------- OS/2+EMX and Win32 ----------
265 if ((p = strrchr(fileName, '/')))
266 return new GString(fileName, p - fileName);
267 if ((p = strrchr(fileName, '\\')))
268 return new GString(fileName, p - fileName);
269 if ((p = strrchr(fileName, ':')))
270 return new GString(fileName, p + 1 - fileName);
271 return new GString();
274 //---------- RISCOS ----------
277 if ((p = strrchr(fileName, '.')))
278 return new GString(fileName, p - fileName);
279 return new GString();
282 //---------- Unix ----------
285 if ((p = strrchr(fileName, '/')))
286 return new GString(fileName, p - fileName);
287 return new GString();
291 GBool isAbsolutePath(char *path) {
293 //---------- VMS ----------
294 return strchr(path, ':') ||
295 (path[0] == '[' && path[1] != '.' && path[1] != '-');
297 #elif defined(__EMX__) || defined(WIN32)
298 //---------- OS/2+EMX and Win32 ----------
299 return path[0] == '/' || path[0] == '\\' || path[1] == ':';
302 //---------- RISCOS ----------
303 return path[0] == '$';
306 //---------- Unix ----------
307 return path[0] == '/';
311 GString *makePathAbsolute(GString *path) {
313 //---------- VMS ----------
314 char buf[PATH_MAX+1];
316 if (!isAbsolutePath(path->getCString())) {
317 if (getcwd(buf, sizeof(buf))) {
318 if (path->getChar(0) == '[') {
319 if (path->getChar(1) != '.')
320 path->insert(0, '.');
321 path->insert(0, buf);
323 path->insert(0, '[');
324 path->insert(1, ']');
325 path->insert(1, buf);
332 //---------- Win32 ----------
337 if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) {
346 //---------- RISCOS ----------
347 path->insert(0, '@');
351 //---------- Unix and OS/2+EMX ----------
353 char buf[PATH_MAX+1];
358 if (path->getChar(0) == '~') {
359 if (path->getChar(1) == '/' ||
361 path->getChar(1) == '\\' ||
363 path->getLength() == 1) {
369 p1 = path->getCString() + 1;
371 for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
373 for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
375 if ((n = p2 - p1) > PATH_MAX)
379 if ((pw = getpwnam(buf))) {
380 path->del(0, p2 - p1 + 1);
381 path->insert(0, pw->pw_dir);
384 } else if (!isAbsolutePath(path->getCString())) {
385 if (getcwd(buf, sizeof(buf))) {
387 path->insert(0, '/');
389 path->insert(0, buf);
396 //------------------------------------------------------------------------
397 // GDir and GDirEntry
398 //------------------------------------------------------------------------
400 GDirEntry::GDirEntry(char *dirPath, char *name1, GBool doStat) {
412 name = new GString(name1);
416 if (!strcmp(name1, "-") ||
417 ((p = strrchr(name1, '.')) && !strncmp(p, ".DIR;", 5)))
421 s = new GString(dirPath);
422 appendToPath(s, name1);
424 fa = GetFileAttributes(s->getCString());
425 dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
427 if (stat(s->getCString(), &st) == 0)
428 dir = S_ISDIR(st.st_mode);
435 GDirEntry::~GDirEntry() {
439 GDir::GDir(char *name, GBool doStat1) {
440 path = new GString(name);
447 hnd = FindFirstFile(tmp->getCString(), &ffd);
453 needParent = strchr(name, '[') != NULL;
472 GDirEntry *GDir::getNextEntry() {
478 e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
479 if (hnd && !FindNextFile(hnd, &ffd)) {
488 e = new GDirEntry(path->getCString(), "-", doStat);
495 if (ent && !strcmp(ent->d_name, "."))
499 e = new GDirEntry(path->getCString(), ent->d_name, doStat);
505 void GDir::rewind() {
513 hnd = FindFirstFile(tmp->getCString(), &ffd);
519 needParent = strchr(path->getCString(), '[') != NULL;