]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/gfile.cxx
1 //========================================================================
5 // Miscellaneous file and directory name manipulation.
7 // Copyright 1996 Derek B. Noonburg
9 //========================================================================
14 # include <kpathsea/win32lib.h>
19 # include <sys/stat.h>
20 # elif !defined(ACORN)
21 # include <sys/types.h>
22 # include <sys/stat.h>
27 # if !defined(VMS) && !defined(ACORN) && !defined(MACOS)
30 # if defined(VMS) && (__DECCXX_VER < 50200000)
38 # include <cups/cups.h>
39 #endif // HAVE_LIBCUPS
42 // Solaris doesn't define mkstemp()...
44 extern int mkstemp(char *);
48 // Some systems don't define this, so just make it something reasonably
54 //------------------------------------------------------------------------
56 GString
*getHomeDir() {
58 //---------- VMS ----------
59 return new GString("SYS$LOGIN:");
61 #elif defined(__EMX__) || defined(WIN32)
62 //---------- OS/2+EMX and Win32 ----------
66 if ((s
= getenv("HOME")))
69 ret
= new GString(".");
73 //---------- RISCOS ----------
74 return new GString("@");
77 //---------- MacOS ----------
78 return new GString(":");
81 //---------- Unix ----------
86 if ((s
= getenv("HOME"))) {
89 } else if ((s
= getenv("CUPS_SERVERROOT"))) {
91 # endif // HAVE_LIBCUPS
93 if ((s
= getenv("USER")))
96 pw
= getpwuid(getuid());
98 ret
= new GString(pw
->pw_dir
);
100 ret
= new GString(".");
106 GString
*getCurrentDir() {
107 char buf
[PATH_MAX
+1];
110 if (_getcwd2(buf
, sizeof(buf
)))
112 if (GetCurrentDirectory(sizeof(buf
), buf
))
114 if (strcpy(buf
, "@"))
116 if (strcpy(buf
, ":"))
118 if (getcwd(buf
, sizeof(buf
)))
120 return new GString(buf
);
121 return new GString();
124 GString
*appendToPath(GString
*path
, const char *fileName
) {
126 //---------- VMS ----------
127 //~ this should handle everything necessary for file
128 //~ requesters, but it's certainly not complete
132 p0
= path
->getCString();
133 p1
= p0
+ path
->getLength() - 1;
134 if (!strcmp(fileName
, "-")) {
136 for (p2
= p1
; p2
> p0
&& *p2
!= '.' && *p2
!= '['; --p2
) ;
139 path
->del(p2
- p0
, p1
- p2
);
140 } else if (*p1
== ':') {
146 } else if ((q1
= strrchr(fileName
, '.')) && !strncmp(q1
, ".DIR;", 5)) {
148 path
->insert(p1
- p0
, '.');
149 path
->insert(p1
- p0
+ 1, fileName
, q1
- fileName
);
150 } else if (*p1
== ':') {
153 path
->append(fileName
, q1
- fileName
);
156 path
->append(fileName
, q1
- fileName
);
159 if (*p1
!= ']' && *p1
!= ':')
161 path
->append(fileName
);
166 //---------- Win32 ----------
171 tmp
= new GString(path
);
173 tmp
->append(fileName
);
174 GetFullPathName(tmp
->getCString(), sizeof(buf
), buf
, &fp
);
181 //---------- RISCOS ----------
186 i
= path
->getLength();
187 path
->append(fileName
);
188 for (p
= path
->getCString() + i
; *p
; ++p
) {
191 } else if (*p
== '.') {
198 //---------- MacOS ----------
203 i
= path
->getLength();
204 path
->append(fileName
);
205 for (p
= path
->getCString() + i
; *p
; ++p
) {
208 } else if (*p
== '.') {
214 #elif defined(__EMX__)
215 //---------- OS/2+EMX ----------
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
) == '/' || path
->getChar(i
) == '\\' ||
226 path
->getChar(i
) == ':')
230 if (path
->getChar(0) == '/' || path
->getChar(0) == '\\') {
231 path
->del(1, path
->getLength() - 1);
232 } else if (path
->getLength() >= 2 && path
->getChar(1) == ':') {
233 path
->del(2, path
->getLength() - 2);
239 if (path
->getChar(i
-1) == ':')
241 path
->del(i
, path
->getLength() - i
);
246 // otherwise, append "/" and new path component
247 if (path
->getLength() > 0 &&
248 path
->getChar(path
->getLength() - 1) != '/' &&
249 path
->getChar(path
->getLength() - 1) != '\\')
251 path
->append(fileName
);
255 //---------- Unix ----------
258 // appending "." does nothing
259 if (!strcmp(fileName
, "."))
262 // appending ".." goes up one directory
263 if (!strcmp(fileName
, "..")) {
264 for (i
= path
->getLength() - 2; i
>= 0; --i
) {
265 if (path
->getChar(i
) == '/')
269 if (path
->getChar(0) == '/') {
270 path
->del(1, path
->getLength() - 1);
276 path
->del(i
, path
->getLength() - i
);
281 // otherwise, append "/" and new path component
282 if (path
->getLength() > 0 &&
283 path
->getChar(path
->getLength() - 1) != '/')
285 path
->append(fileName
);
290 GString
*grabPath(const char *fileName
) {
292 //---------- VMS ----------
295 if ((p
= strrchr(fileName
, ']')))
296 return new GString(fileName
, p
+ 1 - fileName
);
297 if ((p
= strrchr(fileName
, ':')))
298 return new GString(fileName
, p
+ 1 - fileName
);
299 return new GString();
301 #elif defined(__EMX__) || defined(WIN32)
302 //---------- OS/2+EMX and Win32 ----------
305 if ((p
= strrchr(fileName
, '/')))
306 return new GString(fileName
, p
- fileName
);
307 if ((p
= strrchr(fileName
, '\\')))
308 return new GString(fileName
, p
- fileName
);
309 if ((p
= strrchr(fileName
, ':')))
310 return new GString(fileName
, p
+ 1 - fileName
);
311 return new GString();
314 //---------- RISCOS ----------
317 if ((p
= strrchr(fileName
, '.')))
318 return new GString(fileName
, p
- fileName
);
319 return new GString();
322 //---------- MacOS ----------
325 if ((p
= strrchr(fileName
, ':')))
326 return new GString(fileName
, p
- fileName
);
327 return new GString();
330 //---------- Unix ----------
333 if ((p
= strrchr(fileName
, '/')))
334 return new GString(fileName
, p
- fileName
);
335 return new GString();
339 GBool
isAbsolutePath(const char *path
) {
341 //---------- VMS ----------
342 return strchr(path
, ':') ||
343 (path
[0] == '[' && path
[1] != '.' && path
[1] != '-');
345 #elif defined(__EMX__) || defined(WIN32)
346 //---------- OS/2+EMX and Win32 ----------
347 return path
[0] == '/' || path
[0] == '\\' || path
[1] == ':';
350 //---------- RISCOS ----------
351 return path
[0] == '$';
354 //---------- MacOS ----------
355 return path
[0] != ':';
358 //---------- Unix ----------
359 return path
[0] == '/';
363 GString
*makePathAbsolute(GString
*path
) {
365 //---------- VMS ----------
366 char buf
[PATH_MAX
+1];
368 if (!isAbsolutePath(path
->getCString())) {
369 if (getcwd(buf
, sizeof(buf
))) {
370 path
->insert(0, buf
);
376 //---------- Win32 ----------
381 if (!GetFullPathName(path
->getCString(), _MAX_PATH
, buf
, &fp
)) {
390 //---------- RISCOS ----------
391 path
->insert(0, '@');
395 //---------- MacOS ----------
400 //---------- Unix and OS/2+EMX ----------
402 char buf
[PATH_MAX
+1];
407 if (path
->getChar(0) == '~') {
408 if (path
->getChar(1) == '/' ||
410 path
->getChar(1) == '\\' ||
412 path
->getLength() == 1) {
418 p1
= path
->getCString() + 1;
420 for (p2
= p1
; *p2
&& *p2
!= '/' && *p2
!= '\\'; ++p2
) ;
422 for (p2
= p1
; *p2
&& *p2
!= '/'; ++p2
) ;
424 if ((n
= p2
- p1
) > PATH_MAX
)
428 if ((pw
= getpwnam(buf
))) {
429 path
->del(0, p2
- p1
+ 1);
430 path
->insert(0, pw
->pw_dir
);
433 } else if (!isAbsolutePath(path
->getCString())) {
434 if (getcwd(buf
, sizeof(buf
))) {
436 path
->insert(0, '/');
438 path
->insert(0, buf
);
445 time_t getModTime(const char *fileName
) {
447 //~ should implement this, but it's (currently) only used in xpdf
452 if (stat(fileName
, &statBuf
)) {
455 return statBuf
.st_mtime
;
459 GBool
openTempFile(GString
**name
, FILE **f
, const char *mode
, const char *ext
) {
460 #if defined(VMS) || defined(__EMX__) || defined(WIN32) || defined(ACORN) || defined(MACOS)
461 //---------- non-Unix ----------
464 // There is a security hole here: an attacker can create a symlink
465 // with this file name after the tmpnam call and before the fopen
466 // call. I will happily accept fixes to this function for non-Unix
468 if (!(s
= tmpnam(NULL
))) {
471 *name
= new GString(s
);
473 (*name
)->append(ext
);
475 if (!(*f
= fopen((*name
)->getCString(), mode
))) {
481 //---------- Unix ----------
485 // MRS: Currently there is no standard function for creating a temporary
486 // file with an extension; this is required when uncompressing
487 // LZW data using the uncompress program on some UNIX, which is
488 // looking for a ".Z" extension on the temporary filename. Sooo,
489 // when you print an *OLD* PDF file that uses LZW compression,
490 // the tmpnam() function is usually the one that is called to
491 // create the temporary file. Under *BSD, the safer mkstemps()
492 // function is used instead.
494 // That said, all CUPS filters are run with TMPDIR pointing to
495 // a private temporary directory, which by default is only
496 // accessible to the 'lp' user. Also, most files use Flate
497 // compression now and will be able to use the (safer)
498 // mkstemp() function for any temporary files...
502 if ((s
= getenv("TMPDIR"))) {
503 *name
= new GString(s
);
505 *name
= new GString("/tmp");
507 (*name
)->append("/XXXXXX");
508 (*name
)->append(ext
);
509 fd
= mkstemps((*name
)->getCString(), strlen(ext
));
510 # else // HAVE_MKSTEMPS
512 if (!(s
= tmpnam(NULL
))) {
515 *name
= new GString(s
);
516 s
= (*name
)->getCString();
517 if ((p
= strrchr(s
, '.'))) {
518 (*name
)->del(p
- s
, (*name
)->getLength() - (p
- s
));
520 (*name
)->append(ext
);
521 fd
= open((*name
)->getCString(), O_WRONLY
| O_CREAT
| O_EXCL
, 0600);
522 # endif // HAVE_MKSTEMPS
525 if ((s
= getenv("TMPDIR"))) {
526 *name
= new GString(s
);
528 *name
= new GString("/tmp");
530 (*name
)->append("/XXXXXX");
531 fd
= mkstemp((*name
)->getCString());
532 # else // HAVE_MKSTEMP
533 if (!(s
= tmpnam(NULL
))) {
536 *name
= new GString(s
);
537 fd
= open((*name
)->getCString(), O_WRONLY
| O_CREAT
| O_EXCL
, 0600);
538 # endif // HAVE_MKSTEMP
540 if (fd
< 0 || !(*f
= fdopen(fd
, mode
))) {
548 //------------------------------------------------------------------------
549 // GDir and GDirEntry
550 //------------------------------------------------------------------------
552 GDirEntry::GDirEntry(const char *dirPath
, const char *name1
, GBool doStat
) {
564 name
= new GString(name1
);
568 if (!strcmp(name1
, "-") ||
569 ((p
= strrchr(name1
, '.')) && !strncmp(p
, ".DIR;", 5)))
573 s
= new GString(dirPath
);
574 appendToPath(s
, name1
);
576 fa
= GetFileAttributes(s
->getCString());
577 dir
= (fa
!= 0xFFFFFFFF && (fa
& FILE_ATTRIBUTE_DIRECTORY
));
579 if (stat(s
->getCString(), &st
) == 0)
580 dir
= S_ISDIR(st
.st_mode
);
587 GDirEntry::~GDirEntry() {
591 GDir::GDir(const char *name
, GBool doStat1
) {
592 path
= new GString(name
);
599 hnd
= FindFirstFile(tmp
->getCString(), &ffd
);
606 needParent
= strchr(name
, '[') != NULL
;
626 GDirEntry
*GDir::getNextEntry() {
632 e
= new GDirEntry(path
->getCString(), ffd
.cFileName
, doStat
);
633 if (hnd
&& !FindNextFile(hnd
, &ffd
)) {
643 e
= new GDirEntry(path
->getCString(), "-", doStat
);
650 if (ent
&& !strcmp(ent
->d_name
, "."))
654 e
= new GDirEntry(path
->getCString(), ent
->d_name
, doStat
);
660 void GDir::rewind() {
668 hnd
= FindFirstFile(tmp
->getCString(), &ffd
);
675 needParent
= strchr(path
->getCString(), '[') != NULL
;