1 //========================================================================
2 //
3 // gfile.cc
4 //
5 // Miscellaneous file and directory name manipulation.
6 //
7 // Copyright 1996-2003 Glyph & Cog, LLC
8 //
9 //========================================================================
10 // Modified for TeX Live by Peter Breitenlohner <tex-live@tug.org>
11 // See top-level ChangeLog for a list of all modifications
12 //========================================================================
13
14 #include <aconf.h>
15
16 #ifdef _WIN32
17 # include <time.h>
18 # include <direct.h>
19 #else
20 # if defined(MACOS)
21 # include <sys/stat.h>
22 # elif !defined(ACORN)
23 # include <sys/types.h>
24 # include <sys/stat.h>
25 # include <fcntl.h>
26 # endif
27 # include <time.h>
28 # include <limits.h>
29 # include <string.h>
30 # if !defined(VMS) && !defined(ACORN) && !defined(MACOS)
31 # include <pwd.h>
32 # endif
33 # if defined(VMS) && (__DECCXX_VER < 50200000)
34 # include <unixlib.h>
35 # endif
36 #endif // _WIN32
37 #include "GString.h"
38 #include "gfile.h"
39
40 // Some systems don't define this, so just make it something reasonably
41 // large.
42 #ifndef PATH_MAX
43 #define PATH_MAX 1024
44 #endif
45
46 //------------------------------------------------------------------------
47
getHomeDir()48 GString *getHomeDir() {
49 #ifdef VMS
50 //---------- VMS ----------
51 return new GString("SYS$LOGIN:");
52
53 #elif defined(__EMX__) || defined(_WIN32)
54 //---------- OS/2+EMX and Win32 ----------
55 char *s;
56 GString *ret;
57
58 #ifdef _WIN32
59 if ((s = getenv("USERPROFILE")))
60 #else
61 if ((s = getenv("HOME")))
62 #endif
63 ret = new GString(s);
64 else
65 ret = new GString(".");
66 return ret;
67
68 #elif defined(ACORN)
69 //---------- RISCOS ----------
70 return new GString("@");
71
72 #elif defined(MACOS)
73 //---------- MacOS ----------
74 return new GString(":");
75
76 #else
77 //---------- Unix ----------
78 char *s;
79 struct passwd *pw;
80 GString *ret;
81
82 if ((s = getenv("HOME"))) {
83 ret = new GString(s);
84 } else {
85 if ((s = getenv("USER")))
86 pw = getpwnam(s);
87 else
88 pw = getpwuid(getuid());
89 if (pw)
90 ret = new GString(pw->pw_dir);
91 else
92 ret = new GString(".");
93 }
94 return ret;
95 #endif
96 }
97
getCurrentDir()98 GString *getCurrentDir() {
99 char buf[PATH_MAX+1];
100
101 #if defined(__EMX__)
102 if (_getcwd2(buf, sizeof(buf)))
103 #elif defined(_WIN32)
104 if (GetCurrentDirectoryA(sizeof(buf), buf))
105 #elif defined(ACORN)
106 if (strcpy(buf, "@"))
107 #elif defined(MACOS)
108 if (strcpy(buf, ":"))
109 #else
110 if (getcwd(buf, sizeof(buf)))
111 #endif
112 return new GString(buf);
113 return new GString();
114 }
115
appendToPath(GString * path,const char * fileName)116 GString *appendToPath(GString *path, const char *fileName) {
117 #if defined(VMS)
118 //---------- VMS ----------
119 //~ this should handle everything necessary for file
120 //~ requesters, but it's certainly not complete
121 char *p0, *p1, *p2;
122 char *q1;
123
124 p0 = path->getCString();
125 p1 = p0 + path->getLength() - 1;
126 if (!strcmp(fileName, "-")) {
127 if (*p1 == ']') {
128 for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
129 if (*p2 == '[')
130 ++p2;
131 path->del(p2 - p0, p1 - p2);
132 } else if (*p1 == ':') {
133 path->append("[-]");
134 } else {
135 path->clear();
136 path->append("[-]");
137 }
138 } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
139 if (*p1 == ']') {
140 path->insert(p1 - p0, '.');
141 path->insert(p1 - p0 + 1, fileName, q1 - fileName);
142 } else if (*p1 == ':') {
143 path->append('[');
144 path->append(']');
145 path->append(fileName, q1 - fileName);
146 } else {
147 path->clear();
148 path->append(fileName, q1 - fileName);
149 }
150 } else {
151 if (*p1 != ']' && *p1 != ':')
152 path->clear();
153 path->append(fileName);
154 }
155 return path;
156
157 #elif defined(_WIN32)
158 //---------- Win32 ----------
159 GString *tmp;
160 char buf[256];
161 char *fp;
162
163 tmp = new GString(path);
164 tmp->append('/');
165 tmp->append(fileName);
166 GetFullPathNameA(tmp->getCString(), sizeof(buf), buf, &fp);
167 delete tmp;
168 path->clear();
169 path->append(buf);
170 return path;
171
172 #elif defined(ACORN)
173 //---------- RISCOS ----------
174 char *p;
175 int i;
176
177 path->append(".");
178 i = path->getLength();
179 path->append(fileName);
180 for (p = path->getCString() + i; *p; ++p) {
181 if (*p == '/') {
182 *p = '.';
183 } else if (*p == '.') {
184 *p = '/';
185 }
186 }
187 return path;
188
189 #elif defined(MACOS)
190 //---------- MacOS ----------
191 char *p;
192 int i;
193
194 path->append(":");
195 i = path->getLength();
196 path->append(fileName);
197 for (p = path->getCString() + i; *p; ++p) {
198 if (*p == '/') {
199 *p = ':';
200 } else if (*p == '.') {
201 *p = ':';
202 }
203 }
204 return path;
205
206 #elif defined(__EMX__)
207 //---------- OS/2+EMX ----------
208 int i;
209
210 // appending "." does nothing
211 if (!strcmp(fileName, "."))
212 return path;
213
214 // appending ".." goes up one directory
215 if (!strcmp(fileName, "..")) {
216 for (i = path->getLength() - 2; i >= 0; --i) {
217 if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
218 path->getChar(i) == ':')
219 break;
220 }
221 if (i <= 0) {
222 if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
223 path->del(1, path->getLength() - 1);
224 } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
225 path->del(2, path->getLength() - 2);
226 } else {
227 path->clear();
228 path->append("..");
229 }
230 } else {
231 if (path->getChar(i-1) == ':')
232 ++i;
233 path->del(i, path->getLength() - i);
234 }
235 return path;
236 }
237
238 // otherwise, append "/" and new path component
239 if (path->getLength() > 0 &&
240 path->getChar(path->getLength() - 1) != '/' &&
241 path->getChar(path->getLength() - 1) != '\\')
242 path->append('/');
243 path->append(fileName);
244 return path;
245
246 #else
247 //---------- Unix ----------
248 int i;
249
250 // appending "." does nothing
251 if (!strcmp(fileName, "."))
252 return path;
253
254 // appending ".." goes up one directory
255 if (!strcmp(fileName, "..")) {
256 for (i = path->getLength() - 2; i >= 0; --i) {
257 if (path->getChar(i) == '/')
258 break;
259 }
260 if (i <= 0) {
261 if (path->getChar(0) == '/') {
262 path->del(1, path->getLength() - 1);
263 } else {
264 path->clear();
265 path->append("..");
266 }
267 } else {
268 path->del(i, path->getLength() - i);
269 }
270 return path;
271 }
272
273 // otherwise, append "/" and new path component
274 if (path->getLength() > 0 &&
275 path->getChar(path->getLength() - 1) != '/')
276 path->append('/');
277 path->append(fileName);
278 return path;
279 #endif
280 }
281
grabPath(char * fileName)282 GString *grabPath(char *fileName) {
283 #ifdef VMS
284 //---------- VMS ----------
285 char *p;
286
287 if ((p = strrchr(fileName, ']')))
288 return new GString(fileName, p + 1 - fileName);
289 if ((p = strrchr(fileName, ':')))
290 return new GString(fileName, p + 1 - fileName);
291 return new GString();
292
293 #elif defined(__EMX__) || defined(_WIN32)
294 //---------- OS/2+EMX and Win32 ----------
295 char *p;
296
297 if ((p = strrchr(fileName, '/')))
298 return new GString(fileName, (int)(p - fileName));
299 if ((p = strrchr(fileName, '\\')))
300 return new GString(fileName, (int)(p - fileName));
301 if ((p = strrchr(fileName, ':')))
302 return new GString(fileName, (int)(p + 1 - fileName));
303 return new GString();
304
305 #elif defined(ACORN)
306 //---------- RISCOS ----------
307 char *p;
308
309 if ((p = strrchr(fileName, '.')))
310 return new GString(fileName, p - fileName);
311 return new GString();
312
313 #elif defined(MACOS)
314 //---------- MacOS ----------
315 char *p;
316
317 if ((p = strrchr(fileName, ':')))
318 return new GString(fileName, p - fileName);
319 return new GString();
320
321 #else
322 //---------- Unix ----------
323 char *p;
324
325 if ((p = strrchr(fileName, '/')))
326 return new GString(fileName, p - fileName);
327 return new GString();
328 #endif
329 }
330
isAbsolutePath(char * path)331 GBool isAbsolutePath(char *path) {
332 #ifdef VMS
333 //---------- VMS ----------
334 return strchr(path, ':') ||
335 (path[0] == '[' && path[1] != '.' && path[1] != '-');
336
337 #elif defined(__EMX__) || defined(_WIN32)
338 //---------- OS/2+EMX and Win32 ----------
339 return path[0] == '/' || path[0] == '\\' || path[1] == ':';
340
341 #elif defined(ACORN)
342 //---------- RISCOS ----------
343 return path[0] == '$';
344
345 #elif defined(MACOS)
346 //---------- MacOS ----------
347 return path[0] != ':';
348
349 #else
350 //---------- Unix ----------
351 return path[0] == '/';
352 #endif
353 }
354
makePathAbsolute(GString * path)355 GString *makePathAbsolute(GString *path) {
356 #ifdef VMS
357 //---------- VMS ----------
358 char buf[PATH_MAX+1];
359
360 if (!isAbsolutePath(path->getCString())) {
361 if (getcwd(buf, sizeof(buf))) {
362 path->insert(0, buf);
363 }
364 }
365 return path;
366
367 #elif defined(_WIN32)
368 //---------- Win32 ----------
369 char buf[_MAX_PATH];
370 char *fp;
371
372 buf[0] = '\0';
373 if (!GetFullPathNameA(path->getCString(), _MAX_PATH, buf, &fp)) {
374 path->clear();
375 return path;
376 }
377 path->clear();
378 path->append(buf);
379 return path;
380
381 #elif defined(ACORN)
382 //---------- RISCOS ----------
383 path->insert(0, '@');
384 return path;
385
386 #elif defined(MACOS)
387 //---------- MacOS ----------
388 path->del(0, 1);
389 return path;
390
391 #else
392 //---------- Unix and OS/2+EMX ----------
393 struct passwd *pw;
394 char buf[PATH_MAX+1];
395 GString *s;
396 char *p1, *p2;
397 int n;
398
399 if (path->getChar(0) == '~') {
400 if (path->getChar(1) == '/' ||
401 #ifdef __EMX__
402 path->getChar(1) == '\\' ||
403 #endif
404 path->getLength() == 1) {
405 path->del(0, 1);
406 s = getHomeDir();
407 path->insert(0, s);
408 delete s;
409 } else {
410 p1 = path->getCString() + 1;
411 #ifdef __EMX__
412 for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
413 #else
414 for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
415 #endif
416 if ((n = p2 - p1) > PATH_MAX)
417 n = PATH_MAX;
418 strncpy(buf, p1, n);
419 buf[n] = '\0';
420 if ((pw = getpwnam(buf))) {
421 path->del(0, p2 - p1 + 1);
422 path->insert(0, pw->pw_dir);
423 }
424 }
425 } else if (!isAbsolutePath(path->getCString())) {
426 if (getcwd(buf, sizeof(buf))) {
427 #ifndef __EMX__
428 path->insert(0, '/');
429 #endif
430 path->insert(0, buf);
431 }
432 }
433 return path;
434 #endif
435 }
436
getModTime(char * fileName)437 time_t getModTime(char *fileName) {
438 #ifdef _WIN32
439 //~ should implement this, but it's (currently) only used in xpdf
440 return 0;
441 #else
442 struct stat statBuf;
443
444 if (stat(fileName, &statBuf)) {
445 return 0;
446 }
447 return statBuf.st_mtime;
448 #endif
449 }
450
451 #ifndef PDF_PARSER_ONLY
openTempFile(GString ** name,FILE ** f,const char * mode,const char * ext)452 GBool openTempFile(GString **name, FILE **f,
453 const char *mode, const char *ext) {
454 #if defined(_WIN32)
455 //---------- Win32 ----------
456 char *tempDir;
457 GString *s, *s2;
458 FILE *f2;
459 int t, i;
460
461 // this has the standard race condition problem, but I haven't found
462 // a better way to generate temp file names with extensions on
463 // Windows
464 if ((tempDir = getenv("TEMP"))) {
465 s = new GString(tempDir);
466 s->append('\\');
467 } else {
468 s = new GString();
469 }
470 s->appendf("x_{0:d}_{1:d}_",
471 (int)GetCurrentProcessId(), (int)GetCurrentThreadId());
472 t = (int)time(NULL);
473 for (i = 0; i < 1000; ++i) {
474 s2 = s->copy()->appendf("{0:d}", t + i);
475 if (ext) {
476 s2->append(ext);
477 }
478 if (!(f2 = fopen(s2->getCString(), "r"))) {
479 if (!(f2 = fopen(s2->getCString(), mode))) {
480 delete s2;
481 delete s;
482 return gFalse;
483 }
484 *name = s2;
485 *f = f2;
486 delete s;
487 return gTrue;
488 }
489 fclose(f2);
490 delete s2;
491 }
492 delete s;
493 return gFalse;
494 #elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS)
495 //---------- non-Unix ----------
496 char *s;
497
498 // There is a security hole here: an attacker can create a symlink
499 // with this file name after the tmpnam call and before the fopen
500 // call. I will happily accept fixes to this function for non-Unix
501 // OSs.
502 if (!(s = tmpnam(NULL))) {
503 return gFalse;
504 }
505 *name = new GString(s);
506 if (ext) {
507 (*name)->append(ext);
508 }
509 if (!(*f = fopen((*name)->getCString(), mode))) {
510 delete (*name);
511 *name = NULL;
512 return gFalse;
513 }
514 return gTrue;
515 #else
516 //---------- Unix ----------
517 char *s;
518 int fd;
519
520 if (ext) {
521 #if HAVE_MKSTEMPS
522 if ((s = getenv("TMPDIR"))) {
523 *name = new GString(s);
524 } else {
525 *name = new GString("/tmp");
526 }
527 (*name)->append("/XXXXXX")->append(ext);
528 fd = mkstemps((*name)->getCString(), strlen(ext));
529 #else
530 if (!(s = tmpnam(NULL))) {
531 return gFalse;
532 }
533 *name = new GString(s);
534 (*name)->append(ext);
535 fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
536 #endif
537 } else {
538 #if HAVE_MKSTEMP
539 if ((s = getenv("TMPDIR"))) {
540 *name = new GString(s);
541 } else {
542 *name = new GString("/tmp");
543 }
544 (*name)->append("/XXXXXX");
545 fd = mkstemp((*name)->getCString());
546 #else // HAVE_MKSTEMP
547 if (!(s = tmpnam(NULL))) {
548 return gFalse;
549 }
550 *name = new GString(s);
551 fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
552 #endif // HAVE_MKSTEMP
553 }
554 if (fd < 0 || !(*f = fdopen(fd, mode))) {
555 delete *name;
556 *name = NULL;
557 return gFalse;
558 }
559 return gTrue;
560 #endif
561 }
562 #endif
563
createDir(char * path,int mode)564 GBool createDir(char *path, int mode) {
565 #ifdef _WIN32
566 return !_mkdir(path);
567 #else
568 return !mkdir(path, mode);
569 #endif
570 }
571
executeCommand(char * cmd)572 GBool executeCommand(char *cmd) {
573 #ifdef VMS
574 return system(cmd) ? gTrue : gFalse;
575 #else
576 return system(cmd) ? gFalse : gTrue;
577 #endif
578 }
579
580 #ifdef _WIN32
fileNameToUTF8(char * path)581 GString *fileNameToUTF8(char *path) {
582 GString *s;
583 char *p;
584
585 s = new GString();
586 for (p = path; *p; ++p) {
587 if (*p & 0x80) {
588 s->append((char)(0xc0 | ((*p >> 6) & 0x03)));
589 s->append((char)(0x80 | (*p & 0x3f)));
590 } else {
591 s->append(*p);
592 }
593 }
594 return s;
595 }
596
fileNameToUTF8(wchar_t * path)597 GString *fileNameToUTF8(wchar_t *path) {
598 GString *s;
599 wchar_t *p;
600
601 s = new GString();
602 for (p = path; *p; ++p) {
603 if (*p < 0x80) {
604 s->append((char)*p);
605 } else if (*p < 0x800) {
606 s->append((char)(0xc0 | ((*p >> 6) & 0x1f)));
607 s->append((char)(0x80 | (*p & 0x3f)));
608 } else {
609 s->append((char)(0xe0 | ((*p >> 12) & 0x0f)));
610 s->append((char)(0x80 | ((*p >> 6) & 0x3f)));
611 s->append((char)(0x80 | (*p & 0x3f)));
612 }
613 }
614 return s;
615 }
616 #endif
617
openFile(const char * path,const char * mode)618 FILE *openFile(const char *path, const char *mode) {
619 #ifdef _WIN32
620 OSVERSIONINFO version;
621 wchar_t wPath[_MAX_PATH + 1];
622 char nPath[_MAX_PATH + 1];
623 wchar_t wMode[8];
624 const char *p;
625 int i;
626
627 // NB: _wfopen is only available in NT
628 version.dwOSVersionInfoSize = sizeof(version);
629 GetVersionEx(&version);
630 if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
631 for (p = path, i = 0; *p && i < _MAX_PATH; ++i) {
632 if ((p[0] & 0xe0) == 0xc0 &&
633 p[1] && (p[1] & 0xc0) == 0x80) {
634 wPath[i] = (wchar_t)(((p[0] & 0x1f) << 6) |
635 (p[1] & 0x3f));
636 p += 2;
637 } else if ((p[0] & 0xf0) == 0xe0 &&
638 p[1] && (p[1] & 0xc0) == 0x80 &&
639 p[2] && (p[2] & 0xc0) == 0x80) {
640 wPath[i] = (wchar_t)(((p[0] & 0x0f) << 12) |
641 ((p[1] & 0x3f) << 6) |
642 (p[2] & 0x3f));
643 p += 3;
644 } else {
645 wPath[i] = (wchar_t)(p[0] & 0xff);
646 p += 1;
647 }
648 }
649 wPath[i] = (wchar_t)0;
650 for (i = 0; mode[i] && i < sizeof(mode) - 1; ++i) {
651 wMode[i] = (wchar_t)(mode[i] & 0xff);
652 }
653 wMode[i] = (wchar_t)0;
654 return _wfopen(wPath, wMode);
655 } else {
656 for (p = path, i = 0; *p && i < _MAX_PATH; ++i) {
657 if ((p[0] & 0xe0) == 0xc0 &&
658 p[1] && (p[1] & 0xc0) == 0x80) {
659 nPath[i] = (char)(((p[0] & 0x1f) << 6) |
660 (p[1] & 0x3f));
661 p += 2;
662 } else if ((p[0] & 0xf0) == 0xe0 &&
663 p[1] && (p[1] & 0xc0) == 0x80 &&
664 p[2] && (p[2] & 0xc0) == 0x80) {
665 nPath[i] = (char)(((p[1] & 0x3f) << 6) |
666 (p[2] & 0x3f));
667 p += 3;
668 } else {
669 nPath[i] = p[0];
670 p += 1;
671 }
672 }
673 nPath[i] = '\0';
674 return fopen(nPath, mode);
675 }
676 #else
677 return fopen(path, mode);
678 #endif
679 }
680
getLine(char * buf,int size,FILE * f)681 char *getLine(char *buf, int size, FILE *f) {
682 int c, i;
683
684 i = 0;
685 while (i < size - 1) {
686 if ((c = fgetc(f)) == EOF) {
687 break;
688 }
689 buf[i++] = (char)c;
690 if (c == '\x0a') {
691 break;
692 }
693 if (c == '\x0d') {
694 c = fgetc(f);
695 if (c == '\x0a' && i < size - 1) {
696 buf[i++] = (char)c;
697 } else if (c != EOF) {
698 ungetc(c, f);
699 }
700 break;
701 }
702 }
703 buf[i] = '\0';
704 if (i == 0) {
705 return NULL;
706 }
707 return buf;
708 }
709
gfseek(FILE * f,GFileOffset offset,int whence)710 int gfseek(FILE *f, GFileOffset offset, int whence) {
711 #if HAVE_FSEEKO
712 return fseeko(f, offset, whence);
713 #elif HAVE_FSEEK64
714 return fseek64(f, offset, whence);
715 #elif HAVE_FSEEKI64
716 return _fseeki64(f, offset, whence);
717 #else
718 return fseek(f, offset, whence);
719 #endif
720 }
721
gftell(FILE * f)722 GFileOffset gftell(FILE *f) {
723 #if HAVE_FSEEKO
724 return ftello(f);
725 #elif HAVE_FSEEK64
726 return ftell64(f);
727 #elif HAVE_FSEEKI64
728 return _ftelli64(f);
729 #else
730 return ftell(f);
731 #endif
732 }
733
734 //------------------------------------------------------------------------
735 // GDir and GDirEntry
736 //------------------------------------------------------------------------
737
GDirEntry(char * dirPath,char * nameA,GBool doStat)738 GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) {
739 #ifdef VMS
740 char *p;
741 #elif defined(_WIN32)
742 int fa;
743 GString *s;
744 #elif defined(ACORN)
745 #else
746 struct stat st;
747 GString *s;
748 #endif
749
750 name = new GString(nameA);
751 dir = gFalse;
752 if (doStat) {
753 #ifdef VMS
754 if (!strcmp(nameA, "-") ||
755 ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5)))
756 dir = gTrue;
757 #elif defined(ACORN)
758 #else
759 s = new GString(dirPath);
760 appendToPath(s, nameA);
761 #ifdef _WIN32
762 fa = GetFileAttributesA(s->getCString());
763 dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
764 #else
765 if (stat(s->getCString(), &st) == 0)
766 dir = S_ISDIR(st.st_mode);
767 #endif
768 delete s;
769 #endif
770 }
771 }
772
~GDirEntry()773 GDirEntry::~GDirEntry() {
774 delete name;
775 }
776
GDir(char * name,GBool doStatA)777 GDir::GDir(char *name, GBool doStatA) {
778 path = new GString(name);
779 doStat = doStatA;
780 #if defined(_WIN32)
781 GString *tmp;
782
783 tmp = path->copy();
784 tmp->append("/*.*");
785 hnd = FindFirstFileA(tmp->getCString(), &ffd);
786 delete tmp;
787 #elif defined(ACORN)
788 #elif defined(MACOS)
789 #elif defined(ANDROID)
790 #else
791 dir = opendir(name);
792 #ifdef VMS
793 needParent = strchr(name, '[') != NULL;
794 #endif
795 #endif
796 }
797
~GDir()798 GDir::~GDir() {
799 delete path;
800 #if defined(_WIN32)
801 if (hnd) {
802 FindClose(hnd);
803 hnd = NULL;
804 }
805 #elif defined(ACORN)
806 #elif defined(MACOS)
807 #elif defined(ANDROID)
808 #else
809 if (dir)
810 closedir(dir);
811 #endif
812 }
813
getNextEntry()814 GDirEntry *GDir::getNextEntry() {
815 GDirEntry *e;
816
817 #if defined(_WIN32)
818 if (hnd) {
819 e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
820 if (hnd && !FindNextFileA(hnd, &ffd)) {
821 FindClose(hnd);
822 hnd = NULL;
823 }
824 } else {
825 e = NULL;
826 }
827 #elif defined(ACORN)
828 #elif defined(MACOS)
829 #elif defined(ANDROID)
830 #elif defined(VMS)
831 struct dirent *ent;
832 e = NULL;
833 if (dir) {
834 if (needParent) {
835 e = new GDirEntry(path->getCString(), "-", doStat);
836 needParent = gFalse;
837 return e;
838 }
839 ent = readdir(dir);
840 if (ent) {
841 e = new GDirEntry(path->getCString(), ent->d_name, doStat);
842 }
843 }
844 #else
845 struct dirent *ent;
846 e = NULL;
847 if (dir) {
848 ent = (struct dirent *)readdir(dir);
849 if (ent && !strcmp(ent->d_name, ".")) {
850 ent = (struct dirent *)readdir(dir);
851 }
852 if (ent) {
853 e = new GDirEntry(path->getCString(), ent->d_name, doStat);
854 }
855 }
856 #endif
857
858 return e;
859 }
860
rewind()861 void GDir::rewind() {
862 #ifdef _WIN32
863 GString *tmp;
864
865 if (hnd)
866 FindClose(hnd);
867 tmp = path->copy();
868 tmp->append("/*.*");
869 hnd = FindFirstFileA(tmp->getCString(), &ffd);
870 delete tmp;
871 #elif defined(ACORN)
872 #elif defined(MACOS)
873 #elif defined(ANDROID)
874 #else
875 if (dir)
876 rewinddir(dir);
877 #ifdef VMS
878 needParent = strchr(path->getCString(), '[') != NULL;
879 #endif
880 #endif
881 }
882