]> www.fi.muni.cz Git - evince.git/blob - pdf/goo/gfile.cc
Completely synched with Xpdf 0.90
[evince.git] / pdf / goo / gfile.cc
1 //========================================================================
2 //
3 // gfile.cc
4 //
5 // Miscellaneous file and directory name manipulation.
6 //
7 // Copyright 1996 Derek B. Noonburg
8 //
9 //========================================================================
10
11 extern "C" {
12 #ifdef WIN32
13 #  include <sys/stat.h>
14 #  ifndef _MSC_VER
15 #    include <kpathsea/win32lib.h>
16 #  endif
17 #else // !WIN32
18 #  ifndef ACORN
19 #    include <sys/types.h>
20 #    include <sys/stat.h>
21 #  endif
22 #  include <limits.h>
23 #  include <string.h>
24 #  if !defined(VMS) && !defined(ACORN)
25 #    include <pwd.h>
26 #  endif
27 #  if defined(VMS) && (__DECCXX_VER < 50200000)
28 #    include <unixlib.h>
29 #  endif
30 #endif // WIN32
31 }
32 #include "GString.h"
33 #include "gfile.h"
34
35 // Some systems don't define this, so just make it something reasonably
36 // large.
37 #ifndef PATH_MAX
38 #define PATH_MAX 1024
39 #endif
40
41 //------------------------------------------------------------------------
42
43 GString *getHomeDir() {
44 #ifdef VMS
45   //---------- VMS ----------
46   return new GString("SYS$LOGIN:");
47
48 #elif defined(__EMX__) || defined(WIN32)
49   //---------- OS/2+EMX and Win32 ----------
50   char *s;
51   GString *ret;
52
53   if ((s = getenv("HOME")))
54     ret = new GString(s);
55   else
56     ret = new GString(".");
57   return ret;
58
59 #elif defined(ACORN)
60   //---------- RISCOS ----------
61   return new GString("@");
62
63 #else
64   //---------- Unix ----------
65   char *s;
66   struct passwd *pw;
67   GString *ret;
68
69   if ((s = getenv("HOME"))) {
70     ret = new GString(s);
71   } else {
72     if ((s = getenv("USER")))
73       pw = getpwnam(s);
74     else
75       pw = getpwuid(getuid());
76     if (pw)
77       ret = new GString(pw->pw_dir);
78     else
79       ret = new GString(".");
80   }
81   return ret;
82 #endif
83 }
84
85 GString *getCurrentDir() {
86   char buf[PATH_MAX+1];
87
88 #if defined(__EMX__)
89   if (_getcwd2(buf, sizeof(buf)))
90 #elif defined(WIN32)
91   if (GetCurrentDirectory(sizeof(buf), buf))
92 #elif defined(ACORN)
93   if (strcpy(buf, "@"))
94 #else
95   if (getcwd(buf, sizeof(buf)))
96 #endif
97     return new GString(buf);
98   return new GString();
99 }
100
101 GString *appendToPath(GString *path, char *fileName) {
102 #if defined(VMS)
103   //---------- VMS ----------
104   //~ this should handle everything necessary for file
105   //~ requesters, but it's certainly not complete
106   char *p0, *p1, *p2;
107   char *q1;
108
109   p0 = path->getCString();
110   p1 = p0 + path->getLength() - 1;
111   if (!strcmp(fileName, "-")) {
112     if (*p1 == ']') {
113       for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
114       if (*p2 == '[')
115         ++p2;
116       path->del(p2 - p0, p1 - p2);
117     } else if (*p1 == ':') {
118       path->append("[-]");
119     } else {
120       path->clear();
121       path->append("[-]");
122     }
123   } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
124     if (*p1 == ']') {
125       path->insert(p1 - p0, '.');
126       path->insert(p1 - p0 + 1, fileName, q1 - fileName);
127     } else if (*p1 == ':') {
128       path->append('[');
129       path->append(']');
130       path->append(fileName, q1 - fileName);
131     } else {
132       path->clear();
133       path->append(fileName, q1 - fileName);
134     }
135   } else {
136     if (*p1 != ']' && *p1 != ':')
137       path->clear();
138     path->append(fileName);
139   }
140   return path;
141
142 #elif defined(WIN32)
143   //---------- Win32 ----------
144   GString *tmp;
145   char buf[256];
146   char *fp;
147
148   tmp = new GString(path);
149   tmp->append('/');
150   tmp->append(fileName);
151   GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
152   delete tmp;
153   path->clear();
154   path->append(buf);
155   return path;
156
157 #elif defined(ACORN)
158   //---------- RISCOS ----------
159   char *p;
160   int i;
161
162   path->append(".");
163   i = path->getLength();
164   path->append(fileName);
165   for (p = path->getCString() + i; *p; ++p) {
166     if (*p == '/') {
167       *p = '.';
168     } else if (*p == '.') {
169       *p = '/';
170     }
171   }
172   return path;
173
174 #elif defined(__EMX__)
175   //---------- OS/2+EMX ----------
176   int i;
177
178   // appending "." does nothing
179   if (!strcmp(fileName, "."))
180     return path;
181
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) == ':')
187         break;
188     }
189     if (i <= 0) {
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);
194       } else {
195         path->clear();
196         path->append("..");
197       }
198     } else {
199       if (path->getChar(i-1) == ':')
200         ++i;
201       path->del(i, path->getLength() - i);
202     }
203     return path;
204   }
205
206   // otherwise, append "/" and new path component
207   if (path->getLength() > 0 &&
208       path->getChar(path->getLength() - 1) != '/' &&
209       path->getChar(path->getLength() - 1) != '\\')
210     path->append('/');
211   path->append(fileName);
212   return path;
213
214 #else
215   //---------- Unix ----------
216   int i;
217
218   // appending "." does nothing
219   if (!strcmp(fileName, "."))
220     return path;
221
222   // appending ".." goes up one directory
223   if (!strcmp(fileName, "..")) {
224     for (i = path->getLength() - 2; i >= 0; --i) {
225       if (path->getChar(i) == '/')
226         break;
227     }
228     if (i <= 0) {
229       if (path->getChar(0) == '/') {
230         path->del(1, path->getLength() - 1);
231       } else {
232         path->clear();
233         path->append("..");
234       }
235     } else {
236       path->del(i, path->getLength() - i);
237     }
238     return path;
239   }
240
241   // otherwise, append "/" and new path component
242   if (path->getLength() > 0 &&
243       path->getChar(path->getLength() - 1) != '/')
244     path->append('/');
245   path->append(fileName);
246   return path;
247 #endif
248 }
249
250 GString *grabPath(char *fileName) {
251 #ifdef VMS
252   //---------- VMS ----------
253   char *p;
254
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();
260
261 #elif defined(__EMX__) || defined(WIN32)
262   //---------- OS/2+EMX and Win32 ----------
263   char *p;
264
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();
272
273 #elif defined(ACORN)
274   //---------- RISCOS ----------
275   char *p;
276
277   if ((p = strrchr(fileName, '.')))
278     return new GString(fileName, p - fileName);
279   return new GString();
280
281 #else
282   //---------- Unix ----------
283   char *p;
284
285   if ((p = strrchr(fileName, '/')))
286     return new GString(fileName, p - fileName);
287   return new GString();
288 #endif
289 }
290
291 GBool isAbsolutePath(char *path) {
292 #ifdef VMS
293   //---------- VMS ----------
294   return strchr(path, ':') ||
295          (path[0] == '[' && path[1] != '.' && path[1] != '-');
296
297 #elif defined(__EMX__) || defined(WIN32)
298   //---------- OS/2+EMX and Win32 ----------
299   return path[0] == '/' || path[0] == '\\' || path[1] == ':';
300
301 #elif defined(ACORN)
302   //---------- RISCOS ----------
303   return path[0] == '$';
304
305 #else
306   //---------- Unix ----------
307   return path[0] == '/';
308 #endif
309 }
310
311 GString *makePathAbsolute(GString *path) {
312 #ifdef VMS
313   //---------- VMS ----------
314   char buf[PATH_MAX+1];
315
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);
322       } else {
323         path->insert(0, '[');
324         path->insert(1, ']');
325         path->insert(1, buf);
326       }
327     }
328   }
329   return path;
330
331 #elif defined(WIN32)
332   //---------- Win32 ----------
333   char buf[_MAX_PATH];
334   char *fp;
335
336   buf[0] = '\0';
337   if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) {
338     path->clear();
339     return path;
340   }
341   path->clear();
342   path->append(buf);
343   return path;
344
345 #elif defined(ACORN)
346   //---------- RISCOS ----------
347   path->insert(0, '@');
348   return path;
349
350 #else
351   //---------- Unix and OS/2+EMX ----------
352   struct passwd *pw;
353   char buf[PATH_MAX+1];
354   GString *s;
355   char *p1, *p2;
356   int n;
357
358   if (path->getChar(0) == '~') {
359     if (path->getChar(1) == '/' ||
360 #ifdef __EMX__
361         path->getChar(1) == '\\' ||
362 #endif
363         path->getLength() == 1) {
364       path->del(0, 1);
365       s = getHomeDir();
366       path->insert(0, s);
367       delete s;
368     } else {
369       p1 = path->getCString() + 1;
370 #ifdef __EMX__
371       for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
372 #else
373       for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
374 #endif
375       if ((n = p2 - p1) > PATH_MAX)
376         n = PATH_MAX;
377       strncpy(buf, p1, n);
378       buf[n] = '\0';
379       if ((pw = getpwnam(buf))) {
380         path->del(0, p2 - p1 + 1);
381         path->insert(0, pw->pw_dir);
382       }
383     }
384   } else if (!isAbsolutePath(path->getCString())) {
385     if (getcwd(buf, sizeof(buf))) {
386 #ifndef __EMX__
387       path->insert(0, '/');
388 #endif
389       path->insert(0, buf);
390     }
391   }
392   return path;
393 #endif
394 }
395
396 //------------------------------------------------------------------------
397 // GDir and GDirEntry
398 //------------------------------------------------------------------------
399
400 GDirEntry::GDirEntry(char *dirPath, char *name1, GBool doStat) {
401 #ifdef VMS
402   char *p;
403 #elif defined(WIN32)
404   int fa;
405   GString *s;
406 #elif defined(ACORN)
407 #else
408   struct stat st;
409   GString *s;
410 #endif
411
412   name = new GString(name1);
413   dir = gFalse;
414   if (doStat) {
415 #ifdef VMS
416     if (!strcmp(name1, "-") ||
417         ((p = strrchr(name1, '.')) && !strncmp(p, ".DIR;", 5)))
418       dir = gTrue;
419 #elif defined(ACORN)
420 #else
421     s = new GString(dirPath);
422     appendToPath(s, name1);
423 #ifdef WIN32
424     fa = GetFileAttributes(s->getCString());
425     dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
426 #else
427     if (stat(s->getCString(), &st) == 0)
428       dir = S_ISDIR(st.st_mode);
429 #endif
430     delete s;
431 #endif
432   }
433 }
434
435 GDirEntry::~GDirEntry() {
436   delete name;
437 }
438
439 GDir::GDir(char *name, GBool doStat1) {
440   path = new GString(name);
441   doStat = doStat1;
442 #if defined(WIN32)
443   GString *tmp;
444
445   tmp = path->copy();
446   tmp->append("/*.*");
447   hnd = FindFirstFile(tmp->getCString(), &ffd);
448   delete tmp;
449 #elif defined(ACORN)
450 #else
451   dir = opendir(name);
452 #ifdef VMS
453   needParent = strchr(name, '[') != NULL;
454 #endif
455 #endif
456 }
457
458 GDir::~GDir() {
459   delete path;
460 #if defined(WIN32)
461   if (hnd) {
462     FindClose(hnd);
463     hnd = NULL;
464   }
465 #elif defined(ACORN)
466 #else
467   if (dir)
468     closedir(dir);
469 #endif
470 }
471
472 GDirEntry *GDir::getNextEntry() {
473   struct dirent *ent;
474   GDirEntry *e;
475
476   e = NULL;
477 #if defined(WIN32)
478   e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
479   if (hnd  && !FindNextFile(hnd, &ffd)) {
480     FindClose(hnd);
481     hnd = NULL;
482   }
483 #elif defined(ACORN)
484 #else
485   if (dir) {
486 #ifdef VMS
487     if (needParent) {
488       e = new GDirEntry(path->getCString(), "-", doStat);
489       needParent = gFalse;
490       return e;
491     }
492 #endif
493     ent = readdir(dir);
494 #ifndef VMS
495     if (ent && !strcmp(ent->d_name, "."))
496       ent = readdir(dir);
497 #endif
498     if (ent)
499       e = new GDirEntry(path->getCString(), ent->d_name, doStat);
500   }
501 #endif
502   return e;
503 }
504
505 void GDir::rewind() {
506 #ifdef WIN32
507   GString *tmp;
508
509   if (hnd)
510     FindClose(hnd);
511   tmp = path->copy();
512   tmp->append("/*.*");
513   hnd = FindFirstFile(tmp->getCString(), &ffd);
514 #elif defined(ACORN)
515 #else
516   if (dir)
517     rewinddir(dir);
518 #ifdef VMS
519   needParent = strchr(path->getCString(), '[') != NULL;
520 #endif
521 #endif
522 }