mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
1456 lines
45 KiB
C++
1456 lines
45 KiB
C++
/*********** File AM Zip C++ Program Source Code File (.CPP) ***********/
|
|
/* PROGRAM NAME: FILAMZIP */
|
|
/* ------------- */
|
|
/* Version 1.4 */
|
|
/* */
|
|
/* COPYRIGHT: */
|
|
/* ---------- */
|
|
/* (C) Copyright to the author Olivier BERTRAND 2016-2020 */
|
|
/* */
|
|
/* WHAT THIS PROGRAM DOES: */
|
|
/* ----------------------- */
|
|
/* This program are the ZIP file access method classes. */
|
|
/* */
|
|
/***********************************************************************/
|
|
|
|
/***********************************************************************/
|
|
/* Include relevant sections of the System header files. */
|
|
/***********************************************************************/
|
|
#include "my_global.h"
|
|
#if !defined(_WIN32)
|
|
#if defined(UNIX)
|
|
#include <fnmatch.h>
|
|
#include <errno.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
#else // !UNIX
|
|
#include <io.h>
|
|
#endif // !UNIX
|
|
#include <fcntl.h>
|
|
#endif // !_WIN32
|
|
#include <time.h>
|
|
#include <m_string.h>
|
|
|
|
/***********************************************************************/
|
|
/* Include application header files: */
|
|
/* global.h is header containing all global declarations. */
|
|
/* plgdbsem.h is header containing the DB application declarations. */
|
|
/***********************************************************************/
|
|
#include "global.h"
|
|
#include "plgdbsem.h"
|
|
#include "osutil.h"
|
|
#include "filamtxt.h"
|
|
#include "tabfmt.h"
|
|
//#include "tabzip.h"
|
|
#include "filamzip.h"
|
|
|
|
#define WRITEBUFFERSIZE (16384)
|
|
|
|
/****************************************************************************/
|
|
/* Definitions used for DBF tables. */
|
|
/****************************************************************************/
|
|
#define HEADLEN 32 /* sizeof ( mainhead or thisfield ) */
|
|
//efine MEMOLEN 10 /* length of memo field in .dbf */
|
|
#define DBFTYPE 3 /* value of bits 0 and 1 if .dbf */
|
|
#define EOH 0x0D /* end-of-header marker in .dbf file */
|
|
|
|
/****************************************************************************/
|
|
/* First 32 bytes of a DBF table. */
|
|
/* Note: some reserved fields are used here to store info (Fields) */
|
|
/****************************************************************************/
|
|
typedef struct _dbfheader {
|
|
uchar Version; /* Version information flags */
|
|
char Filedate[3]; /* date, YYMMDD, binary. YY=year-1900 */
|
|
private:
|
|
/* The following four members are stored in little-endian format on disk */
|
|
char m_RecordsBuf[4]; /* records in the file */
|
|
char m_HeadlenBuf[2]; /* bytes in the header */
|
|
char m_ReclenBuf[2]; /* bytes in a record */
|
|
char m_FieldsBuf[2]; /* Reserved but used to store fields */
|
|
public:
|
|
char Incompleteflag; /* 01 if incomplete, else 00 */
|
|
char Encryptflag; /* 01 if encrypted, else 00 */
|
|
char Reserved2[12]; /* for LAN use */
|
|
char Mdxflag; /* 01 if production .mdx, else 00 */
|
|
char Language; /* Codepage */
|
|
char Reserved3[2];
|
|
|
|
uint Records(void) const { return uint4korr(m_RecordsBuf); }
|
|
ushort Headlen(void) const { return uint2korr(m_HeadlenBuf); }
|
|
ushort Reclen(void) const { return uint2korr(m_ReclenBuf); }
|
|
ushort Fields(void) const { return uint2korr(m_FieldsBuf); }
|
|
|
|
void SetHeadlen(ushort num) { int2store(m_HeadlenBuf, num); }
|
|
void SetReclen(ushort num) { int2store(m_ReclenBuf, num); }
|
|
void SetFields(ushort num) { int2store(m_FieldsBuf, num); }
|
|
} DBFHEADER;
|
|
|
|
/****************************************************************************/
|
|
/* Column field descriptor of a .dbf file. */
|
|
/****************************************************************************/
|
|
typedef struct _descriptor {
|
|
char Name[11]; /* field name, in capitals, null filled*/
|
|
char Type; /* field type, C, D, F, L, M or N */
|
|
uint Offset; /* used in memvars, not in files. */
|
|
uchar Length; /* field length */
|
|
uchar Decimals; /* number of decimal places */
|
|
short Reserved4;
|
|
char Workarea; /* ??? */
|
|
char Reserved5[2];
|
|
char Setfield; /* ??? */
|
|
char Reserved6[7];
|
|
char Mdxfield; /* 01 if tag field in production .mdx */
|
|
} DESCRIPTOR;
|
|
|
|
bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul);
|
|
|
|
/***********************************************************************/
|
|
/* Compress a file in zip when creating a table. */
|
|
/***********************************************************************/
|
|
static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, PCSZ fn, PCSZ entry, char *buf)
|
|
{
|
|
int rc = RC_OK, size_read, size_buf = WRITEBUFFERSIZE;
|
|
FILE *fin;
|
|
|
|
if (zutp->addEntry(g, entry))
|
|
return true;
|
|
else if (!(fin = fopen(fn, "rb"))) {
|
|
snprintf(g->Message, sizeof(g->Message), "error in opening %s for reading", fn);
|
|
return true;
|
|
} // endif fin
|
|
|
|
do {
|
|
size_read = (int)fread(buf, 1, size_buf, fin);
|
|
|
|
if (size_read < size_buf && feof(fin) == 0) {
|
|
snprintf(g->Message, sizeof(g->Message), "error in reading %s", fn);
|
|
rc = RC_FX;
|
|
} // endif size_read
|
|
|
|
if (size_read > 0) {
|
|
rc = zutp->writeEntry(g, buf, size_read);
|
|
|
|
if (rc == RC_FX)
|
|
snprintf(g->Message, sizeof(g->Message), "error in writing %s in the zipfile", fn);
|
|
|
|
} // endif size_read
|
|
|
|
} while (rc == RC_OK && size_read > 0);
|
|
|
|
fclose(fin);
|
|
zutp->closeEntry();
|
|
return rc != RC_OK;
|
|
} // end of ZipFile
|
|
|
|
/***********************************************************************/
|
|
/* Find and Compress several files in zip when creating a table. */
|
|
/***********************************************************************/
|
|
static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf)
|
|
{
|
|
char filename[_MAX_PATH];
|
|
|
|
/*********************************************************************/
|
|
/* pat is a multiple file name with wildcard characters */
|
|
/*********************************************************************/
|
|
snprintf(filename, sizeof(filename), "%s", pat);
|
|
|
|
#if defined(_WIN32)
|
|
int rc;
|
|
char drive[_MAX_DRIVE], direc[_MAX_DIR];
|
|
WIN32_FIND_DATA FileData;
|
|
HANDLE hSearch;
|
|
|
|
_splitpath(filename, drive, direc, NULL, NULL);
|
|
|
|
// Start searching files in the target directory.
|
|
hSearch = FindFirstFile(filename, &FileData);
|
|
|
|
if (hSearch == INVALID_HANDLE_VALUE) {
|
|
rc = GetLastError();
|
|
|
|
if (rc != ERROR_FILE_NOT_FOUND) {
|
|
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL, GetLastError(), 0, (LPTSTR)&filename, sizeof(filename), NULL);
|
|
snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), filename);
|
|
return true;
|
|
} else {
|
|
snprintf(g->Message, sizeof(g->Message), "Cannot find any file to load");
|
|
return true;
|
|
} // endif rc
|
|
|
|
} // endif hSearch
|
|
|
|
while (true) {
|
|
if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
snprintf(filename, sizeof(filename), "%s%s%s",
|
|
drive, direc, FileData.cFileName);
|
|
|
|
if (ZipFile(g, zutp, filename, FileData.cFileName, buf)) {
|
|
FindClose(hSearch);
|
|
return true;
|
|
} // endif ZipFile
|
|
|
|
} // endif dwFileAttributes
|
|
|
|
if (!FindNextFile(hSearch, &FileData)) {
|
|
rc = GetLastError();
|
|
|
|
if (rc != ERROR_NO_MORE_FILES) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc);
|
|
FindClose(hSearch);
|
|
return true;
|
|
} // endif rc
|
|
|
|
break;
|
|
} // endif FindNextFile
|
|
|
|
} // endwhile n
|
|
|
|
// Close the search handle.
|
|
if (!FindClose(hSearch)) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(SRCH_CLOSE_ERR));
|
|
return true;
|
|
} // endif FindClose
|
|
|
|
#else // !_WIN32
|
|
struct stat fileinfo;
|
|
char fn[FN_REFLEN], direc[FN_REFLEN], pattern[FN_HEADLEN], ftype[FN_EXTLEN];
|
|
DIR *dir;
|
|
struct dirent *entry;
|
|
|
|
_splitpath(filename, NULL, direc, pattern, ftype);
|
|
safe_strcat(pattern, sizeof(pattern), ftype);
|
|
|
|
// Start searching files in the target directory.
|
|
if (!(dir = opendir(direc))) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), direc, strerror(errno));
|
|
return true;
|
|
} // endif dir
|
|
|
|
while ((entry = readdir(dir))) {
|
|
snprintf(fn, sizeof(fn), "%s%s", direc, entry->d_name);
|
|
|
|
if (lstat(fn, &fileinfo) < 0) {
|
|
snprintf(g->Message, sizeof(g->Message), "%s: %s", fn, strerror(errno));
|
|
return true;
|
|
} else if (!S_ISREG(fileinfo.st_mode))
|
|
continue; // Not a regular file (should test for links)
|
|
|
|
/*******************************************************************/
|
|
/* Test whether the file name matches the table name filter. */
|
|
/*******************************************************************/
|
|
if (fnmatch(pattern, entry->d_name, 0))
|
|
continue; // Not a match
|
|
|
|
snprintf(filename, sizeof(filename), "%s%s", direc, entry->d_name);
|
|
|
|
if (ZipFile(g, zutp, filename, entry->d_name, buf)) {
|
|
closedir(dir);
|
|
return true;
|
|
} // endif ZipFile
|
|
|
|
} // endwhile readdir
|
|
|
|
// Close the dir handle.
|
|
closedir(dir);
|
|
#endif // !_WIN32
|
|
|
|
return false;
|
|
} // end of ZipFiles
|
|
|
|
/***********************************************************************/
|
|
/* Load and Compress a file in zip when creating a table. */
|
|
/***********************************************************************/
|
|
bool ZipLoadFile(PGLOBAL g, PCSZ zfn, PCSZ fn, PCSZ entry, bool append, bool mul)
|
|
{
|
|
char *buf;
|
|
bool err;
|
|
ZIPUTIL *zutp = new(g) ZIPUTIL(NULL);
|
|
|
|
if (zutp->open(g, zfn, append))
|
|
return true;
|
|
|
|
buf = (char*)PlugSubAlloc(g, NULL, WRITEBUFFERSIZE);
|
|
|
|
if (!mul) {
|
|
PCSZ entp;
|
|
|
|
if (!entry) { // entry defaults to the file name
|
|
char* p = strrchr((char*)fn, '/');
|
|
#if defined(_WIN32)
|
|
if (!p) p = strrchr((char*)fn, '\\');
|
|
#endif // _WIN32
|
|
entp = (p) ? p + 1 : entry;
|
|
} else
|
|
entp = entry;
|
|
|
|
err = ZipFile(g, zutp, fn, entp, buf);
|
|
} else
|
|
err = ZipFiles(g, zutp, fn, buf);
|
|
|
|
zutp->close();
|
|
return err;
|
|
} // end of ZipLoadFile
|
|
|
|
/* -------------------------- class ZIPUTIL -------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructors. */
|
|
/***********************************************************************/
|
|
ZIPUTIL::ZIPUTIL(PCSZ tgt)
|
|
{
|
|
zipfile = NULL;
|
|
target = tgt;
|
|
pwd = NULL;
|
|
fp = NULL;
|
|
entryopen = false;
|
|
} // end of ZIPUTIL standard constructor
|
|
|
|
#if 0
|
|
ZIPUTIL::ZIPUTIL(ZIPUTIL *zutp)
|
|
{
|
|
zipfile = zutp->zipfile;
|
|
target = zutp->target;
|
|
pwd = zutp->pwd;
|
|
fp = zutp->fp;
|
|
entryopen = zutp->entryopen;
|
|
} // end of UNZIPUTL copy constructor
|
|
#endif // 0
|
|
|
|
/***********************************************************************/
|
|
/* Fill the zip time structure */
|
|
/* param: tmZip time structure to be filled */
|
|
/***********************************************************************/
|
|
void ZIPUTIL::getTime(tm_zip& tmZip)
|
|
{
|
|
time_t rawtime;
|
|
time(&rawtime);
|
|
struct tm *timeinfo = localtime(&rawtime);
|
|
tmZip.tm_sec = timeinfo->tm_sec;
|
|
tmZip.tm_min = timeinfo->tm_min;
|
|
tmZip.tm_hour = timeinfo->tm_hour;
|
|
tmZip.tm_mday = timeinfo->tm_mday;
|
|
tmZip.tm_mon = timeinfo->tm_mon;
|
|
tmZip.tm_year = timeinfo->tm_year;
|
|
} // end of getTime
|
|
|
|
/***********************************************************************/
|
|
/* open a zip file for deflate. */
|
|
/* param: filename path and the filename of the zip file to open. */
|
|
/* append: set true to append the zip file */
|
|
/* return: true if open, false otherwise. */
|
|
/***********************************************************************/
|
|
bool ZIPUTIL::open(PGLOBAL g, PCSZ filename, bool append)
|
|
{
|
|
if (!zipfile && !(zipfile = zipOpen64(filename,
|
|
append ? APPEND_STATUS_ADDINZIP
|
|
: APPEND_STATUS_CREATE)))
|
|
snprintf(g->Message, sizeof(g->Message), "Zipfile open error on %s", filename);
|
|
|
|
return (zipfile == NULL);
|
|
} // end of open
|
|
|
|
/***********************************************************************/
|
|
/* Close the zip file. */
|
|
/***********************************************************************/
|
|
void ZIPUTIL::close()
|
|
{
|
|
if (zipfile) {
|
|
closeEntry();
|
|
zipClose(zipfile, 0);
|
|
zipfile = NULL;
|
|
} // endif zipfile
|
|
|
|
if (fp)
|
|
fp->Count = 0;
|
|
|
|
} // end of close
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool ZIPUTIL::OpenTable(PGLOBAL g, MODE mode, PCSZ fn, bool append)
|
|
{
|
|
/*********************************************************************/
|
|
/* The file will be compressed. */
|
|
/*********************************************************************/
|
|
if (mode == MODE_INSERT) {
|
|
bool b = open(g, fn, append);
|
|
|
|
if (!b) {
|
|
if (addEntry(g, target))
|
|
return true;
|
|
|
|
/*****************************************************************/
|
|
/* Link a Fblock. This make possible to automatically close it */
|
|
/* in case of error g->jump. */
|
|
/*****************************************************************/
|
|
PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
|
|
|
|
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
|
|
fp->Type = TYPE_FB_ZIP;
|
|
fp->Fname = PlugDup(g, fn);
|
|
fp->Next = dbuserp->Openlist;
|
|
dbuserp->Openlist = fp;
|
|
fp->Count = 1;
|
|
fp->Length = 0;
|
|
fp->Memory = NULL;
|
|
fp->Mode = mode;
|
|
fp->File = this;
|
|
fp->Handle = 0;
|
|
} else
|
|
return true;
|
|
|
|
} else {
|
|
snprintf(g->Message, sizeof(g->Message), "Only INSERT mode supported for ZIPPING files");
|
|
return true;
|
|
} // endif mode
|
|
|
|
return false;
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* Add target in zip file. */
|
|
/***********************************************************************/
|
|
bool ZIPUTIL::addEntry(PGLOBAL g, PCSZ entry)
|
|
{
|
|
//?? we dont need the stinking time
|
|
zip_fileinfo zi = { {0, 0, 0, 0, 0, 0}, 0, 0, 0 };
|
|
|
|
getTime(zi.tmz_date);
|
|
target = entry;
|
|
|
|
int err = zipOpenNewFileInZip(zipfile, target, &zi,
|
|
NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
|
|
|
|
return !(entryopen = (err == ZIP_OK));
|
|
} // end of addEntry
|
|
|
|
/***********************************************************************/
|
|
/* writeEntry: Deflate the buffer to the zip file. */
|
|
/***********************************************************************/
|
|
int ZIPUTIL::writeEntry(PGLOBAL g, char *buf, int len)
|
|
{
|
|
if (zipWriteInFileInZip(zipfile, buf, len) < 0) {
|
|
snprintf(g->Message, sizeof(g->Message), "Error writing %s in the zipfile", target);
|
|
return RC_FX;
|
|
} // endif zipWriteInFileInZip
|
|
|
|
return RC_OK;
|
|
} // end of writeEntry
|
|
|
|
/***********************************************************************/
|
|
/* Close the zip file. */
|
|
/***********************************************************************/
|
|
void ZIPUTIL::closeEntry()
|
|
{
|
|
if (entryopen) {
|
|
zipCloseFileInZip(zipfile);
|
|
entryopen = false;
|
|
} // endif entryopen
|
|
|
|
} // end of closeEntry
|
|
|
|
/* ------------------------- class UNZIPUTL -------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructors. */
|
|
/***********************************************************************/
|
|
UNZIPUTL::UNZIPUTL(PCSZ tgt, PCSZ pw, bool mul)
|
|
{
|
|
zipfile = NULL;
|
|
target = tgt;
|
|
pwd = pw;
|
|
fp = NULL;
|
|
memory = NULL;
|
|
size = 0;
|
|
entryopen = false;
|
|
multiple = mul;
|
|
memset(fn, 0, sizeof(fn));
|
|
|
|
// Init the case mapping table.
|
|
#if defined(_WIN32)
|
|
for (int i = 0; i < 256; ++i) mapCaseTable[i] = toupper(i);
|
|
#else
|
|
for (int i = 0; i < 256; ++i) mapCaseTable[i] = i;
|
|
#endif
|
|
} // end of UNZIPUTL standard constructor
|
|
|
|
UNZIPUTL::UNZIPUTL(PDOSDEF tdp)
|
|
{
|
|
zipfile = NULL;
|
|
target = tdp->GetEntry();
|
|
pwd = tdp->Pwd;
|
|
fp = NULL;
|
|
memory = NULL;
|
|
size = 0;
|
|
entryopen = false;
|
|
multiple = tdp->GetMul();
|
|
memset(fn, 0, sizeof(fn));
|
|
|
|
// Init the case mapping table.
|
|
#if defined(_WIN32)
|
|
for (int i = 0; i < 256; ++i) mapCaseTable[i] = toupper(i);
|
|
#else
|
|
for (int i = 0; i < 256; ++i) mapCaseTable[i] = i;
|
|
#endif
|
|
} // end of UNZIPUTL standard constructor
|
|
|
|
#if 0
|
|
UNZIPUTL::UNZIPUTL(PZIPUTIL zutp)
|
|
{
|
|
zipfile = zutp->zipfile;
|
|
target = zutp->target;
|
|
fp = zutp->fp;
|
|
finfo = zutp->finfo;
|
|
entryopen = zutp->entryopen;
|
|
multiple = zutp->multiple;
|
|
for (int i = 0; i < 256; ++i) mapCaseTable[i] = zutp->mapCaseTable[i];
|
|
} // end of UNZIPUTL copy constructor
|
|
#endif // 0
|
|
|
|
/***********************************************************************/
|
|
/* This code is the copyright property of Alessandro Felice Cantatore. */
|
|
/* http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html */
|
|
/***********************************************************************/
|
|
bool UNZIPUTL::WildMatch(PCSZ pat, PCSZ str) {
|
|
PCSZ s, p;
|
|
bool star = FALSE;
|
|
|
|
loopStart:
|
|
for (s = str, p = pat; *s; ++s, ++p) {
|
|
switch (*p) {
|
|
case '?':
|
|
if (*s == '.') goto starCheck;
|
|
break;
|
|
case '*':
|
|
star = TRUE;
|
|
str = s, pat = p;
|
|
if (!*++pat) return TRUE;
|
|
goto loopStart;
|
|
default:
|
|
if (mapCaseTable[(uint)*s] != mapCaseTable[(uint)*p])
|
|
goto starCheck;
|
|
break;
|
|
} /* endswitch */
|
|
} /* endfor */
|
|
if (*p == '*') ++p;
|
|
return (!*p);
|
|
|
|
starCheck:
|
|
if (!star) return FALSE;
|
|
str++;
|
|
goto loopStart;
|
|
} // end of WildMatch
|
|
|
|
/***********************************************************************/
|
|
/* open a zip file. */
|
|
/* param: filename path and the filename of the zip file to open. */
|
|
/* return: true if open, false otherwise. */
|
|
/***********************************************************************/
|
|
bool UNZIPUTL::open(PGLOBAL g, PCSZ filename)
|
|
{
|
|
if (!zipfile && !(zipfile = unzOpen64(filename)))
|
|
snprintf(g->Message, sizeof(g->Message), "Zipfile open error on %s", filename);
|
|
|
|
return (zipfile == NULL);
|
|
} // end of open
|
|
|
|
/***********************************************************************/
|
|
/* Close the zip file. */
|
|
/***********************************************************************/
|
|
void UNZIPUTL::close()
|
|
{
|
|
if (zipfile) {
|
|
closeEntry();
|
|
unzClose(zipfile);
|
|
zipfile = NULL;
|
|
} // endif zipfile
|
|
|
|
if (fp)
|
|
fp->Count = 0;
|
|
|
|
} // end of close
|
|
|
|
/***********************************************************************/
|
|
/* Find next entry matching target pattern. */
|
|
/***********************************************************************/
|
|
int UNZIPUTL::findEntry(PGLOBAL g, bool next)
|
|
{
|
|
int rc;
|
|
|
|
do {
|
|
if (next) {
|
|
rc = unzGoToNextFile(zipfile);
|
|
|
|
if (rc == UNZ_END_OF_LIST_OF_FILE)
|
|
return RC_EF;
|
|
else if (rc != UNZ_OK) {
|
|
snprintf(g->Message, sizeof(g->Message), "unzGoToNextFile rc = %d", rc);
|
|
return RC_FX;
|
|
} // endif rc
|
|
|
|
} // endif next
|
|
|
|
if (target && *target) {
|
|
rc = unzGetCurrentFileInfo(zipfile, NULL, fn, sizeof(fn),
|
|
NULL, 0, NULL, 0);
|
|
if (rc == UNZ_OK) {
|
|
if (WildMatch(target, fn))
|
|
return RC_OK;
|
|
|
|
} else {
|
|
snprintf(g->Message, sizeof(g->Message), "GetCurrentFileInfo rc = %d", rc);
|
|
return RC_FX;
|
|
} // endif rc
|
|
|
|
} else
|
|
return RC_OK;
|
|
|
|
next = true;
|
|
} while (true);
|
|
|
|
snprintf(g->Message, sizeof(g->Message), "FindNext logical error");
|
|
return RC_FX;
|
|
} // end of FindEntry
|
|
|
|
|
|
/***********************************************************************/
|
|
/* Get the next used entry. */
|
|
/***********************************************************************/
|
|
int UNZIPUTL::nextEntry(PGLOBAL g)
|
|
{
|
|
if (multiple) {
|
|
int rc;
|
|
|
|
closeEntry();
|
|
|
|
if ((rc = findEntry(g, true)) != RC_OK)
|
|
return rc;
|
|
|
|
if (openEntry(g))
|
|
return RC_FX;
|
|
|
|
return RC_OK;
|
|
} else
|
|
return RC_EF;
|
|
|
|
} // end of nextEntry
|
|
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool UNZIPUTL::OpenTable(PGLOBAL g, MODE mode, PCSZ fn)
|
|
{
|
|
/*********************************************************************/
|
|
/* The file will be decompressed into virtual memory. */
|
|
/*********************************************************************/
|
|
if (mode == MODE_READ || mode == MODE_ANY) {
|
|
bool b = open(g, fn);
|
|
|
|
if (!b) {
|
|
int rc;
|
|
|
|
if (target && *target) {
|
|
if (!multiple) {
|
|
rc = unzLocateFile(zipfile, target, 0);
|
|
|
|
if (rc == UNZ_END_OF_LIST_OF_FILE) {
|
|
snprintf(g->Message, sizeof(g->Message), "Target file %s not in %s", target, fn);
|
|
return true;
|
|
} else if (rc != UNZ_OK) {
|
|
snprintf(g->Message, sizeof(g->Message), "unzLocateFile rc=%d", rc);
|
|
return true;
|
|
} // endif's rc
|
|
|
|
} else {
|
|
if ((rc = findEntry(g, false)) == RC_FX)
|
|
return true;
|
|
else if (rc == RC_EF) {
|
|
snprintf(g->Message, sizeof(g->Message), "No match of %s in %s", target, fn);
|
|
return true;
|
|
} // endif rc
|
|
|
|
} // endif multiple
|
|
|
|
} // endif target
|
|
|
|
if (openEntry(g))
|
|
return true;
|
|
|
|
if (size > 0) {
|
|
/*******************************************************************/
|
|
/* Link a Fblock. This make possible to automatically close it */
|
|
/* in case of error g->jump. */
|
|
/*******************************************************************/
|
|
PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
|
|
|
|
fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
|
|
fp->Type = TYPE_FB_ZIP;
|
|
fp->Fname = PlugDup(g, fn);
|
|
fp->Next = dbuserp->Openlist;
|
|
dbuserp->Openlist = fp;
|
|
fp->Count = 1;
|
|
fp->Length = size;
|
|
fp->Memory = memory;
|
|
fp->Mode = mode;
|
|
fp->File = this;
|
|
fp->Handle = 0;
|
|
} // endif fp
|
|
|
|
} else
|
|
return true;
|
|
|
|
} else {
|
|
snprintf(g->Message, sizeof(g->Message), "Only READ mode supported for ZIPPED tables");
|
|
return true;
|
|
} // endif mode
|
|
|
|
return false;
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* Insert only if the entry does not exist. */
|
|
/***********************************************************************/
|
|
bool UNZIPUTL::IsInsertOk(PGLOBAL g, PCSZ fn)
|
|
{
|
|
bool ok = true, b = open(g, fn);
|
|
|
|
if (!b) {
|
|
if (!target || *target == 0) {
|
|
unz_global_info64 ginfo;
|
|
int err = unzGetGlobalInfo64(zipfile, &ginfo);
|
|
|
|
ok = !(err == UNZ_OK && ginfo.number_entry > 0);
|
|
} else // Check if the target exist
|
|
ok = (unzLocateFile(zipfile, target, 0) != UNZ_OK);
|
|
|
|
unzClose(zipfile);
|
|
} // endif b
|
|
|
|
return ok;
|
|
} // end of IsInsertOk
|
|
|
|
/***********************************************************************/
|
|
/* Open target in zip file. */
|
|
/***********************************************************************/
|
|
bool UNZIPUTL::openEntry(PGLOBAL g)
|
|
{
|
|
int rc;
|
|
|
|
rc = unzGetCurrentFileInfo(zipfile, &finfo, fn, sizeof(fn),
|
|
NULL, 0, NULL, 0);
|
|
|
|
if (rc != UNZ_OK) {
|
|
snprintf(g->Message, sizeof(g->Message), "unzGetCurrentFileInfo64 rc=%d", rc);
|
|
return true;
|
|
} else if ((rc = unzOpenCurrentFilePassword(zipfile, pwd)) != UNZ_OK) {
|
|
snprintf(g->Message, sizeof(g->Message), "unzOpen fn=%s rc=%d", fn, rc);
|
|
return true;
|
|
} // endif rc
|
|
|
|
size = finfo.uncompressed_size;
|
|
|
|
try {
|
|
memory = new char[size + 1];
|
|
} catch (...) {
|
|
snprintf(g->Message, sizeof(g->Message), "Out of memory");
|
|
return true;
|
|
} // end try/catch
|
|
|
|
if ((rc = unzReadCurrentFile(zipfile, memory, size)) < 0) {
|
|
snprintf(g->Message, sizeof(g->Message), "unzReadCurrentFile rc = %d", rc);
|
|
unzCloseCurrentFile(zipfile);
|
|
delete[] memory;
|
|
memory = NULL;
|
|
entryopen = false;
|
|
} else {
|
|
memory[size] = 0; // Required by some table types (XML)
|
|
entryopen = true;
|
|
} // endif rc
|
|
|
|
if (trace(1))
|
|
htrc("Opening entry%s %s\n", fn, (entryopen) ? "oked" : "failed");
|
|
|
|
return !entryopen;
|
|
} // end of openEntry
|
|
|
|
/***********************************************************************/
|
|
/* Close the zip file. */
|
|
/***********************************************************************/
|
|
void UNZIPUTL::closeEntry()
|
|
{
|
|
if (entryopen) {
|
|
unzCloseCurrentFile(zipfile);
|
|
entryopen = false;
|
|
} // endif entryopen
|
|
|
|
if (memory) {
|
|
delete[] memory;
|
|
memory = NULL;
|
|
} // endif memory
|
|
|
|
} // end of closeEntry
|
|
|
|
/* -------------------------- class UNZFAM --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructors. */
|
|
/***********************************************************************/
|
|
UNZFAM::UNZFAM(PDOSDEF tdp) : MAPFAM(tdp)
|
|
{
|
|
zutp = NULL;
|
|
tdfp = tdp;
|
|
//target = tdp->GetEntry();
|
|
//mul = tdp->GetMul();
|
|
} // end of UNZFAM standard constructor
|
|
|
|
UNZFAM::UNZFAM(PUNZFAM txfp) : MAPFAM(txfp)
|
|
{
|
|
zutp = txfp->zutp;
|
|
tdfp = txfp->tdfp;
|
|
//target = txfp->target;
|
|
//mul = txfp->mul;
|
|
} // end of UNZFAM copy constructor
|
|
|
|
/***********************************************************************/
|
|
/* ZIP GetFileLength: returns file size in number of bytes. */
|
|
/***********************************************************************/
|
|
int UNZFAM::GetFileLength(PGLOBAL g)
|
|
{
|
|
int len = (zutp && zutp->entryopen) ? (int)(Top - Memory)
|
|
: TXTFAM::GetFileLength(g) * 3;
|
|
|
|
if (trace(1))
|
|
htrc("Zipped file length=%d\n", len);
|
|
|
|
return len;
|
|
} // end of GetFileLength
|
|
|
|
/***********************************************************************/
|
|
/* ZIP Cardinality: return the number of rows if possible. */
|
|
/***********************************************************************/
|
|
int UNZFAM::Cardinality(PGLOBAL g)
|
|
{
|
|
if (!g)
|
|
return 1;
|
|
|
|
int card = -1;
|
|
int len = GetFileLength(g);
|
|
|
|
if (len) {
|
|
// Estimated ???
|
|
card = (len / (int)Lrecl) * 2;
|
|
card = card ? card : 10; // Lrecl can be too big
|
|
} else
|
|
card = 0;
|
|
|
|
return card;
|
|
} // end of Cardinality
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool UNZFAM::OpenTableFile(PGLOBAL g)
|
|
{
|
|
char filename[_MAX_PATH];
|
|
MODE mode = Tdbp->GetMode();
|
|
|
|
/*********************************************************************/
|
|
/* Allocate the ZIP utility class. */
|
|
/*********************************************************************/
|
|
zutp = new(g) UNZIPUTL(tdfp);
|
|
|
|
// We used the file name relative to recorded datapath
|
|
PlugSetPath(filename, To_File, Tdbp->GetPath());
|
|
|
|
if (!zutp->OpenTable(g, mode, filename)) {
|
|
// The pseudo "buffer" is here the entire real buffer
|
|
Fpos = Mempos = Memory = zutp->memory;
|
|
Top = Memory + zutp->size;
|
|
To_Fb = zutp->fp; // Useful when closing
|
|
} else
|
|
return true;
|
|
|
|
return false;
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* GetNext: go to next entry. */
|
|
/***********************************************************************/
|
|
int UNZFAM::GetNext(PGLOBAL g)
|
|
{
|
|
int rc = zutp->nextEntry(g);
|
|
|
|
if (rc != RC_OK)
|
|
return rc;
|
|
|
|
Mempos = Memory = zutp->memory;
|
|
Top = Memory + zutp->size;
|
|
return RC_OK;
|
|
} // end of GetNext
|
|
|
|
#if 0
|
|
/***********************************************************************/
|
|
/* ReadBuffer: Read one line for a ZIP file. */
|
|
/***********************************************************************/
|
|
int UNZFAM::ReadBuffer(PGLOBAL g)
|
|
{
|
|
int rc, len;
|
|
|
|
// Are we at the end of the memory
|
|
if (Mempos >= Top) {
|
|
if ((rc = zutp->nextEntry(g)) != RC_OK)
|
|
return rc;
|
|
|
|
Mempos = Memory = zutp->memory;
|
|
Top = Memory + zutp->size;
|
|
} // endif Mempos
|
|
|
|
#if 0
|
|
if (!Placed) {
|
|
/*******************************************************************/
|
|
/* Record file position in case of UPDATE or DELETE. */
|
|
/*******************************************************************/
|
|
int rc;
|
|
|
|
next:
|
|
Fpos = Mempos;
|
|
CurBlk = (int)Rows++;
|
|
|
|
/*******************************************************************/
|
|
/* Check whether optimization on ROWID */
|
|
/* can be done, as well as for join as for local filtering. */
|
|
/*******************************************************************/
|
|
switch (Tdbp->TestBlock(g)) {
|
|
case RC_EF:
|
|
return RC_EF;
|
|
case RC_NF:
|
|
// Skip this record
|
|
if ((rc = SkipRecord(g, false)) != RC_OK)
|
|
return rc;
|
|
|
|
goto next;
|
|
} // endswitch rc
|
|
|
|
} else
|
|
Placed = false;
|
|
#else
|
|
// Perhaps unuseful
|
|
Fpos = Mempos;
|
|
CurBlk = (int)Rows++;
|
|
Placed = false;
|
|
#endif
|
|
|
|
// Immediately calculate next position (Used by DeleteDB)
|
|
while (*Mempos++ != '\n'); // What about Unix ???
|
|
|
|
// Set caller line buffer
|
|
len = (Mempos - Fpos) - 1;
|
|
|
|
// Don't rely on ENDING setting
|
|
if (len > 0 && *(Mempos - 2) == '\r')
|
|
len--; // Line ends by CRLF
|
|
|
|
memcpy(Tdbp->GetLine(), Fpos, len);
|
|
Tdbp->GetLine()[len] = '\0';
|
|
return RC_OK;
|
|
} // end of ReadBuffer
|
|
|
|
/***********************************************************************/
|
|
/* Table file close routine for MAP access method. */
|
|
/***********************************************************************/
|
|
void UNZFAM::CloseTableFile(PGLOBAL g, bool)
|
|
{
|
|
close();
|
|
} // end of CloseTableFile
|
|
#endif // 0
|
|
|
|
/* -------------------------- class UZXFAM --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructors. */
|
|
/***********************************************************************/
|
|
UZXFAM::UZXFAM(PDOSDEF tdp) : MPXFAM(tdp)
|
|
{
|
|
zutp = NULL;
|
|
tdfp = tdp;
|
|
//target = tdp->GetEntry();
|
|
//mul = tdp->GetMul();
|
|
//Lrecl = tdp->GetLrecl();
|
|
} // end of UZXFAM standard constructor
|
|
|
|
UZXFAM::UZXFAM(PUZXFAM txfp) : MPXFAM(txfp)
|
|
{
|
|
zutp = txfp->zutp;
|
|
tdfp = txfp->tdfp;
|
|
//target = txfp->target;
|
|
//mul = txfp->mul;
|
|
//Lrecl = txfp->Lrecl;
|
|
} // end of UZXFAM copy constructor
|
|
|
|
/***********************************************************************/
|
|
/* ZIP GetFileLength: returns file size in number of bytes. */
|
|
/***********************************************************************/
|
|
int UZXFAM::GetFileLength(PGLOBAL g)
|
|
{
|
|
int len;
|
|
|
|
if (!zutp && OpenTableFile(g))
|
|
return 0;
|
|
|
|
if (zutp->entryopen)
|
|
len = zutp->size;
|
|
else
|
|
len = 0;
|
|
|
|
return len;
|
|
} // end of GetFileLength
|
|
|
|
/***********************************************************************/
|
|
/* ZIP Cardinality: return the number of rows if possible. */
|
|
/***********************************************************************/
|
|
int UZXFAM::Cardinality(PGLOBAL g)
|
|
{
|
|
if (!g)
|
|
return 1;
|
|
|
|
int card = -1;
|
|
int len = GetFileLength(g);
|
|
|
|
if (!(len % Lrecl))
|
|
card = len / (int)Lrecl; // Fixed length file
|
|
else
|
|
snprintf(g->Message, sizeof(g->Message), MSG(NOT_FIXED_LEN), zutp->fn, len, Lrecl);
|
|
|
|
// Set number of blocks for later use
|
|
Block = (card > 0) ? (card + Nrec - 1) / Nrec : 0;
|
|
return card;
|
|
} // end of Cardinality
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a FIX/UNIX table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool UZXFAM::OpenTableFile(PGLOBAL g)
|
|
{
|
|
// May have been already opened in GetFileLength
|
|
if (!zutp || !zutp->zipfile) {
|
|
char filename[_MAX_PATH];
|
|
MODE mode = Tdbp->GetMode();
|
|
|
|
/*********************************************************************/
|
|
/* Allocate the ZIP utility class. */
|
|
/*********************************************************************/
|
|
if (!zutp)
|
|
zutp = new(g)UNZIPUTL(tdfp);
|
|
|
|
// We used the file name relative to recorded datapath
|
|
PlugSetPath(filename, To_File, Tdbp->GetPath());
|
|
|
|
if (!zutp->OpenTable(g, mode, filename)) {
|
|
// The pseudo "buffer" is here the entire real buffer
|
|
Memory = zutp->memory;
|
|
Fpos = Mempos = Memory + Headlen;
|
|
Top = Memory + zutp->size;
|
|
To_Fb = zutp->fp; // Useful when closing
|
|
} else
|
|
return true;
|
|
|
|
} else
|
|
Reset();
|
|
|
|
return false;
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* GetNext: go to next entry. */
|
|
/***********************************************************************/
|
|
int UZXFAM::GetNext(PGLOBAL g)
|
|
{
|
|
int rc = zutp->nextEntry(g);
|
|
|
|
if (rc != RC_OK)
|
|
return rc;
|
|
|
|
int len = zutp->size;
|
|
|
|
if (len % Lrecl) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(NOT_FIXED_LEN), zutp->fn, len, Lrecl);
|
|
return RC_FX;
|
|
} // endif size
|
|
|
|
Memory = zutp->memory;
|
|
Top = Memory + len;
|
|
Rewind();
|
|
return RC_OK;
|
|
} // end of GetNext
|
|
|
|
/* -------------------------- class UZDFAM --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructors. */
|
|
/***********************************************************************/
|
|
UZDFAM::UZDFAM(PDOSDEF tdp) : DBMFAM(tdp)
|
|
{
|
|
zutp = NULL;
|
|
tdfp = tdp;
|
|
//target = tdp->GetEntry();
|
|
//mul = tdp->GetMul();
|
|
//Lrecl = tdp->GetLrecl();
|
|
} // end of UZXFAM standard constructor
|
|
|
|
UZDFAM::UZDFAM(PUZDFAM txfp) : DBMFAM(txfp)
|
|
{
|
|
zutp = txfp->zutp;
|
|
tdfp = txfp->tdfp;
|
|
//target = txfp->target;
|
|
//mul = txfp->mul;
|
|
//Lrecl = txfp->Lrecl;
|
|
} // end of UZXFAM copy constructor
|
|
|
|
#if 0
|
|
/****************************************************************************/
|
|
/* dbfhead: Routine to analyze a DBF header. */
|
|
/* Parameters: */
|
|
/* PGLOBAL g -- pointer to the CONNECT Global structure */
|
|
/* DBFHEADER *hdrp -- pointer to _dbfheader structure */
|
|
/* Returns: */
|
|
/* RC_OK, RC_NF, RC_INFO, or RC_FX if error. */
|
|
/* Side effects: */
|
|
/* Set the fields number in the header. */
|
|
/****************************************************************************/
|
|
int UZDFAM::dbfhead(PGLOBAL g, void* buf)
|
|
{
|
|
char *endmark;
|
|
int dbc = 2, rc = RC_OK;
|
|
DBFHEADER* hdrp = (DBFHEADER*)buf;
|
|
|
|
*g->Message = '\0';
|
|
|
|
// Check first byte to be sure of .dbf type
|
|
if ((hdrp->Version & 0x03) != DBFTYPE) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(NOT_A_DBF_FILE));
|
|
rc = RC_INFO;
|
|
|
|
if ((hdrp->Version & 0x30) == 0x30) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(FOXPRO_FILE));
|
|
dbc = 264; // FoxPro database container
|
|
} // endif Version
|
|
|
|
} else
|
|
snprintf(g->Message, sizeof(g->Message), MSG(DBASE_FILE));
|
|
|
|
// Check last byte(s) of header
|
|
endmark = (char*)hdrp + hdrp->Headlen() - dbc;
|
|
|
|
// Some headers just have 1D others have 1D00 following fields
|
|
if (endmark[0] != EOH && endmark[1] != EOH) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(NO_0DH_HEAD), dbc);
|
|
|
|
if (rc == RC_OK)
|
|
return RC_FX;
|
|
|
|
} // endif endmark
|
|
|
|
// Calculate here the number of fields while we have the dbc info
|
|
hdrp->SetFields((hdrp->Headlen() - dbc - 1) / 32);
|
|
return rc;
|
|
} // end of dbfhead
|
|
|
|
/****************************************************************************/
|
|
/* ScanHeader: scan the DBF file header for number of records, record size,*/
|
|
/* and header length. Set Records, check that Reclen is equal to lrecl and */
|
|
/* return the header length or 0 in case of error. */
|
|
/****************************************************************************/
|
|
int UZDFAM::ScanHeader(PGLOBAL g, int* rln)
|
|
{
|
|
int rc;
|
|
DBFHEADER header;
|
|
|
|
/************************************************************************/
|
|
/* Get the first 32 bytes of the header. */
|
|
/************************************************************************/
|
|
rc = dbfhead(g, &header);
|
|
|
|
if (rc == RC_FX)
|
|
return -1;
|
|
|
|
*rln = (int)header.Reclen();
|
|
Records = (int)header.Records();
|
|
return (int)header.Headlen();
|
|
} // end of ScanHeader
|
|
#endif // 0
|
|
|
|
/***********************************************************************/
|
|
/* ZIP GetFileLength: returns file size in number of bytes. */
|
|
/***********************************************************************/
|
|
int UZDFAM::GetFileLength(PGLOBAL g)
|
|
{
|
|
int len;
|
|
|
|
if (!zutp && OpenTableFile(g))
|
|
return 0;
|
|
|
|
if (zutp->entryopen)
|
|
len = zutp->size;
|
|
else
|
|
len = 0;
|
|
|
|
return len;
|
|
} // end of GetFileLength
|
|
|
|
/***********************************************************************/
|
|
/* ZIP Cardinality: return the number of rows if possible. */
|
|
/***********************************************************************/
|
|
int UZDFAM::Cardinality(PGLOBAL g)
|
|
{
|
|
if (!g)
|
|
return 1;
|
|
|
|
int card = -1;
|
|
|
|
card = Records;
|
|
|
|
// Set number of blocks for later use
|
|
Block = (card > 0) ? (card + Nrec - 1) / Nrec : 0;
|
|
return card;
|
|
} // end of Cardinality
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a DBF table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool UZDFAM::OpenTableFile(PGLOBAL g)
|
|
{
|
|
// May have been already opened in GetFileLength
|
|
if (!zutp || !zutp->zipfile) {
|
|
char filename[_MAX_PATH];
|
|
MODE mode = Tdbp->GetMode();
|
|
|
|
/*********************************************************************/
|
|
/* Allocate the ZIP utility class. */
|
|
/*********************************************************************/
|
|
if (!zutp)
|
|
zutp = new(g)UNZIPUTL(tdfp);
|
|
|
|
// We used the file name relative to recorded datapath
|
|
PlugSetPath(filename, To_File, Tdbp->GetPath());
|
|
|
|
if (!zutp->OpenTable(g, mode, filename)) {
|
|
// The pseudo "buffer" is here the entire real buffer
|
|
Memory = zutp->memory;
|
|
Top = Memory + zutp->size;
|
|
To_Fb = zutp->fp; // Useful when closing
|
|
return AllocateBuffer(g);
|
|
} else
|
|
return true;
|
|
|
|
} else
|
|
Reset();
|
|
|
|
return false;
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* GetNext: go to next entry. */
|
|
/***********************************************************************/
|
|
int UZDFAM::GetNext(PGLOBAL g)
|
|
{
|
|
int rc = zutp->nextEntry(g);
|
|
|
|
if (rc != RC_OK)
|
|
return rc;
|
|
|
|
int len = zutp->size;
|
|
|
|
#if 0
|
|
if (len % Lrecl) {
|
|
snprintf(g->Message, sizeof(g->Message), MSG(NOT_FIXED_LEN), zutp->fn, len, Lrecl);
|
|
return RC_FX;
|
|
} // endif size
|
|
#endif // 0
|
|
|
|
Memory = zutp->memory;
|
|
Top = Memory + len;
|
|
Rewind();
|
|
return RC_OK;
|
|
} // end of GetNext
|
|
|
|
/* -------------------------- class ZIPFAM --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructor. */
|
|
/***********************************************************************/
|
|
ZIPFAM::ZIPFAM(PDOSDEF tdp) : DOSFAM(tdp)
|
|
{
|
|
zutp = NULL;
|
|
target = tdp->GetEntry();
|
|
append = tdp->GetAppend();
|
|
} // end of ZIPFAM standard constructor
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool ZIPFAM::OpenTableFile(PGLOBAL g)
|
|
{
|
|
char filename[_MAX_PATH];
|
|
MODE mode = Tdbp->GetMode();
|
|
int len = TXTFAM::GetFileLength(g);
|
|
|
|
// We used the file name relative to recorded datapath
|
|
PlugSetPath(filename, To_File, Tdbp->GetPath());
|
|
|
|
if (len < 0)
|
|
return true;
|
|
else if (!append && len > 0) {
|
|
snprintf(g->Message, sizeof(g->Message), "No insert into existing zip file");
|
|
return true;
|
|
} else if (append && len > 0) {
|
|
UNZIPUTL *zutp = new(g) UNZIPUTL(target, NULL, false);
|
|
|
|
if (!zutp->IsInsertOk(g, filename)) {
|
|
snprintf(g->Message, sizeof(g->Message), "No insert into existing entry");
|
|
return true;
|
|
} // endif Ok
|
|
|
|
} // endif's
|
|
|
|
/*********************************************************************/
|
|
/* Allocate the ZIP utility class. */
|
|
/*********************************************************************/
|
|
zutp = new(g) ZIPUTIL(target);
|
|
|
|
// We used the file name relative to recorded datapath
|
|
PlugSetPath(filename, To_File, Tdbp->GetPath());
|
|
|
|
if (!zutp->OpenTable(g, mode, filename, append)) {
|
|
To_Fb = zutp->fp; // Useful when closing
|
|
} else
|
|
return true;
|
|
|
|
return AllocateBuffer(g);
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* ReadBuffer: Read one line for a ZIP file. */
|
|
/***********************************************************************/
|
|
int ZIPFAM::ReadBuffer(PGLOBAL g)
|
|
{
|
|
snprintf(g->Message, sizeof(g->Message), "ReadBuffer should not been called when zipping");
|
|
return RC_FX;
|
|
} // end of ReadBuffer
|
|
|
|
/***********************************************************************/
|
|
/* WriteBuffer: Deflate the buffer to the zip file. */
|
|
/***********************************************************************/
|
|
int ZIPFAM::WriteBuffer(PGLOBAL g)
|
|
{
|
|
int len;
|
|
|
|
// Prepare to write the new line
|
|
strcat(strcpy(To_Buf, Tdbp->GetLine()), (Bin) ? CrLf : "\n");
|
|
len = (int)(strchr(To_Buf, '\n') - To_Buf + 1);
|
|
return zutp->writeEntry(g, To_Buf, len);
|
|
} // end of WriteBuffer
|
|
|
|
/***********************************************************************/
|
|
/* Table file close routine for ZIP access method. */
|
|
/***********************************************************************/
|
|
void ZIPFAM::CloseTableFile(PGLOBAL g, bool)
|
|
{
|
|
To_Fb->Count = 0;
|
|
zutp->close();
|
|
} // end of CloseTableFile
|
|
|
|
/* -------------------------- class ZPXFAM --------------------------- */
|
|
|
|
/***********************************************************************/
|
|
/* Constructor. */
|
|
/***********************************************************************/
|
|
ZPXFAM::ZPXFAM(PDOSDEF tdp) : FIXFAM(tdp)
|
|
{
|
|
zutp = NULL;
|
|
target = tdp->GetEntry();
|
|
append = tdp->GetAppend();
|
|
//Lrecl = tdp->GetLrecl();
|
|
} // end of ZPXFAM standard constructor
|
|
|
|
/***********************************************************************/
|
|
/* OpenTableFile: Open a DOS/UNIX table file from a ZIP file. */
|
|
/***********************************************************************/
|
|
bool ZPXFAM::OpenTableFile(PGLOBAL g)
|
|
{
|
|
char filename[_MAX_PATH];
|
|
MODE mode = Tdbp->GetMode();
|
|
int len = TXTFAM::GetFileLength(g);
|
|
|
|
if (len < 0)
|
|
return true;
|
|
else if (!append && len > 0) {
|
|
snprintf(g->Message, sizeof(g->Message), "No insert into existing zip file");
|
|
return true;
|
|
} else if (append && len > 0) {
|
|
UNZIPUTL *zutp = new(g) UNZIPUTL(target, NULL, false);
|
|
|
|
if (!zutp->IsInsertOk(g, filename)) {
|
|
snprintf(g->Message, sizeof(g->Message), "No insert into existing entry");
|
|
return true;
|
|
} // endif Ok
|
|
|
|
} // endif's
|
|
|
|
/*********************************************************************/
|
|
/* Allocate the ZIP utility class. */
|
|
/*********************************************************************/
|
|
zutp = new(g) ZIPUTIL(target);
|
|
|
|
// We used the file name relative to recorded datapath
|
|
PlugSetPath(filename, To_File, Tdbp->GetPath());
|
|
|
|
if (!zutp->OpenTable(g, mode, filename, append)) {
|
|
To_Fb = zutp->fp; // Useful when closing
|
|
} else
|
|
return true;
|
|
|
|
return AllocateBuffer(g);
|
|
} // end of OpenTableFile
|
|
|
|
/***********************************************************************/
|
|
/* WriteBuffer: Deflate the buffer to the zip file. */
|
|
/***********************************************************************/
|
|
int ZPXFAM::WriteBuffer(PGLOBAL g)
|
|
{
|
|
/*********************************************************************/
|
|
/* In Insert mode, we write only full blocks. */
|
|
/*********************************************************************/
|
|
if (++CurNum != Rbuf) {
|
|
Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
|
|
return RC_OK;
|
|
} // endif CurNum
|
|
|
|
// Now start the compress process.
|
|
if (zutp->writeEntry(g, To_Buf, Lrecl * Rbuf) != RC_OK) {
|
|
Closing = true;
|
|
return RC_FX;
|
|
} // endif writeEntry
|
|
|
|
CurBlk++;
|
|
CurNum = 0;
|
|
Tdbp->SetLine(To_Buf);
|
|
return RC_OK;
|
|
} // end of WriteBuffer
|
|
|
|
/***********************************************************************/
|
|
/* Table file close routine for ZIP access method. */
|
|
/***********************************************************************/
|
|
void ZPXFAM::CloseTableFile(PGLOBAL g, bool)
|
|
{
|
|
if (CurNum && !Closing) {
|
|
// Some more inserted lines remain to be written
|
|
Rbuf = CurNum--;
|
|
WriteBuffer(g);
|
|
} // endif Curnum
|
|
|
|
To_Fb->Count = 0;
|
|
zutp->close();
|
|
} // end of CloseTableFile
|