summaryrefslogtreecommitdiff
path: root/src/pdflib/pdcore/pc_file.c
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:33 +0000
committerscuri <scuri>2008-10-17 06:10:33 +0000
commit7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf (patch)
treed0857278bde2eff784227c57dcaf930346ceb7ac /src/pdflib/pdcore/pc_file.c
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/pdflib/pdcore/pc_file.c')
-rw-r--r--src/pdflib/pdcore/pc_file.c1548
1 files changed, 1548 insertions, 0 deletions
diff --git a/src/pdflib/pdcore/pc_file.c b/src/pdflib/pdcore/pc_file.c
new file mode 100644
index 0000000..35c67ed
--- /dev/null
+++ b/src/pdflib/pdcore/pc_file.c
@@ -0,0 +1,1548 @@
+/*---------------------------------------------------------------------------*
+ | PDFlib - A library for generating PDF on the fly |
+ +---------------------------------------------------------------------------+
+ | Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
+ +---------------------------------------------------------------------------+
+ | |
+ | This software is subject to the PDFlib license. It is NOT in the |
+ | public domain. Extended versions and commercial licenses are |
+ | available, please check http://www.pdflib.com. |
+ | |
+ *---------------------------------------------------------------------------*/
+
+/* $Id: pc_file.c,v 1.1 2008/10/17 06:10:43 scuri Exp $
+ *
+ * Various file routines
+ *
+ */
+
+#include <errno.h>
+
+#include "pc_util.h"
+#include "pc_md5.h"
+#include "pc_file.h"
+
+
+/* headers for getpid() or _getpid().
+*/
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <process.h>
+#include <io.h>
+#else
+#if defined(MAC)
+#include <MacErrors.h>
+#else
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#endif
+
+#ifndef WINCE
+#include <time.h>
+#else
+#include <winbase.h>
+#endif
+
+#ifdef VMS
+#include <errno.h>
+#include <descrip.h>
+#include <ssdef.h>
+#endif
+
+/* platform independent wrapper functions for 64-bit file handling.
+*/
+int
+pdc__fseek(FILE *fp, pdc_off_t offset, int whence)
+{
+#if defined(_LARGEFILE_SOURCE)
+ #if defined(WIN32)
+ switch (whence)
+ {
+ case SEEK_SET:
+ return fsetpos(fp, &offset);
+
+ case SEEK_CUR:
+ {
+ pdc_off_t pos;
+
+ fgetpos(fp, &pos);
+ pos += offset;
+ return fsetpos(fp, &pos);
+ }
+
+ case SEEK_END:
+ {
+ pdc_off_t pos, len;
+
+ pos = _telli64(fileno(fp));
+ _lseeki64(fileno(fp), 0, SEEK_END);
+ len = _telli64(fileno(fp));
+ _lseeki64(fileno(fp), pos, SEEK_SET);
+
+ len += offset;
+ return fsetpos(fp, &len);
+ }
+
+ default:
+ return -1;
+ }
+ #else
+ return fseeko(fp, offset, whence);
+ #endif
+#else
+ return fseek(fp, offset, whence);
+#endif
+}
+
+pdc_off_t
+pdc__ftell(FILE *fp)
+{
+#if defined(_LARGEFILE_SOURCE)
+ #if defined(WIN32)
+ pdc_off_t pos;
+
+ fgetpos(fp, &pos);
+ return pos;
+ #else
+ return ftello(fp);
+ #endif
+#else
+ return ftell(fp);
+#endif
+}
+
+size_t
+pdc__fread(void *ptr, size_t size, size_t nmemb, FILE *fp)
+{
+ return fread(ptr, size, nmemb, fp);
+}
+
+size_t
+pdc__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)
+{
+ return fwrite(ptr, size, nmemb, fp);
+}
+
+int
+pdc__fgetc(FILE *fp)
+{
+ return fgetc(fp);
+}
+
+int
+pdc__feof(FILE *fp)
+{
+ return feof(fp);
+}
+
+struct pdc_file_s
+{
+ pdc_core *pdc; /* pdcore struct */
+ char *filename; /* file name */
+ FILE *fp; /* file struct or NULL. Then data != NULL: */
+ pdc_bool wrmode; /* writing mode */
+ pdc_byte *data; /* file data or NULL. Then fp != NULL */
+ pdc_byte *end; /* first byte above data buffer */
+ pdc_byte *pos; /* current file position in data buffer */
+ pdc_byte *limit; /* limit of file buffer in writing mode */
+};
+
+FILE *
+pdc_get_fileptr(pdc_file *sfp)
+{
+ return sfp->fp;
+}
+
+pdc_core *
+pdc_get_pdcptr(pdc_file *sfp)
+{
+ return sfp->pdc;
+}
+
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma unmanaged
+#endif
+int
+pdc_get_fopen_errnum(pdc_core *pdc, int errnum)
+{
+ int outnum = errnum, isread;
+
+ (void) pdc;
+
+ isread = (errnum == PDC_E_IO_RDOPEN);
+
+#if defined(VMS)
+ /*
+ * On the vms system, when a system error occurs which is not
+ * mapped into the unix styled errno values, errno is set EVMSERR
+ * and a VMS error code is set in vaxc$errno.
+ */
+ switch (errno)
+ {
+ case EVMSERR:
+ {
+ /* unmapped VMS runtime error - check vaxc$errno */
+ switch (vaxc$errno)
+ {
+ case 100052: /* old style RMS file specification syntax error */
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ }
+ }
+ return outnum;
+ }
+#endif /* VMS */
+
+#if defined(MVS)
+
+ switch (errno)
+ {
+ case 49:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ }
+ return outnum;
+
+#elif defined(WIN32)
+ {
+ DWORD lasterror = GetLastError();
+ switch (lasterror)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ case ERROR_INVALID_PASSWORD:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ outnum = isread ? PDC_E_IO_RDOPEN_PD : PDC_E_IO_WROPEN_PD;
+ break;
+
+ case ERROR_INVALID_NAME:
+ outnum = isread ? PDC_E_IO_RDOPEN_IS : PDC_E_IO_WROPEN_IS;
+ break;
+
+ case ERROR_PATH_NOT_FOUND:
+ case ERROR_INVALID_DRIVE:
+ case ERROR_BAD_NETPATH:
+ case ERROR_BAD_UNIT:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NP;
+ break;
+
+ case ERROR_TOO_MANY_OPEN_FILES:
+ case ERROR_SHARING_BUFFER_EXCEEDED:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+
+ case ERROR_BAD_COMMAND:
+ outnum = isread ? PDC_E_IO_RDOPEN_BC : PDC_E_IO_WROPEN_BC;
+ break;
+
+ case ERROR_FILE_EXISTS:
+ outnum = PDC_E_IO_WROPEN_AE;
+ break;
+
+ case ERROR_BUFFER_OVERFLOW:
+ outnum = PDC_E_IO_WROPEN_TL;
+ break;
+
+ case ERROR_WRITE_FAULT:
+ case ERROR_CANNOT_MAKE:
+ outnum = PDC_E_IO_WROPEN_NC;
+ break;
+
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ outnum = PDC_E_IO_WROPEN_NS;
+ break;
+
+ case ERROR_SHARING_VIOLATION:
+ outnum = isread ? PDC_E_IO_RDOPEN_SV : PDC_E_IO_WROPEN_SV;
+ break;
+
+ /* This code arises after opening a existing PDF or log file.
+ * Because the file could be opened, we can ignore this code.
+ */
+ case ERROR_ALREADY_EXISTS:
+ lasterror = 0;
+ outnum = 0;
+ break;
+ }
+
+ if (lasterror)
+ {
+ errno = (int) lasterror;
+ return outnum;
+ }
+
+ /* if lasterror == 0 we must look for errno (see .NET) */
+ }
+
+#endif /* WIN32 */
+
+ switch (errno)
+ {
+#ifdef EACCES
+ case EACCES:
+ outnum = isread ? PDC_E_IO_RDOPEN_PD : PDC_E_IO_WROPEN_PD;
+ break;
+#endif
+#ifdef EMACOSERR
+ case EMACOSERR:
+#if defined(MAC)
+
+ switch (__MacOSErrNo)
+ {
+ case fnfErr:
+ case dirNFErr:
+ case resFNotFound:
+ case afpDirNotFound:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ break;
+
+ case permErr:
+ case wrPermErr:
+ case wPrErr:
+ case afpAccessDenied:
+ case afpVolLocked:
+ outnum = isread ? PDC_E_IO_RDOPEN_PD : PDC_E_IO_WROPEN_PD;
+ break;
+
+ case nsvErr:
+ case afpObjectTypeErr:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_IS;
+ break;
+
+ case tmfoErr:
+ case afpTooManyFilesOpen:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+
+ case opWrErr:
+ outnum = PDC_E_IO_WROPEN_AE;
+ break;
+
+ case dirFulErr:
+ case dskFulErr:
+ case afpDiskFull:
+ outnum = PDC_E_IO_WROPEN_NS;
+ break;
+
+ case fLckdErr:
+ case afpLockErr:
+ outnum = isread ? PDC_E_IO_RDOPEN_SV : PDC_E_IO_WROPEN_SV;
+ break;
+
+ default:
+ break;
+ }
+
+ if (__MacOSErrNo)
+ {
+ return outnum;
+ }
+#endif
+ break;
+#endif
+#ifdef ENOENT
+ case ENOENT:
+ outnum = isread ? PDC_E_IO_RDOPEN_NF : PDC_E_IO_WROPEN_NF;
+ break;
+#endif
+#ifdef EMFILE
+ case EMFILE:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+#endif
+#ifdef ENFILE
+ case ENFILE:
+ outnum = isread ? PDC_E_IO_RDOPEN_TM : PDC_E_IO_WROPEN_TM;
+ break;
+#endif
+#ifdef EISDIR
+ case EISDIR:
+ outnum = isread ? PDC_E_IO_RDOPEN_ID : PDC_E_IO_WROPEN_ID;
+ break;
+#endif
+#ifdef EDQUOT
+ case EDQUOT:
+ outnum = isread ? PDC_E_IO_RDOPEN_QU : PDC_E_IO_WROPEN_QU;
+ break;
+#endif
+#ifdef EEXIST
+ case EEXIST:
+ outnum = PDC_E_IO_WROPEN_AE;
+ break;
+#endif
+#ifdef ENAMETOOLONG
+ case ENAMETOOLONG:
+ outnum = PDC_E_IO_WROPEN_TL;
+ break;
+#endif
+#ifdef ENOSPC
+ case ENOSPC:
+ outnum = PDC_E_IO_WROPEN_NS;
+ break;
+#endif
+ default:
+
+ /* observed on Solaris */
+ if (errno == 0)
+ pdc_error(pdc, PDC_E_INT_BADERRNO, 0, 0, 0, 0);
+
+ outnum = errnum;
+ break;
+ }
+
+ return outnum;
+}
+#if defined(_MSC_VER) && defined(_MANAGED)
+#pragma managed
+#endif
+
+void
+pdc_set_fopen_errmsg(pdc_core *pdc, int errnum, const char *qualifier,
+ const char *filename)
+{
+ const char *stemp1 = NULL;
+ const char *stemp2 = NULL;
+ int errno1 = errno;
+
+#if defined(EMACOSERR) && defined(MAC)
+ errno1 = (int) __MacOSErrNo;
+#endif
+
+ errnum = pdc_get_fopen_errnum(pdc, errnum);
+ if (errnum == PDC_E_IO_RDOPEN)
+ errnum = PDC_E_IO_RDOPEN_CODE;
+ else if (errnum == PDC_E_IO_WROPEN)
+ errnum = PDC_E_IO_WROPEN_CODE;
+ if (errnum == PDC_E_IO_RDOPEN_CODE || errnum == PDC_E_IO_WROPEN_CODE)
+ {
+ stemp1 = pdc_errprintf(pdc, "%d", errno1);
+
+#ifdef PDC_HAS_STRERROR
+ stemp2 = strerror(errno1);
+ if (stemp2 != NULL)
+ {
+ if (errnum == PDC_E_IO_RDOPEN_CODE)
+ errnum = PDC_E_IO_RDOPEN_CODETEXT;
+ else if (errnum == PDC_E_IO_WROPEN_CODE)
+ errnum = PDC_E_IO_WROPEN_CODETEXT;
+ }
+#endif
+ }
+
+ pdc_set_errmsg(pdc, errnum, qualifier, filename, stemp1, stemp2);
+}
+
+pdc_bool
+pdc_check_fopen_errmsg(pdc_core *pdc, pdc_bool requested)
+{
+ return (requested || pdc_get_errnum(pdc) != PDC_E_IO_RDOPEN_NF) ?
+ pdc_false : pdc_undef;
+}
+
+static void
+pdc_logg_openclose(pdc_core *pdc, FILE *fp, pdc_bool opened)
+{
+ int errno1 = errno, errno2 = 0;
+
+ if (pdc_logg_is_enabled(pdc, 3, trc_filesearch))
+ {
+#if defined(WIN32)
+ errno2 = (int) GetLastError();
+#elif defined(MAC)
+ errno2 = __MacOSErrNo;
+#endif
+ pdc_logg(pdc, "\t%p", fp);
+ if (opened)
+ pdc_logg(pdc, " opened");
+ else
+ pdc_logg(pdc, " closed");
+#if PDC_FILENO_EXISTS
+ if (fp != NULL && opened)
+ pdc_logg(pdc, ", fileno=%d", fileno(fp));
+#endif
+ pdc_logg(pdc, ", errno=%d", errno1);
+ if (errno2 != 0)
+ pdc_logg(pdc, ", errno2=%d", errno2);
+ pdc_logg(pdc, "\n");
+
+ /* because of logfile IO */
+ if (errno != errno1)
+ errno = errno1;
+ }
+}
+
+void *
+pdc_read_file(pdc_core *pdc, FILE *fp, pdc_off_t *o_filelen, int incore)
+{
+ static const char fn[] = "pdc_read_file";
+ pdc_off_t filelen = 0, len = 0;
+ char *content = NULL;
+
+
+#if !defined(MVS) || !defined(I370)
+
+ pdc__fseek(fp, 0, SEEK_END);
+ filelen = pdc__ftell(fp);
+ pdc__fseek(fp, 0, SEEK_SET);
+
+ if (incore && filelen)
+ {
+ content = (char *) pdc_malloc(pdc, (size_t) (filelen + 1), fn);
+ len = (pdc_off_t) pdc__fread(content, 1, (size_t) filelen, fp);
+
+/* because pdc__ftell lies! */
+filelen = len;
+ if (!filelen)
+ {
+ pdc_free(pdc, content);
+ filelen = 0;
+ content = NULL;
+ }
+ }
+
+#endif
+
+ if (content) content[filelen] = 0;
+ *o_filelen = filelen;
+ return (void *) content;
+}
+
+
+/*
+ * In the case of systems which are not capable of Unicode file names:
+ *
+ * File name can be converted to Latin-1: The incoming char pointer
+ * will be deleted and a new char pointer to the Latin-1 string will
+ * be returned. Otherwise an execption will be thrown.
+ *
+ */
+char *
+pdc_check_filename(pdc_core *pdc, char *filename)
+{
+#if !defined(PDC_UNICODE_FILENAME)
+ char *ffname = pdc_utf8_to_hostbytes(pdc, pdc->honorlang, filename);
+
+ pdc_free(pdc, filename);
+ if (ffname == NULL)
+ pdc_error(pdc, PDC_E_IO_UNSUPP_UNINAME, 0, 0, 0, 0);
+ filename = (char *) ffname;
+#endif
+
+ return filename;
+}
+
+char *
+pdc_get_filename(pdc_core *pdc, char *filename)
+{
+ char *ffname;
+
+#if defined(PDC_UNICODE_FILENAME)
+ static const char fn[] = "pdc_get_filename";
+
+ ffname = pdc_strdup_ext(pdc, filename, 0, fn);
+#else
+ ffname = pdc_hostbytes_to_utf8(pdc, pdc->honorlang, filename);
+#endif
+
+ return ffname;
+}
+
+/*
+ * pdc_convert_filename_ext converts a file name as string of name type
+ * (see function pdc_convert_name) to a [EBCDIC-]UTF-8 string with or
+ * without a BOM. If the compiler doesn't allow Unicode filenames
+ * (see define PDC_UNICODE_FILENAME) the filename is Latin-1 encoded
+ * if possible or an exception will be thrown.
+ *
+ */
+const char *
+pdc_convert_filename_ext(pdc_core *pdc, const char *filename, int len,
+ const char *paramname, pdc_encoding enc, int codepage,
+ int flags)
+{
+ char *fname = NULL;
+ const char *outfilename = NULL;
+ int i = 0;
+
+ if (filename == NULL)
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, paramname, 0, 0, 0);
+
+ fname = pdc_convert_name_ext(pdc, filename, len, enc, codepage, flags);
+
+ if (fname == NULL || *fname == '\0')
+ pdc_error(pdc, PDC_E_ILLARG_EMPTY, paramname, 0, 0, 0);
+
+ if (pdc_is_utf8_bytecode(fname))
+ {
+#if defined(PDC_UNICODE_FILENAME)
+ i = 3;
+#else
+ fname = pdc_check_filename(pdc, fname);
+#endif
+ }
+
+ outfilename = pdc_errprintf(pdc, "%s", &fname[i]);
+ pdc_free(pdc, fname);
+
+ return outfilename;
+}
+
+const char *
+pdc_convert_filename(pdc_core *pdc, const char *filename, int len,
+ const char *paramname, pdc_bool withbom)
+{
+ int flags = PDC_CONV_EBCDIC;
+
+ if (withbom)
+ flags |= PDC_CONV_WITHBOM;
+
+ return pdc_convert_filename_ext(pdc, filename, len, paramname,
+ pdc_invalidenc, 0, flags);
+}
+
+/*
+ * pdc_fopen_logg opens a file. The function expects a UTF-8 encoded file name.
+ * (see function pdc_convert_filename), if define PDC_UNICODE_FILENAME is set.
+ *
+ */
+FILE *
+pdc_fopen_logg(pdc_core *pdc, const char *filename, const char *mode)
+{
+ FILE *fp = NULL;
+
+#if defined(PDC_UNICODE_FILENAME)
+
+ pdc_byte *outfilename = NULL;
+ pdc_text_format nameformat = PDC_UTF8;
+ pdc_text_format targetnameformat = pdc_utf16;
+ int len = (int) strlen(filename);
+ int outlen = 0;
+
+ /* convert filename from UTF-8 to UTF-16 or Latin-1 */
+ pdc_convert_string(pdc, nameformat, 0, NULL, (pdc_byte *) filename, len,
+ &targetnameformat, NULL, &outfilename, &outlen,
+ PDC_CONV_TRYBYTES | PDC_CONV_NOBOM, pdc_true);
+
+ if (targetnameformat == pdc_bytes)
+ {
+ fp = fopen((const char *) outfilename, mode);
+ }
+ else
+ {
+ wchar_t wmode[8];
+ int i;
+
+ len = (int) strlen(mode);
+ for (i = 0; i < len; i++)
+ wmode[i] = (wchar_t) mode[i];
+ wmode[len] = 0;
+
+ fp = _wfopen((wchar_t *) outfilename, wmode);
+ }
+
+ pdc_free(pdc, outfilename);
+
+#else
+ (void) pdc;
+
+ fp = fopen(filename, mode);
+#endif
+
+ pdc_logg_openclose(pdc, fp, pdc_true);
+
+ return fp;
+}
+
+pdc_file *
+pdc_fopen(pdc_core *pdc, const char *filename, const char *qualifier,
+ const pdc_byte *data, size_t size, int flags)
+{
+ static const char fn[] = "pdc_fopen";
+ pdc_file *sfp;
+
+ sfp = (pdc_file *) pdc_calloc(pdc, sizeof(pdc_file), fn);
+
+ /* initialize */
+ sfp->pdc = pdc;
+ sfp->filename = pdc_strdup_ext(pdc, filename, 0, fn);
+
+ if (flags & PDC_FILE_WRITEMODE || flags & PDC_FILE_APPENDMODE)
+ sfp->wrmode = pdc_true;
+
+
+ if (data != NULL || size > 0)
+ {
+ /* virtual file */
+ if (sfp->wrmode)
+ {
+ sfp->data = (pdc_byte *) pdc_calloc(pdc, size, fn);
+ if (data != NULL)
+ {
+ /* append mode */
+ memcpy(sfp->data, data, size);
+ sfp->pos = sfp->data + size;
+ }
+ else
+ {
+ sfp->pos = sfp->data;
+ }
+ sfp->end = sfp->pos;
+ sfp->limit = sfp->data + size;
+ }
+ else
+ {
+ sfp->data = (pdc_byte *) data;
+ sfp->pos = sfp->data;
+ sfp->end = sfp->data + size;
+ }
+ }
+ else
+ {
+ const char *mode;
+
+
+ /* disk file */
+ if (flags & PDC_FILE_BINARY)
+ mode = READBMODE;
+ else
+ mode = READTMODE;
+ if (flags & PDC_FILE_APPENDMODE)
+ mode = APPENDMODE;
+ else if (flags & PDC_FILE_WRITEMODE)
+ mode = WRITEMODE;
+
+ sfp->fp = pdc_fopen_logg(pdc, filename, mode);
+ if (sfp->fp == NULL)
+ {
+ pdc_fclose(sfp);
+
+ if (qualifier == NULL)
+ qualifier = "";
+ pdc_set_fopen_errmsg(pdc, PDC_E_IO_RDOPEN, qualifier, filename);
+ return NULL;
+ }
+ }
+
+ return sfp;
+}
+
+pdc_bool
+pdc_file_isvirtual(pdc_file *sfp)
+{
+ return sfp->fp ? pdc_false : pdc_true;
+}
+
+char *
+pdc_file_name(pdc_file *sfp)
+{
+ return sfp->filename;
+}
+
+pdc_core *
+pdc_file_getpdc(pdc_file *sfp)
+{
+ return sfp->pdc;
+}
+
+pdc_off_t
+pdc_file_size(pdc_file *sfp)
+{
+ pdc_off_t filelen;
+
+ if (sfp->fp)
+ {
+ pdc_off_t pos = pdc__ftell(sfp->fp);
+
+ pdc_read_file(sfp->pdc, sfp->fp, &filelen, 0);
+ pdc__fseek(sfp->fp, pos, SEEK_SET);
+ }
+ else
+ filelen = (pdc_off_t) (sfp->end - sfp->data);
+
+ return filelen;
+}
+
+const void *
+pdc_freadall(pdc_file *sfp, size_t *filelen, pdc_bool *ismem)
+{
+ const void *result = NULL;
+
+ *filelen = 0;
+
+ pdc_logg_cond(sfp->pdc, 1, trc_filesearch,
+ "\tAttempting to read whole file \"%s\"\n", sfp->filename);
+
+ if (sfp->fp)
+ {
+ pdc_off_t flen; /* TODO2GB: >2GB on 32-bit platforms? */
+
+ result = pdc_read_file(sfp->pdc, sfp->fp, &flen, 1);
+
+ if (ismem)
+ *ismem = pdc_false;
+ *filelen = (size_t) flen;
+ }
+ else
+ {
+ result = sfp->data;
+
+ if (ismem)
+ *ismem = pdc_true;
+ *filelen = (size_t) (sfp->end - sfp->data);
+ }
+
+ pdc_logg_cond(sfp->pdc, 1, trc_filesearch,
+ "\t%d bytes read from %s file, contents=%p\n",
+ (int) (*filelen),
+ (sfp->fp) ? "disk" : "memory",
+ result);
+
+ return result;
+}
+
+static int
+pdc_fgetc_e(pdc_file *sfp)
+{
+ int c = pdc_fgetc(sfp);
+ return c;
+}
+
+char *
+pdc_fgetline(char *s, int size, pdc_file *sfp)
+{
+ int i, c;
+
+ c = pdc_fgetc_e(sfp);
+ if (c == EOF)
+ return NULL;
+
+ size--;
+ for (i = 0; i < size; i++)
+ {
+ if (c == '\n' || c == '\r' || c == EOF) break;
+ s[i] = (char) c;
+ c = pdc_fgetc_e(sfp);
+ }
+ s[i] = 0;
+
+ /* Skip windows line end \r\n */
+ if (c == '\r')
+ {
+ c = pdc_fgetc_e(sfp);
+
+ if (c != '\n' && c != EOF)
+ {
+ if (sfp->fp)
+ ungetc(c, sfp->fp);
+ else
+ pdc_fseek(sfp, -1, SEEK_CUR);
+ }
+ }
+ return s;
+}
+
+/*
+ * Emulation of C file functions - relevant for PDFlib
+ */
+
+pdc_off_t
+pdc_ftell(pdc_file *sfp)
+{
+ if (sfp->fp)
+ return pdc__ftell(sfp->fp);
+
+ return (pdc_off_t) (sfp->pos - sfp->data);
+}
+
+int
+pdc_fseek(pdc_file *sfp, pdc_off_t offset, int whence)
+{
+ static const char fn[] = "pdc_fseek";
+
+ if (sfp->fp)
+ return pdc__fseek(sfp->fp, offset, whence);
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ sfp->pos = sfp->data + offset;
+ break;
+
+ case SEEK_CUR:
+ sfp->pos += offset;
+ break;
+
+ case SEEK_END:
+ sfp->pos = sfp->end;
+ break;
+ }
+
+ if (sfp->pos > sfp->end)
+ {
+ /* extend file in writing mode */
+ if (sfp->wrmode)
+ {
+ size_t nbytes = (size_t) (sfp->pos - sfp->end);
+
+ if (sfp->pos > sfp->limit)
+ {
+ size_t size = (size_t) (sfp->pos - sfp->data);
+
+ sfp->data = (pdc_byte *) pdc_realloc(sfp->pdc, sfp->data, size,
+ fn);
+ sfp->end = sfp->data + size;
+ sfp->pos = sfp->end;
+ sfp->limit = sfp->end;
+ }
+
+ memset(sfp->pos - nbytes, 0, nbytes);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else if (sfp->pos < sfp->data)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+size_t
+pdc_fread(void *ptr, size_t size, size_t nmemb, pdc_file *sfp)
+{
+ size_t nbytes = 0;
+
+ if (sfp->fp)
+ return pdc__fread(ptr, size, nmemb, sfp->fp);
+
+ nbytes = size * nmemb;
+ if (sfp->pos + nbytes > sfp->end)
+ {
+ nbytes = (size_t) (sfp->end - sfp->pos);
+ nmemb = nbytes / size;
+ nbytes = nmemb *size;
+ }
+
+ if (nbytes)
+ memcpy(ptr, sfp->pos, nbytes);
+ sfp->pos += nbytes;
+
+ return nmemb;
+}
+
+size_t
+pdc_fwrite(const void *ptr, size_t size, size_t nmemb, pdc_file *sfp)
+{
+ static const char fn[] = "pdc_fwrite";
+
+ if (sfp->wrmode)
+ {
+ size_t poslen, nbytes = 0;
+
+ if (sfp->fp)
+ return pdc__fwrite(ptr, size, nmemb, sfp->fp);
+
+ nbytes = size * nmemb;
+ if (sfp->pos + nbytes > sfp->limit)
+ {
+ poslen = (size_t) (sfp->pos - sfp->data);
+ size = poslen + nbytes;
+
+ sfp->data = (pdc_byte *) pdc_realloc(sfp->pdc, sfp->data, size, fn);
+ sfp->pos = sfp->data + poslen;
+ sfp->end = sfp->data + size;
+ sfp->limit = sfp->end;
+ }
+ memcpy(sfp->pos, ptr, nbytes);
+ sfp->pos += nbytes;
+ if (sfp->pos > sfp->end)
+ sfp->end = sfp->pos;
+ }
+ else
+ {
+ nmemb = 0;
+ }
+
+ return nmemb;
+}
+
+void
+pdc_freset(pdc_file *sfp, size_t size)
+{
+ static const char fn[] = "pdc_freset";
+
+ if (sfp->wrmode && !sfp->fp)
+ {
+ if (size > (size_t) (sfp->limit - sfp->data))
+ {
+ sfp->data = (pdc_byte *) pdc_realloc(sfp->pdc, sfp->data, size, fn);
+ sfp->limit = sfp->data + size;
+ }
+
+ sfp->pos = sfp->data;
+ sfp->end = sfp->data;
+ }
+}
+
+int
+pdc_fgetc(pdc_file *sfp)
+{
+ int ch = 0;
+
+ if (sfp->fp)
+ return pdc__fgetc(sfp->fp);
+
+ if (sfp->pos < sfp->end)
+ {
+ ch = (int) *sfp->pos;
+ sfp->pos++;
+ }
+ else
+ {
+ ch = EOF;
+ }
+
+ return ch;
+}
+
+int
+pdc_feof(pdc_file *sfp)
+{
+ if (sfp->fp)
+ return pdc__feof(sfp->fp);
+
+ return (sfp->pos >= sfp->end) ? 1 : 0;
+}
+
+void
+pdc_fclose_logg(pdc_core *pdc, FILE *fp)
+{
+ fclose(fp);
+ pdc_logg_openclose(pdc, fp, pdc_false);
+}
+
+void
+pdc_fclose(pdc_file *sfp)
+{
+ if (sfp)
+ {
+ if (sfp->fp)
+ {
+ pdc_fclose_logg(sfp->pdc, sfp->fp);
+ sfp->fp = NULL;
+ }
+ else if (sfp->wrmode)
+ {
+ if (sfp->data)
+ {
+ pdc_free(sfp->pdc, sfp->data);
+ sfp->data = NULL;
+ }
+ }
+
+ if (sfp->filename)
+ {
+ pdc_free(sfp->pdc, sfp->filename);
+ sfp->filename = NULL;
+ }
+
+ pdc_free(sfp->pdc, sfp);
+ }
+}
+
+/*
+ * Concatenating a directory name with a file base name to a full valid
+ * file name. On MVS platforms an extension at the end of basename
+ * will be discarded.
+ */
+void
+pdc_file_fullname(const char *dirname, const char *basename, char *fullname)
+{
+ const char *pathsep = PDC_PATHSEP;
+
+#ifdef MVS
+ pdc_bool lastterm = pdc_false;
+#endif
+
+ if (!dirname || !dirname[0])
+ {
+ strcpy(fullname, basename);
+ }
+ else
+ {
+ fullname[0] = 0;
+
+#ifdef MVS
+ if (strncmp(dirname, PDC_FILEQUOT, 1))
+ strcat(fullname, PDC_FILEQUOT);
+#endif
+
+ strcat(fullname, dirname);
+
+#ifdef VMS
+ /* look for logical name or whose result */
+ if(getenv(dirname))
+ pathsep = PDC_PATHSEP_LOG;
+ else if (fullname[strlen(fullname)-1] == ']')
+ pathsep = "";
+#endif
+
+ strcat(fullname, pathsep);
+ strcat(fullname, basename);
+
+#ifdef MVS
+ lastterm = pdc_true;
+#endif
+ }
+
+#ifdef MVS
+ {
+ int ie, len;
+
+ len = strlen(fullname);
+ for (ie = len - 1; ie >= 0; ie--)
+ {
+ if (fullname[ie] == pathsep[0])
+ break;
+
+ if (fullname[ie] == '.')
+ {
+ fullname[ie] = 0;
+ break;
+ }
+ }
+ if (lastterm)
+ {
+ strcat(fullname, PDC_PATHTERM);
+ strcat(fullname, PDC_FILEQUOT);
+ }
+ }
+#endif
+}
+
+#define EXTRA_SPACE 32 /* extra space for separators, FILEQUOT etc. */
+
+char *
+pdc_file_fullname_mem(pdc_core *pdc, const char *dirname, const char *basename)
+{
+ static const char fn[] = "pdc_file_fullname_mem";
+ char *fullname;
+ size_t len;
+
+ len = strlen(basename);
+ if (dirname && dirname[0])
+ len += strlen(dirname);
+ len += EXTRA_SPACE;
+ fullname = (char *) pdc_malloc(pdc, len, fn);
+
+ pdc_file_fullname(dirname, basename, fullname);
+
+ return fullname;
+}
+
+/*
+ * Returns the full specified path name in a new memory.
+ * The full path name can be concatened by a path name,
+ * file name and extension (incl. dot).
+ */
+char *
+pdc_file_concat(pdc_core *pdc, const char *dirname, const char *basename,
+ const char *extension)
+{
+ static const char fn[] = "pdc_file_concat";
+ char *pathname = pdc_file_fullname_mem(pdc, dirname, basename);
+ size_t len = strlen(pathname) + 1;
+
+ if (extension != NULL)
+ len += strlen(extension);
+
+ pathname = (char *) pdc_realloc(pdc, pathname, len, fn);
+
+ if (extension != NULL)
+ strcat(pathname, extension);
+
+ return pathname;
+}
+
+/*
+ * Returns the file basename of a full specified path name in the same memory.
+ */
+const char *
+pdc_file_strip_dirs(const char *pathname)
+{
+ const char *scan = pathname + strlen(pathname);
+ char charsep = PDC_PATHSEP[0];
+
+ while (pathname <= --scan)
+ {
+ if (*scan == charsep)
+ return scan + 1;
+ }
+
+ return pathname;
+}
+
+
+/*
+ * Returns the file path of a full specified path name in the same memory.
+ */
+char *
+pdc_file_strip_name(char *pathname)
+{
+ char *scan = pathname + strlen(pathname);
+ char charsep = PDC_PATHSEP[0];
+
+ while (pathname <= --scan)
+ {
+ if (*scan == charsep)
+ {
+ *scan = 0;
+ break;
+ }
+ }
+
+ return pathname;
+}
+
+
+/*
+ * Returns the file extension of a path name in the same memory.
+ */
+char *
+pdc_file_strip_ext(char *pathname)
+{
+ char *scan = pathname + strlen(pathname);
+
+ while (pathname <= --scan)
+ {
+ if (*scan == '.')
+ {
+ *scan = 0;
+ break;
+ }
+ }
+
+ return pathname;
+}
+
+
+/*
+ * Function reads a text file and creates a string list
+ * of all no-empty and no-comment lines. The strings are stripped
+ * by leading and trailing white space characters.
+ *
+ * The caller is responsible for freeing the resultated string list
+ * by calling the function pdc_cleanup_stringlist.
+ *
+ * Not for unicode strings.
+ *
+ * Return value: Number of strings
+ */
+
+#define PDC_ARGV_CHUNKSIZE 256
+
+int
+pdc_read_textfile(pdc_core *pdc, pdc_file *sfp, int flags, char ***linelist)
+{
+ static const char fn[] = "pdc_read_textfile";
+ char buf[PDC_BUFSIZE];
+ char *content = NULL;
+ char **strlist = NULL;
+ int nlines = 0;
+ pdc_off_t filelen;
+ size_t len = 0, sumlen = 0, maxl = 0;
+ pdc_bool tocont = pdc_false;
+ int i, nbs, is = -1;
+
+ /* get file length */
+ filelen = pdc_file_size(sfp);
+ if (filelen)
+ {
+ /* allocate content array */
+ content = (char *) pdc_calloc(pdc, (size_t) filelen, fn);
+
+ /* read loop */
+ while (pdc_fgetline(buf, PDC_BUFSIZE, sfp) != NULL)
+ {
+ /* trim white spaces */
+ if (tocont)
+ pdc_strtrim(buf);
+ else
+ pdc_str2trim(buf);
+
+ /* skip blank and comment lines */
+ if (buf[0] == 0 || buf[0] == '%')
+ {
+ tocont = pdc_false;
+ continue;
+ }
+
+ /* register new line */
+ if (!tocont)
+ {
+ if (nlines)
+ pdc_logg_cond(pdc, 2, trc_filesearch,
+ "\t\tLine %d; \"%s\"\n", nlines, strlist[nlines - 1]);
+
+ if (nlines >= (int) maxl)
+ {
+ maxl += PDC_ARGV_CHUNKSIZE;
+ strlist = (strlist == NULL) ?
+ (char **)pdc_malloc(pdc, maxl * sizeof(char *), fn):
+ (char **)pdc_realloc(pdc, strlist, maxl *
+ sizeof(char *), fn);
+ }
+
+ is += sumlen + 1;
+ strlist[nlines] = &content[is];
+ nlines++;
+ sumlen = 0;
+ }
+
+ /* process new line */
+ nbs = 0;
+ len = strlen(buf);
+ for (i = 0; i < (int) len; i++)
+ {
+ /* backslash found */
+ if (buf[i] == '\\')
+ {
+ nbs++;
+ }
+ else
+ {
+ /* comment sign found */
+ if (buf[i] == '%')
+ {
+ if (nbs % 2)
+ {
+ /* masked */
+ memmove(&buf[i-1], &buf[i], (size_t) (len-i));
+ len--;
+ buf[len] = 0;
+ }
+ else
+ {
+ buf[i] = 0;
+ len = strlen(buf);
+ }
+ }
+ nbs = 0;
+ }
+ }
+
+ /* continuation line */
+ tocont = (nbs % 2) ? pdc_true : pdc_false;
+ if (tocont)
+ {
+ if (flags & PDC_FILE_KEEPLF)
+ buf[len - 1] = '\n';
+ else
+ len--;
+ }
+ buf[len] = '\0';
+
+ /* backslash substitution */
+ if (flags & PDC_FILE_BSSUBST)
+ {
+ len = (size_t) pdc_subst_backslash(pdc, (pdc_byte *) buf,
+ (int) len, NULL, pdc_bytes, pdc_true);
+ }
+
+ /* concatenate line */
+ strcat(&content[is], buf);
+
+ sumlen += len;
+ }
+
+ if (!strlist) pdc_free(pdc, content);
+ }
+
+ if (nlines)
+ pdc_logg_cond(pdc, 2, trc_filesearch,
+ "\t\tLine %d; \"%s\"\n", nlines, strlist[nlines - 1]);
+
+ *linelist = strlist;
+ return nlines;
+}
+
+
+/* generate a temporary file name from the current time, pid, 'dirname',
+** and the data in 'inbuf' using MD5. prepend 'dirname' to the file name.
+** the result is written to 'outbuf'. if 'outbuf' is NULL, memory will be
+** allocated and must be freed by the caller. otherwise, 'pdc' can be set
+** to NULL.
+**
+** if 'dirname' isn't specified the function looks for an environment
+** variable via the define PDC_TMPDIR_ENV. This define is set in
+** pc_config.h. If the environment variable has a value and if the
+** directory exists (check with the temporary file together) the
+** directory will be used.
+*/
+
+#ifdef MVS
+#define TMP_NAME_LEN 9
+#define TMP_SUFFIX ""
+#define TMP_SUFF_LEN 0
+#else
+#define TMP_NAME_LEN 14
+#define TMP_SUFFIX ".TMP"
+#define TMP_SUFF_LEN 4
+#endif
+
+char *
+pdc_temppath(
+ pdc_core *pdc,
+ char *outbuf,
+ const char *inbuf,
+ size_t inlen,
+ const char *dirname)
+{
+ char name[TMP_NAME_LEN + TMP_SUFF_LEN + 1];
+ MD5_CTX md5;
+ time_t timer;
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ int i;
+ size_t dirlen;
+#ifdef VMS
+ char *tmpdir = NULL;
+#endif /* VMS */
+
+#if defined(WIN32)
+#if defined(__BORLANDC__)
+ int pid = getpid();
+#else
+ int pid = _getpid();
+#endif
+#else
+#if !defined(MAC)
+ pid_t pid = getpid();
+#endif
+#endif
+
+#ifdef PDC_TMPDIR_ENV
+ if (!dirname)
+ {
+ dirname = (char *) getenv(PDC_TMPDIR_ENV);
+ }
+#endif /* !PDC_TMPDIR_ENV */
+
+ time(&timer);
+
+ MD5_Init(&md5);
+#if !defined(MAC)
+ MD5_Update(&md5, (unsigned char *) &pid, sizeof pid);
+#endif
+ MD5_Update(&md5, (unsigned char *) &timer, sizeof timer);
+
+ if (inlen == 0 && inbuf != (const char *) 0)
+ inlen = strlen(inbuf);
+
+ if (inlen != 0)
+ MD5_Update(&md5, (unsigned char *) inbuf, inlen);
+
+ dirlen = dirname ? strlen(dirname) : 0;
+ if (dirlen)
+ MD5_Update(&md5, (const unsigned char *) dirname, dirlen);
+
+ MD5_Final(digest, &md5);
+
+ for (i = 0; i < TMP_NAME_LEN - 1; ++i)
+ name[i] = (char) (PDF_A + digest[i % MD5_DIGEST_LENGTH] % 26);
+
+ name[i] = 0;
+ strcat(name, TMP_SUFFIX);
+
+ if (!outbuf)
+ outbuf = pdc_file_fullname_mem(pdc, dirname, name);
+ else
+ pdc_file_fullname(dirname, name, outbuf);
+ return outbuf;
+}
+
+/* Write function depending on pdc->asciifile.
+ */
+size_t
+pdc_fwrite_ascii(pdc_core *pdc, const char *str, size_t len, FILE *fp)
+{
+
+ (void) pdc;
+ len = fwrite(str, 1, len, fp);
+
+
+ return len;
+}
+
+/* Creates a file depending on PDC_FILE_ASCII and pdc->asciifile.
+*/
+size_t
+pdc_write_file(
+ pdc_core *pdc,
+ const char *filename,
+ const char *qualifier,
+ const char *content,
+ size_t len,
+ int flags)
+{
+ size_t wlen = 0;
+ pdc_file *sfp;
+
+
+ sfp = pdc_fopen(pdc, filename, qualifier, NULL, 0, flags);
+ if (sfp != NULL)
+ {
+ wlen = pdc_fwrite_ascii(pdc, content, len, sfp->fp);
+ pdc_fclose(sfp);
+ if (wlen != len)
+ {
+ pdc_set_errmsg(pdc, PDC_E_IO_WRITE, filename, 0, 0, 0);
+ }
+ }
+
+
+ return wlen;
+}
+
+
+
+#if defined(MAC) || defined(MACOSX)
+
+#ifdef PDF_TARGET_API_MAC_CARBON
+
+/* Construct an FSSpec from a Posix path name. Only required for
+ * Carbon (host font support and file type/creator).
+ */
+
+OSStatus
+FSPathMakeFSSpec(const UInt8 *path, FSSpec *spec)
+{
+ OSStatus result;
+ FSRef ref;
+
+ /* convert the POSIX path to an FSRef */
+ result = FSPathMakeRef(path, &ref, NULL);
+
+ if (result != noErr)
+ return result;
+
+ /* and then convert the FSRef to an FSSpec */
+ result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+
+ return result;
+}
+
+
+#else
+
+
+#endif /* !PDF_TARGET_API_MAC_CARBON */
+
+#endif /* (defined(MAC) || defined(MACOSX)) */
+