]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/gfile.cxx
1 //========================================================================
5 // Miscellaneous file and directory name manipulation.
7 // Copyright 1996-2003 Glyph & Cog, LLC
9 //========================================================================
16 # include <kpathsea/win32lib.h>
21 # include <sys/stat.h>
22 # elif !defined(ACORN)
23 # include <sys/types.h>
24 # include <sys/stat.h>
29 # if !defined(VMS) && !defined(ACORN) && !defined(MACOS)
32 # if defined(VMS) && (__DECCXX_VER < 50200000)
39 // Some systems don't define this, so just make it something reasonably
45 //------------------------------------------------------------------------
47 GString
*getHomeDir() {
49 //---------- VMS ----------
50 return new GString("SYS$LOGIN:");
52 #elif defined(__EMX__) || defined(WIN32)
53 //---------- OS/2+EMX and Win32 ----------
57 if ((s
= getenv("HOME")))
60 ret
= new GString(".");
64 //---------- RISCOS ----------
65 return new GString("@");
68 //---------- MacOS ----------
69 return new GString(":");
72 //---------- Unix ----------
77 if ((s
= getenv("HOME"))) {
80 if ((s
= getenv("USER")))
83 pw
= getpwuid(getuid());
85 ret
= new GString(pw
->pw_dir
);
87 ret
= new GString(".");
93 GString
*getCurrentDir() {
97 if (_getcwd2(buf
, sizeof(buf
)))
99 if (GetCurrentDirectory(sizeof(buf
), buf
))
101 if (strcpy(buf
, "@"))
103 if (strcpy(buf
, ":"))
105 if (getcwd(buf
, sizeof(buf
)))
107 return new GString(buf
);
108 return new GString();
111 GString
*appendToPath(GString
*path
, const char *fileName
) {
113 //---------- VMS ----------
114 //~ this should handle everything necessary for file
115 //~ requesters, but it's certainly not complete
119 p0
= path
->getCString();
120 p1
= p0
+ path
->getLength() - 1;
121 if (!strcmp(fileName
, "-")) {
123 for (p2
= p1
; p2
> p0
&& *p2
!= '.' && *p2
!= '['; --p2
) ;
126 path
->del(p2
- p0
, p1
- p2
);
127 } else if (*p1
== ':') {
133 } else if ((q1
= strrchr(fileName
, '.')) && !strncmp(q1
, ".DIR;", 5)) {
135 path
->insert(p1
- p0
, '.');
136 path
->insert(p1
- p0
+ 1, fileName
, q1
- fileName
);
137 } else if (*p1
== ':') {
140 path
->append(fileName
, q1
- fileName
);
143 path
->append(fileName
, q1
- fileName
);
146 if (*p1
!= ']' && *p1
!= ':')
148 path
->append(fileName
);
153 //---------- Win32 ----------
158 tmp
= new GString(path
);
160 tmp
->append(fileName
);
161 GetFullPathName(tmp
->getCString(), sizeof(buf
), buf
, &fp
);
168 //---------- RISCOS ----------
173 i
= path
->getLength();
174 path
->append(fileName
);
175 for (p
= path
->getCString() + i
; *p
; ++p
) {
178 } else if (*p
== '.') {
185 //---------- MacOS ----------
190 i
= path
->getLength();
191 path
->append(fileName
);
192 for (p
= path
->getCString() + i
; *p
; ++p
) {
195 } else if (*p
== '.') {
201 #elif defined(__EMX__)
202 //---------- OS/2+EMX ----------
205 // appending "." does nothing
206 if (!strcmp(fileName
, "."))
209 // appending ".." goes up one directory
210 if (!strcmp(fileName
, "..")) {
211 for (i
= path
->getLength() - 2; i
>= 0; --i
) {
212 if (path
->getChar(i
) == '/' || path
->getChar(i
) == '\\' ||
213 path
->getChar(i
) == ':')
217 if (path
->getChar(0) == '/' || path
->getChar(0) == '\\') {
218 path
->del(1, path
->getLength() - 1);
219 } else if (path
->getLength() >= 2 && path
->getChar(1) == ':') {
220 path
->del(2, path
->getLength() - 2);
226 if (path
->getChar(i
-1) == ':')
228 path
->del(i
, path
->getLength() - i
);
233 // otherwise, append "/" and new path component
234 if (path
->getLength() > 0 &&
235 path
->getChar(path
->getLength() - 1) != '/' &&
236 path
->getChar(path
->getLength() - 1) != '\\')
238 path
->append(fileName
);
242 //---------- Unix ----------
245 // appending "." does nothing
246 if (!strcmp(fileName
, "."))
249 // appending ".." goes up one directory
250 if (!strcmp(fileName
, "..")) {
251 for (i
= path
->getLength() - 2; i
>= 0; --i
) {
252 if (path
->getChar(i
) == '/')
256 if (path
->getChar(0) == '/') {
257 path
->del(1, path
->getLength() - 1);
263 path
->del(i
, path
->getLength() - i
);
268 // otherwise, append "/" and new path component
269 if (path
->getLength() > 0 &&
270 path
->getChar(path
->getLength() - 1) != '/')
272 path
->append(fileName
);
277 GString
*grabPath(const char *fileName
) {
279 //---------- VMS ----------
282 if ((p
= strrchr(fileName
, ']')))
283 return new GString(fileName
, p
+ 1 - fileName
);
284 if ((p
= strrchr(fileName
, ':')))
285 return new GString(fileName
, p
+ 1 - fileName
);
286 return new GString();
288 #elif defined(__EMX__) || defined(WIN32)
289 //---------- OS/2+EMX and Win32 ----------
292 if ((p
= strrchr(fileName
, '/')))
293 return new GString(fileName
, p
- fileName
);
294 if ((p
= strrchr(fileName
, '\\')))
295 return new GString(fileName
, p
- fileName
);
296 if ((p
= strrchr(fileName
, ':')))
297 return new GString(fileName
, p
+ 1 - fileName
);
298 return new GString();
301 //---------- RISCOS ----------
304 if ((p
= strrchr(fileName
, '.')))
305 return new GString(fileName
, p
- fileName
);
306 return new GString();
309 //---------- MacOS ----------
312 if ((p
= strrchr(fileName
, ':')))
313 return new GString(fileName
, p
- fileName
);
314 return new GString();
317 //---------- Unix ----------
320 if ((p
= strrchr(fileName
, '/')))
321 return new GString(fileName
, p
- fileName
);
322 return new GString();
326 GBool
isAbsolutePath(const char *path
) {
328 //---------- VMS ----------
329 return strchr(path
, ':') ||
330 (path
[0] == '[' && path
[1] != '.' && path
[1] != '-');
332 #elif defined(__EMX__) || defined(WIN32)
333 //---------- OS/2+EMX and Win32 ----------
334 return path
[0] == '/' || path
[0] == '\\' || path
[1] == ':';
337 //---------- RISCOS ----------
338 return path
[0] == '$';
341 //---------- MacOS ----------
342 return path
[0] != ':';
345 //---------- Unix ----------
346 return path
[0] == '/';
350 GString
*makePathAbsolute(GString
*path
) {
352 //---------- VMS ----------
353 char buf
[PATH_MAX
+1];
355 if (!isAbsolutePath(path
->getCString())) {
356 if (getcwd(buf
, sizeof(buf
))) {
357 path
->insert(0, buf
);
363 //---------- Win32 ----------
368 if (!GetFullPathName(path
->getCString(), _MAX_PATH
, buf
, &fp
)) {
377 //---------- RISCOS ----------
378 path
->insert(0, '@');
382 //---------- MacOS ----------
387 //---------- Unix and OS/2+EMX ----------
389 char buf
[PATH_MAX
+1];
394 if (path
->getChar(0) == '~') {
395 if (path
->getChar(1) == '/' ||
397 path
->getChar(1) == '\\' ||
399 path
->getLength() == 1) {
405 p1
= path
->getCString() + 1;
407 for (p2
= p1
; *p2
&& *p2
!= '/' && *p2
!= '\\'; ++p2
) ;
409 for (p2
= p1
; *p2
&& *p2
!= '/'; ++p2
) ;
411 if ((n
= p2
- p1
) > PATH_MAX
)
415 if ((pw
= getpwnam(buf
))) {
416 path
->del(0, p2
- p1
+ 1);
417 path
->insert(0, pw
->pw_dir
);
420 } else if (!isAbsolutePath(path
->getCString())) {
421 if (getcwd(buf
, sizeof(buf
))) {
423 path
->insert(0, '/');
425 path
->insert(0, buf
);
432 time_t getModTime(const char *fileName
) {
434 //~ should implement this, but it's (currently) only used in xpdf
439 if (stat(fileName
, &statBuf
)) {
442 return statBuf
.st_mtime
;
446 GBool
openTempFile(GString
**name
, FILE **f
, const char *mode
, const char *ext
) {
448 //---------- Win32 ----------
451 if (!(s
= _tempnam(getenv("TEMP"), NULL
))) {
454 *name
= new GString(s
);
457 (*name
)->append(ext
);
459 if (!(*f
= fopen((*name
)->getCString(), mode
))) {
464 #elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS)
465 //---------- non-Unix ----------
468 // There is a security hole here: an attacker can create a symlink
469 // with this file name after the tmpnam call and before the fopen
470 // call. I will happily accept fixes to this function for non-Unix
472 if (!(s
= tmpnam(NULL
))) {
475 *name
= new GString(s
);
477 (*name
)->append(ext
);
479 if (!(*f
= fopen((*name
)->getCString(), mode
))) {
485 //---------- Unix ----------
491 if ((s
= getenv("TMPDIR"))) {
492 *name
= new GString(s
);
494 *name
= new GString("/tmp");
496 (*name
)->append("/XXXXXX")->append(ext
);
497 fd
= mkstemps((*name
)->getCString(), strlen(ext
));
499 if (!(s
= tmpnam(NULL
))) {
502 *name
= new GString(s
);
503 (*name
)->append(ext
);
504 fd
= open((*name
)->getCString(), O_WRONLY
| O_CREAT
| O_EXCL
, 0600);
508 if ((s
= getenv("TMPDIR"))) {
509 *name
= new GString(s
);
511 *name
= new GString("/tmp");
513 (*name
)->append("/XXXXXX");
514 fd
= mkstemp((*name
)->getCString());
515 #else // HAVE_MKSTEMP
516 if (!(s
= tmpnam(NULL
))) {
519 *name
= new GString(s
);
520 fd
= open((*name
)->getCString(), O_WRONLY
| O_CREAT
| O_EXCL
, 0600);
521 #endif // HAVE_MKSTEMP
523 if (fd
< 0 || !(*f
= fdopen(fd
, mode
))) {
531 GBool
executeCommand(const char *cmd
) {
533 return system(cmd
) ? gTrue
: gFalse
;
535 return system(cmd
) ? gFalse
: gTrue
;
539 char *getLine(char *buf
, int size
, FILE *f
) {
543 while (i
< size
- 1) {
544 if ((c
= fgetc(f
)) == EOF
) {
553 if (c
== '\x0a' && i
< size
- 1) {
555 } else if (c
!= EOF
) {
568 //------------------------------------------------------------------------
569 // GDir and GDirEntry
570 //------------------------------------------------------------------------
572 GDirEntry::GDirEntry(const char *dirPath
, const char *nameA
, GBool doStat
) {
584 name
= new GString(nameA
);
588 if (!strcmp(nameA
, "-") ||
589 ((p
= strrchr(nameA
, '.')) && !strncmp(p
, ".DIR;", 5)))
593 s
= new GString(dirPath
);
594 appendToPath(s
, nameA
);
596 fa
= GetFileAttributes(s
->getCString());
597 dir
= (fa
!= 0xFFFFFFFF && (fa
& FILE_ATTRIBUTE_DIRECTORY
));
599 if (stat(s
->getCString(), &st
) == 0)
600 dir
= S_ISDIR(st
.st_mode
);
607 GDirEntry::~GDirEntry() {
611 GDir::GDir(const char *name
, GBool doStatA
) {
612 path
= new GString(name
);
619 hnd
= FindFirstFile(tmp
->getCString(), &ffd
);
626 needParent
= strchr(name
, '[') != NULL
;
646 GDirEntry
*GDir::getNextEntry() {
650 e
= new GDirEntry(path
->getCString(), ffd
.cFileName
, doStat
);
651 if (hnd
&& !FindNextFile(hnd
, &ffd
)) {
662 e
= new GDirEntry(path
->getCString(), "-", doStat
);
668 e
= new GDirEntry(path
->getCString(), ent
->d_name
, doStat
);
676 if (ent
&& !strcmp(ent
->d_name
, ".")) {
680 e
= new GDirEntry(path
->getCString(), ent
->d_name
, doStat
);
688 void GDir::rewind() {
696 hnd
= FindFirstFile(tmp
->getCString(), &ffd
);
703 needParent
= strchr(path
->getCString(), '[') != NULL
;