campo-sirio/pdf/pdcore/pc_file.c
guy 3bf951f42c Patch level : 10.0
Files correlati     : pdflib
Ricompilazione Demo : [ ]
Commento            :
Aggiornata pdflib.dll alla versione 7.0.4


git-svn-id: svn://10.65.10.50/trunk@18580 c028cbd2-c16b-5b4b-a496-9718f37d4682
2009-03-23 08:55:58 +00:00

1677 lines
38 KiB
C
Executable File

/*---------------------------------------------------------------------------*
| 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.4 2009-03-23 08:51:17 guy 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>
#define PDC_FILENO _fileno
#else
#define PDC_FILENO fileno
#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
#if defined(WIN32) && !defined(__BORLANDC__)
#define PDC_MAXFILEHANDLES 2048
/* set a new maximum for the number of simultaneously open files.
* if return = -1 error occured
*/
int
pdc_set_maxfilehandles(pdc_core *pdc, int maxfps)
{
const char *stemp = pdc_errprintf(pdc, "%d", maxfps);
if (maxfps < _IOB_ENTRIES)
pdc_error(pdc, PDC_E_IO_TOOFEW_REQFILEHDLS, stemp,
pdc_errprintf(pdc, "%d", _IOB_ENTRIES), 0, 0);
if (maxfps > PDC_MAXFILEHANDLES)
pdc_error(pdc, PDC_E_IO_TOOMANY_REQFILEHDLS, stemp,
pdc_errprintf(pdc, "%d", PDC_MAXFILEHANDLES), 0, 0);
return _setmaxstdio(maxfps);
}
int
pdc_get_maxfilehandles(void)
{
return _getmaxstdio();
}
#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(PDC_FILENO(fp));
_lseeki64(PDC_FILENO(fp), 0, SEEK_END);
len = _telli64(PDC_FILENO(fp));
_lseeki64(PDC_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
}
/* we had troubles writing a block of 80 MB via network on a windows platform.
** this could be fixed by breaking down the entire block into 1 MB pieces.
*/
#undef PDC_BLOCKSIZE
#define PDC_BLOCKSIZE 1048576
size_t
pdc__fread(void *ptr, size_t size, size_t nmemb, FILE *fp)
{
char * cp = (char *) ptr;
size_t total = size * nmemb;
size_t left = total;
size_t n, r;
do
{
n = (left < PDC_BLOCKSIZE) ? left : PDC_BLOCKSIZE;
r = fread(cp, 1, n, fp);
left -= r;
cp += r;
} while (r == n && left != 0);
return total - left;
}
size_t
pdc__fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)
{
const char *cp = (const char *) ptr;
size_t total = size * nmemb;
size_t left = total;
size_t n, r;
do
{
n = (left < PDC_BLOCKSIZE) ? left : PDC_BLOCKSIZE;
r = fwrite(cp, 1, n, fp);
left -= r;
cp += r;
} while (r == n && left != 0);
return total - left;
}
#undef PDC_BLOCKSIZE
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) && defined(PDF_ALLOW_MAC_DEPR_FUNCS)
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;
}
#else
outnum = errnum;
break;
#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 because of thread unsafe errno */
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)
#if defined(MAC) && defined(PDF_ALLOW_MAC_DEPR_FUNCS)
errno1 = (int) __MacOSErrNo;
#endif
#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);
}
void
pdc_set_fwrite_errmsg(pdc_core *pdc, const char *filename)
{
const char *stemp1 = NULL;
const char *stemp2 = NULL;
int errno1 = errno;
int errnum = PDC_E_IO_WRITE;
#if defined(EMACOSERR)
#if defined(MAC) && defined(PDF_ALLOW_MAC_DEPR_FUNCS)
errno1 = (int) __MacOSErrNo;
#endif
#endif
stemp1 = pdc_errprintf(pdc, "%d", errno1);
#ifdef PDC_HAS_STRERROR
stemp2 = strerror(errno1);
if (stemp2 != NULL)
errnum = PDC_E_IO_WRITE_CODETEXT;
#endif
pdc_set_errmsg(pdc, errnum, filename, stemp1, stemp2, 0);
}
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) && defined(PDF_ALLOW_MAC_DEPR_FUNCS)
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", PDC_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.
*
* Returned string is temporary allocated.
*/
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_tmp(pdc, filename);
if (ffname == NULL)
pdc_error(pdc, PDC_E_IO_UNSUPP_UNINAME, 0, 0, 0, 0);
filename = (char *) ffname;
#endif
return filename;
}
/*
* Returned string is temporary allocated.
*/
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, PDC_CONV_TMPALLOC, 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_ext) 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.
*
* Returned string is temporary allocated.
*
*/
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);
/* temporary allocation will be enforced */
flags |= PDC_CONV_TMPALLOC;
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 = &fname[i];
return outfilename;
}
/*
* Returned string is temporary allocated.
*/
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;
int i = 0;
#if defined(PDC_UNICODE_FILENAME)
pdc_byte *outfilename = NULL;
pdc_text_format nameformat = PDC_UTF8;
pdc_text_format targetnameformat = pdc_utf16;
int len = (int) pdc_strlen(filename);
int outlen = 0;
if (pdc_is_utf16be_unicode(filename))
nameformat = pdc_utf16be;
/* convert filename from UTF-8 / UTF-16BE 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];
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;
/* due to honorlang, codeset of LANG: UTF-8 */
if (pdc_is_utf8_bytecode(filename))
i = 3;
fp = fopen(&filename[i], 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;
/* reset error number */
pdc_set_errmsg(pdc, 0, 0, 0, 0, 0);
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;
}
char *
pdc_fgetline(char *s, int size, pdc_file *sfp)
{
int i, c;
c = pdc_fgetc(sfp);
if (c == EOF)
return NULL;
size--;
for (i = 0; i < size; i++)
{
if (c == '\n' || c == '\r')
break;
s[i] = (char) c;
c = pdc_fgetc(sfp);
if (c == EOF)
{
i++;
break;
}
}
s[i] = 0;
/* Skip windows line end \r\n */
if (c == '\r')
{
c = pdc_fgetc(sfp);
if (c != EOF)
{
if (c != '\n')
{
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)
{
size_t total = pdc__fwrite(ptr, size, nmemb, sfp->fp);
if (total < size * nmemb)
{
pdc_set_fwrite_errmsg(sfp->pdc, sfp->filename);
PDC_RETHROW(sfp->pdc);
}
return total;
}
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 of maximal length PDC_FILENAMELEN - 1.
*
* On MVS platforms an extension at the end of basename will be discarded.
*/
void
pdc_file_fullname(pdc_core *pdc, const char *dirname, const char *basename,
char *fullname)
{
const char *pathsep = PDC_PATHSEP;
const char *stemp = NULL;
size_t len = 0;
#ifdef MVS
pdc_bool lastterm = pdc_false;
#endif
if (!dirname || !dirname[0])
{
len += strlen(basename);
if (len >= PDC_FILENAMELEN)
goto PDC_FILE_ERROR;
strcpy(fullname, basename);
}
else
{
fullname[0] = 0;
#ifdef MVS
if (strncmp(dirname, PDC_FILEQUOT, 1))
strcat(fullname, PDC_FILEQUOT);
#endif
len += strlen(dirname);
if (len >= PDC_FILENAMELEN)
goto PDC_FILE_ERROR;
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
len += strlen(pathsep) + strlen(basename);
if (len >= PDC_FILENAMELEN)
goto PDC_FILE_ERROR;
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)
{
len += strlen(PDC_PATHTERM) + strlen(PDC_FILEQUOT);
if (len >= PDC_FILENAMELEN)
goto PDC_FILE_ERROR;
strcat(fullname, PDC_PATHTERM);
strcat(fullname, PDC_FILEQUOT);
}
}
#endif
return;
PDC_FILE_ERROR:
if (!dirname || !dirname[0])
stemp = pdc_errprintf(pdc, "%s", basename);
else
stemp = pdc_errprintf(pdc, "%s%s%s", dirname, pathsep, basename);
pdc_error(pdc, PDC_E_IO_TOOLONG_FULLNAME, stemp, 0, 0, 0);
}
#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(pdc, 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);
while (pathname <= --scan)
{
if (*scan == PDC_PATHSEP[0] || *scan == PDC_PATHSEP_ALT[0])
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);
while (pathname <= --scan)
{
if (*scan == PDC_PATHSEP[0] || *scan == PDC_PATHSEP_ALT[0])
{
*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(pdc, 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 = pdc__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);
if (wlen < len)
{
pdc_set_fwrite_errmsg(pdc, filename);
PDC_RETHROW(pdc);
}
pdc_fclose(sfp);
}
return wlen;
}