source: trunk/poppler/mypoppler/goo/gfile.cc @ 292

Last change on this file since 292 was 292, checked in by rbri, 11 years ago

Upps

File size: 16.0 KB
Line 
1//========================================================================
2//
3// gfile.cc
4//
5// Miscellaneous file and directory name manipulation.
6//
7// Copyright 1996-2003 Glyph & Cog, LLC
8//
9//========================================================================
10
11//========================================================================
12//
13// Modified under the Poppler project - http://poppler.freedesktop.org
14//
15// All changes made under the Poppler project to this file are licensed
16// under GPL version 2 or later
17//
18// Copyright (C) 2006 Takashi Iwai <tiwai@suse.de>
19// Copyright (C) 2006 Kristian HÞgsberg <krh@redhat.com>
20// Copyright (C) 2008 Adam Batkin <adam@batkin.net>
21// Copyright (C) 2008 Hib Eris <hib@hiberis.nl>
22// Copyright (C) 2009 Albert Astals Cid <aacid@kde.org>
23// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
24//
25// To see a description of the changes please see the Changelog file that
26// came with your tarball or type make ChangeLog if you are building from git
27//
28//========================================================================
29
30#include <config.h>
31
32#ifdef _WIN32
33#  include <time.h>
34#else
35#  if defined(MACOS)
36#    include <sys/stat.h>
37#  elif !defined(ACORN)
38#    include <sys/types.h>
39#    include <sys/stat.h>
40#    include <fcntl.h>
41#  endif
42#  include <limits.h>
43#  include <string.h>
44/* Lucide */
45#  if !defined(VMS) && !defined(ACORN) && !defined(MACOS) && !defined(OS2)
46#    include <pwd.h>
47#  endif
48#  if defined(VMS) && (__DECCXX_VER < 50200000)
49#    include <unixlib.h>
50#  endif
51#endif // _WIN32
52#include "GooString.h"
53#include "gfile.h"
54
55// Some systems don't define this, so just make it something reasonably
56// large.
57#ifndef PATH_MAX
58#define PATH_MAX 1024
59#endif
60
61//------------------------------------------------------------------------
62
63GooString *getHomeDir() {
64#ifdef VMS
65  //---------- VMS ----------
66  return new GooString("SYS$LOGIN:");
67
68/* Lucide */
69#elif defined(__EMX__) || defined(_WIN32) || defined(OS2)
70  //---------- OS/2+EMX and Win32 ----------
71  char *s;
72  GooString *ret;
73
74  if ((s = getenv("HOME")))
75    ret = new GooString(s);
76  else
77    ret = new GooString(".");
78  return ret;
79
80#elif defined(ACORN)
81  //---------- RISCOS ----------
82  return new GooString("@");
83
84#elif defined(MACOS)
85  //---------- MacOS ----------
86  return new GooString(":");
87
88#else
89  //---------- Unix ----------
90  char *s;
91  struct passwd *pw;
92  GooString *ret;
93
94  if ((s = getenv("HOME"))) {
95    ret = new GooString(s);
96  } else {
97    if ((s = getenv("USER")))
98      pw = getpwnam(s);
99    else
100      pw = getpwuid(getuid());
101    if (pw)
102      ret = new GooString(pw->pw_dir);
103    else
104      ret = new GooString(".");
105  }
106  return ret;
107#endif
108}
109
110GooString *getCurrentDir() {
111  char buf[PATH_MAX+1];
112
113#if defined(__EMX__)
114  if (_getcwd2(buf, sizeof(buf)))
115#elif defined(_WIN32)
116  if (GetCurrentDirectory(sizeof(buf), buf))
117#elif defined(ACORN)
118  if (strcpy(buf, "@"))
119#elif defined(MACOS)
120  if (strcpy(buf, ":"))
121#else
122  if (getcwd(buf, sizeof(buf)))
123#endif
124    return new GooString(buf);
125  return new GooString();
126}
127
128GooString *appendToPath(GooString *path, char *fileName) {
129#if defined(VMS)
130  //---------- VMS ----------
131  //~ this should handle everything necessary for file
132  //~ requesters, but it's certainly not complete
133  char *p0, *p1, *p2;
134  char *q1;
135
136  p0 = path->getCString();
137  p1 = p0 + path->getLength() - 1;
138  if (!strcmp(fileName, "-")) {
139    if (*p1 == ']') {
140      for (p2 = p1; p2 > p0 && *p2 != '.' && *p2 != '['; --p2) ;
141      if (*p2 == '[')
142        ++p2;
143      path->del(p2 - p0, p1 - p2);
144    } else if (*p1 == ':') {
145      path->append("[-]");
146    } else {
147      path->clear();
148      path->append("[-]");
149    }
150  } else if ((q1 = strrchr(fileName, '.')) && !strncmp(q1, ".DIR;", 5)) {
151    if (*p1 == ']') {
152      path->insert(p1 - p0, '.');
153      path->insert(p1 - p0 + 1, fileName, q1 - fileName);
154    } else if (*p1 == ':') {
155      path->append('[');
156      path->append(']');
157      path->append(fileName, q1 - fileName);
158    } else {
159      path->clear();
160      path->append(fileName, q1 - fileName);
161    }
162  } else {
163    if (*p1 != ']' && *p1 != ':')
164      path->clear();
165    path->append(fileName);
166  }
167  return path;
168
169#elif defined(_WIN32)
170  //---------- Win32 ----------
171  GooString *tmp;
172  char buf[256];
173  char *fp;
174
175  tmp = new GooString(path);
176  tmp->append('/');
177  tmp->append(fileName);
178  GetFullPathName(tmp->getCString(), sizeof(buf), buf, &fp);
179  delete tmp;
180  path->clear();
181  path->append(buf);
182  return path;
183
184#elif defined(ACORN)
185  //---------- RISCOS ----------
186  char *p;
187  int i;
188
189  path->append(".");
190  i = path->getLength();
191  path->append(fileName);
192  for (p = path->getCString() + i; *p; ++p) {
193    if (*p == '/') {
194      *p = '.';
195    } else if (*p == '.') {
196      *p = '/';
197    }
198  }
199  return path;
200
201#elif defined(MACOS)
202  //---------- MacOS ----------
203  char *p;
204  int i;
205
206  path->append(":");
207  i = path->getLength();
208  path->append(fileName);
209  for (p = path->getCString() + i; *p; ++p) {
210    if (*p == '/') {
211      *p = ':';
212    } else if (*p == '.') {
213      *p = ':';
214    }
215  }
216  return path;
217
218/* Lucide */
219#elif defined(__EMX__) || defined(OS2)
220  //---------- OS/2+EMX ----------
221  int i;
222
223  // appending "." does nothing
224  if (!strcmp(fileName, "."))
225    return path;
226
227  // appending ".." goes up one directory
228  if (!strcmp(fileName, "..")) {
229    for (i = path->getLength() - 2; i >= 0; --i) {
230      if (path->getChar(i) == '/' || path->getChar(i) == '\\' ||
231          path->getChar(i) == ':')
232        break;
233    }
234    if (i <= 0) {
235      if (path->getChar(0) == '/' || path->getChar(0) == '\\') {
236        path->del(1, path->getLength() - 1);
237      } else if (path->getLength() >= 2 && path->getChar(1) == ':') {
238        path->del(2, path->getLength() - 2);
239      } else {
240        path->clear();
241        path->append("..");
242      }
243    } else {
244      if (path->getChar(i-1) == ':')
245        ++i;
246      path->del(i, path->getLength() - i);
247    }
248    return path;
249  }
250
251  // otherwise, append "/" and new path component
252  if (path->getLength() > 0 &&
253      path->getChar(path->getLength() - 1) != '/' &&
254      path->getChar(path->getLength() - 1) != '\\')
255    path->append('/');
256  path->append(fileName);
257  return path;
258
259#else
260  //---------- Unix ----------
261  int i;
262
263  // appending "." does nothing
264  if (!strcmp(fileName, "."))
265    return path;
266
267  // appending ".." goes up one directory
268  if (!strcmp(fileName, "..")) {
269    for (i = path->getLength() - 2; i >= 0; --i) {
270      if (path->getChar(i) == '/')
271        break;
272    }
273    if (i <= 0) {
274      if (path->getChar(0) == '/') {
275        path->del(1, path->getLength() - 1);
276      } else {
277        path->clear();
278        path->append("..");
279      }
280    } else {
281      path->del(i, path->getLength() - i);
282    }
283    return path;
284  }
285
286  // otherwise, append "/" and new path component
287  if (path->getLength() > 0 &&
288      path->getChar(path->getLength() - 1) != '/')
289    path->append('/');
290  path->append(fileName);
291  return path;
292#endif
293}
294
295GooString *grabPath(char *fileName) {
296#ifdef VMS
297  //---------- VMS ----------
298  char *p;
299
300  if ((p = strrchr(fileName, ']')))
301    return new GooString(fileName, p + 1 - fileName);
302  if ((p = strrchr(fileName, ':')))
303    return new GooString(fileName, p + 1 - fileName);
304  return new GooString();
305
306/* Lucide */
307#elif defined(__EMX__) || defined(_WIN32) || defined(OS2)
308  //---------- OS/2+EMX and Win32 ----------
309  char *p;
310
311  if ((p = strrchr(fileName, '/')))
312    return new GooString(fileName, p - fileName);
313  if ((p = strrchr(fileName, '\\')))
314    return new GooString(fileName, p - fileName);
315  if ((p = strrchr(fileName, ':')))
316    return new GooString(fileName, p + 1 - fileName);
317  return new GooString();
318
319#elif defined(ACORN)
320  //---------- RISCOS ----------
321  char *p;
322
323  if ((p = strrchr(fileName, '.')))
324    return new GooString(fileName, p - fileName);
325  return new GooString();
326
327#elif defined(MACOS)
328  //---------- MacOS ----------
329  char *p;
330
331  if ((p = strrchr(fileName, ':')))
332    return new GooString(fileName, p - fileName);
333  return new GooString();
334
335#else
336  //---------- Unix ----------
337  char *p;
338
339  if ((p = strrchr(fileName, '/')))
340    return new GooString(fileName, p - fileName);
341  return new GooString();
342#endif
343}
344
345GBool isAbsolutePath(char *path) {
346#ifdef VMS
347  //---------- VMS ----------
348  return strchr(path, ':') ||
349         (path[0] == '[' && path[1] != '.' && path[1] != '-');
350
351/* Lucide */
352#elif defined(__EMX__) || defined(_WIN32) || defined(OS2)
353  //---------- OS/2+EMX and Win32 ----------
354  return path[0] == '/' || path[0] == '\\' || path[1] == ':';
355
356#elif defined(ACORN)
357  //---------- RISCOS ----------
358  return path[0] == '$';
359
360#elif defined(MACOS)
361  //---------- MacOS ----------
362  return path[0] != ':';
363
364#else
365  //---------- Unix ----------
366  return path[0] == '/';
367#endif
368}
369
370GooString *makePathAbsolute(GooString *path) {
371#ifdef VMS
372  //---------- VMS ----------
373  char buf[PATH_MAX+1];
374
375  if (!isAbsolutePath(path->getCString())) {
376    if (getcwd(buf, sizeof(buf))) {
377      path->insert(0, buf);
378    }
379  }
380  return path;
381
382#elif defined(_WIN32)
383  //---------- Win32 ----------
384  char buf[_MAX_PATH];
385  char *fp;
386
387  buf[0] = '\0';
388  if (!GetFullPathName(path->getCString(), _MAX_PATH, buf, &fp)) {
389    path->clear();
390    return path;
391  }
392  path->clear();
393  path->append(buf);
394  return path;
395
396#elif defined(ACORN)
397  //---------- RISCOS ----------
398  path->insert(0, '@');
399  return path;
400
401#elif defined(MACOS)
402  //---------- MacOS ----------
403  path->del(0, 1);
404  return path;
405
406/* Lucide */
407#elif defined(OS2)
408  //---------- OS/2 -----------
409  char buf[_MAX_PATH];
410  buf[0] = '\0';
411  if (!_fullpath( buf, path->getCString(), _MAX_PATH ) ) {
412    path->clear();
413    return path;
414  }
415  path->clear();
416  path->append(buf);
417  return path;
418
419#else
420  //---------- Unix and OS/2+EMX ----------
421  struct passwd *pw;
422  char buf[PATH_MAX+1];
423  GooString *s;
424  char *p1, *p2;
425  int n;
426
427  if (path->getChar(0) == '~') {
428    if (path->getChar(1) == '/' ||
429#ifdef __EMX__
430        path->getChar(1) == '\\' ||
431#endif
432        path->getLength() == 1) {
433      path->del(0, 1);
434      s = getHomeDir();
435      path->insert(0, s);
436      delete s;
437    } else {
438      p1 = path->getCString() + 1;
439#ifdef __EMX__
440      for (p2 = p1; *p2 && *p2 != '/' && *p2 != '\\'; ++p2) ;
441#else
442      for (p2 = p1; *p2 && *p2 != '/'; ++p2) ;
443#endif
444      if ((n = p2 - p1) > PATH_MAX)
445        n = PATH_MAX;
446      strncpy(buf, p1, n);
447      buf[n] = '\0';
448      if ((pw = getpwnam(buf))) {
449        path->del(0, p2 - p1 + 1);
450        path->insert(0, pw->pw_dir);
451      }
452    }
453  } else if (!isAbsolutePath(path->getCString())) {
454    if (getcwd(buf, sizeof(buf))) {
455#ifndef __EMX__
456      path->insert(0, '/');
457#endif
458      path->insert(0, buf);
459    }
460  }
461  return path;
462#endif
463}
464
465time_t getModTime(char *fileName) {
466#ifdef _WIN32
467  //~ should implement this, but it's (currently) only used in xpdf
468  return 0;
469#else
470  struct stat statBuf;
471
472  if (stat(fileName, &statBuf)) {
473    return 0;
474  }
475  return statBuf.st_mtime;
476#endif
477}
478
479GBool openTempFile(GooString **name, FILE **f, char *mode) {
480#if defined(_WIN32)
481  //---------- Win32 ----------
482  char *tempDir;
483  GooString *s, *s2;
484  char buf[32];
485  FILE *f2;
486  int t, i;
487
488  // this has the standard race condition problem, but I haven't found
489  // a better way to generate temp file names with extensions on
490  // Windows
491  if ((tempDir = getenv("TEMP"))) {
492    s = new GooString(tempDir);
493    s->append('\\');
494  } else {
495    s = new GooString();
496  }
497  s->append("x");
498  t = (int)time(NULL);
499  for (i = 0; i < 1000; ++i) {
500    sprintf(buf, "%d", t + i);
501    s2 = s->copy()->append(buf);
502    if (!(f2 = fopen(s2->getCString(), "r"))) {
503      if (!(f2 = fopen(s2->getCString(), mode))) {
504        delete s2;
505        delete s;
506        return gFalse;
507      }
508      *name = s2;
509      *f = f2;
510      delete s;
511      return gTrue;
512    }
513    fclose(f2);
514    delete s2;
515  }
516  delete s;
517  return gFalse;
518/* Lucide */
519#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS) || defined(OS2)
520  //---------- non-Unix ----------
521  char *s;
522
523  // There is a security hole here: an attacker can create a symlink
524  // with this file name after the tmpnam call and before the fopen
525  // call.  I will happily accept fixes to this function for non-Unix
526  // OSs.
527  if (!(s = tmpnam(NULL))) {
528    return gFalse;
529  }
530  *name = new GooString(s);
531  if (!(*f = fopen((*name)->getCString(), mode))) {
532    delete (*name);
533    return gFalse;
534  }
535  return gTrue;
536#else
537  //---------- Unix ----------
538  char *s;
539  int fd;
540
541#if HAVE_MKSTEMP
542  if ((s = getenv("TMPDIR"))) {
543    *name = new GooString(s);
544  } else {
545    *name = new GooString("/tmp");
546  }
547  (*name)->append("/XXXXXX");
548  fd = mkstemp((*name)->getCString());
549#else // HAVE_MKSTEMP
550  if (!(s = tmpnam(NULL))) {
551    return gFalse;
552  }
553  *name = new GooString(s);
554  fd = open((*name)->getCString(), O_WRONLY | O_CREAT | O_EXCL, 0600);
555#endif // HAVE_MKSTEMP
556  if (fd < 0 || !(*f = fdopen(fd, mode))) {
557    delete *name;
558    return gFalse;
559  }
560  return gTrue;
561#endif
562}
563
564GBool executeCommand(char *cmd) {
565#ifdef VMS
566  return system(cmd) ? gTrue : gFalse;
567#else
568  return system(cmd) ? gFalse : gTrue;
569#endif
570}
571
572char *getLine(char *buf, int size, FILE *f) {
573  int c, i;
574
575  i = 0;
576  while (i < size - 1) {
577    if ((c = fgetc(f)) == EOF) {
578      break;
579    }
580    buf[i++] = (char)c;
581    if (c == '\x0a') {
582      break;
583    }
584    if (c == '\x0d') {
585      c = fgetc(f);
586      if (c == '\x0a' && i < size - 1) {
587        buf[i++] = (char)c;
588      } else if (c != EOF) {
589        ungetc(c, f);
590      }
591      break;
592    }
593  }
594  buf[i] = '\0';
595  if (i == 0) {
596    return NULL;
597  }
598  return buf;
599}
600
601//------------------------------------------------------------------------
602// GDir and GDirEntry
603//------------------------------------------------------------------------
604
605GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) {
606#ifdef VMS
607  char *p;
608#elif defined(_WIN32)
609  DWORD fa;
610#elif defined(ACORN)
611#else
612  struct stat st;
613#endif
614
615  name = new GooString(nameA);
616  dir = gFalse;
617  fullPath = new GooString(dirPath);
618  appendToPath(fullPath, nameA);
619  if (doStat) {
620#ifdef VMS
621    if (!strcmp(nameA, "-") ||
622        ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5)))
623      dir = gTrue;
624#elif defined(ACORN)
625#else
626#ifdef _WIN32
627    fa = GetFileAttributes(fullPath->getCString());
628    dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
629#else
630    if (stat(fullPath->getCString(), &st) == 0)
631      dir = S_ISDIR(st.st_mode);
632#endif
633#endif
634  }
635}
636
637GDirEntry::~GDirEntry() {
638  delete fullPath;
639  delete name;
640}
641
642GDir::GDir(char *name, GBool doStatA) {
643  path = new GooString(name);
644  doStat = doStatA;
645#if defined(_WIN32)
646  GooString *tmp;
647
648  tmp = path->copy();
649  tmp->append("/*.*");
650  hnd = FindFirstFile(tmp->getCString(), &ffd);
651  delete tmp;
652#elif defined(ACORN)
653#elif defined(MACOS)
654#else
655  dir = opendir(name);
656#ifdef VMS
657  needParent = strchr(name, '[') != NULL;
658#endif
659#endif
660}
661
662GDir::~GDir() {
663  delete path;
664#if defined(_WIN32)
665  if (hnd != INVALID_HANDLE_VALUE) {
666    FindClose(hnd);
667    hnd = INVALID_HANDLE_VALUE;
668  }
669#elif defined(ACORN)
670#elif defined(MACOS)
671#else
672  if (dir)
673    closedir(dir);
674#endif
675}
676
677GDirEntry *GDir::getNextEntry() {
678  GDirEntry *e;
679
680#if defined(_WIN32)
681  if (hnd != INVALID_HANDLE_VALUE) {
682    e = new GDirEntry(path->getCString(), ffd.cFileName, doStat);
683    if (!FindNextFile(hnd, &ffd)) {
684      FindClose(hnd);
685      hnd = INVALID_HANDLE_VALUE;
686    }
687  } else {
688    e = NULL;
689  }
690#elif defined(ACORN)
691#elif defined(MACOS)
692#elif defined(VMS)
693  struct dirent *ent;
694  e = NULL;
695  if (dir) {
696    if (needParent) {
697      e = new GDirEntry(path->getCString(), "-", doStat);
698      needParent = gFalse;
699      return e;
700    }
701    ent = readdir(dir);
702    if (ent) {
703      e = new GDirEntry(path->getCString(), ent->d_name, doStat);
704    }
705  }
706#else
707  struct dirent *ent;
708  e = NULL;
709  if (dir) {
710    do {
711      ent = readdir(dir);
712    }
713    while (ent && (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")));
714    if (ent) {
715      e = new GDirEntry(path->getCString(), ent->d_name, doStat);
716    }
717  }
718#endif
719
720  return e;
721}
722
723void GDir::rewind() {
724#ifdef _WIN32
725  GooString *tmp;
726
727  if (hnd != INVALID_HANDLE_VALUE)
728    FindClose(hnd);
729  tmp = path->copy();
730  tmp->append("/*.*");
731  hnd = FindFirstFile(tmp->getCString(), &ffd);
732  delete tmp;
733#elif defined(ACORN)
734#elif defined(MACOS)
735#else
736  if (dir)
737    rewinddir(dir);
738#ifdef VMS
739  needParent = strchr(path->getCString(), '[') != NULL;
740#endif
741#endif
742}
Note: See TracBrowser for help on using the repository browser.