mirror of
https://github.com/MariaDB/server.git
synced 2025-11-28 17:36:30 +03:00
Old style C functions `strcpy()`, `strcat()` and `sprintf()` are vulnerable to security issues due to lacking memory boundary checks. Replace these in the Connect storage engine with safe new and/or custom functions such as `snprintf()` `safe_strcpy()` and `safe_strcat()`. With this change FlawFinder and other static security analyzers report 287 fewer findings. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
1458 lines
45 KiB
C++
1458 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;
|
|
GetFileLength(g);
|
|
|
|
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
|