From 7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf Mon Sep 17 00:00:00 2001 From: scuri Date: Fri, 17 Oct 2008 06:10:33 +0000 Subject: First commit - moving from LuaForge to SourceForge --- src/pdflib/pdcore/pc_file.c | 1548 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1548 insertions(+) create mode 100644 src/pdflib/pdcore/pc_file.c (limited to 'src/pdflib/pdcore/pc_file.c') 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 + +#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 +#include +#include +#else +#if defined(MAC) +#include +#else +#include +#include +#endif +#endif + +#ifndef WINCE +#include +#else +#include +#endif + +#ifdef VMS +#include +#include +#include +#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)) */ + -- cgit v1.2.3