mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 20:36:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1620 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1620 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/************* TabMul C++ Program Source Code File (.CPP) **************/
 | 
						|
/* PROGRAM NAME: TABMUL                                                */
 | 
						|
/* -------------                                                       */
 | 
						|
/*  Version 1.9                                                        */
 | 
						|
/*                                                                     */
 | 
						|
/* COPYRIGHT:                                                          */
 | 
						|
/* ----------                                                          */
 | 
						|
/*  (C) Copyright to PlugDB Software Development          2003 - 2017  */
 | 
						|
/*  Author: Olivier BERTRAND                                           */
 | 
						|
/*                                                                     */
 | 
						|
/* WHAT THIS PROGRAM DOES:                                             */
 | 
						|
/* -----------------------                                             */
 | 
						|
/*  This program are the TDBMUL class DB routines.                     */
 | 
						|
/*                                                                     */
 | 
						|
/* WHAT YOU NEED TO COMPILE THIS PROGRAM:                              */
 | 
						|
/* --------------------------------------                              */
 | 
						|
/*                                                                     */
 | 
						|
/*  REQUIRED FILES:                                                    */
 | 
						|
/*  ---------------                                                    */
 | 
						|
/*    TABMUL.CPP     - Source code                                     */
 | 
						|
/*    PLGDBSEM.H     - DB application declaration file                 */
 | 
						|
/*    TABDOS.H       - TABDOS classes declaration file                 */
 | 
						|
/*    TABMUL.H       - TABFIX classes declaration file                 */
 | 
						|
/*    GLOBAL.H       - Global declaration file                         */
 | 
						|
/*                                                                     */
 | 
						|
/*  REQUIRED LIBRARIES:                                                */
 | 
						|
/*  -------------------                                                */
 | 
						|
/*    Large model C library                                            */
 | 
						|
/*                                                                     */
 | 
						|
/*  REQUIRED PROGRAMS:                                                 */
 | 
						|
/*  ------------------                                                 */
 | 
						|
/*    IBM, Borland, GNU or Microsoft C++ Compiler and Linker           */
 | 
						|
/*                                                                     */
 | 
						|
/***********************************************************************/
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Include relevant section of system dependant header files.         */
 | 
						|
/***********************************************************************/
 | 
						|
#include "my_global.h"
 | 
						|
#if defined(_WIN32)
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#if defined(__BORLANDC__)
 | 
						|
#define __MFC_COMPAT__                   // To define min/max as macro
 | 
						|
#endif
 | 
						|
//#include <windows.h>
 | 
						|
#if defined(PATHMATCHSPEC) 
 | 
						|
#include "Shlwapi.h"
 | 
						|
//using namespace std;
 | 
						|
#pragma comment(lib,"shlwapi.lib")
 | 
						|
#endif   //	PATHMATCHSPEC
 | 
						|
#else
 | 
						|
#if defined(UNIX)
 | 
						|
#include <fnmatch.h>
 | 
						|
#include <errno.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include "osutil.h"
 | 
						|
#else
 | 
						|
//#include <io.h>
 | 
						|
#endif
 | 
						|
//#include <fcntl.h>
 | 
						|
#endif
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Include application header files:                                  */
 | 
						|
/***********************************************************************/
 | 
						|
#include "global.h"      // global declarations
 | 
						|
#include "plgdbsem.h"    // DB application declarations
 | 
						|
#include "reldef.h"      // DB definition declares
 | 
						|
#include "filamtxt.h"
 | 
						|
#include "tabdos.h"      // TDBDOS and DOSCOL class dcls
 | 
						|
#include "tabmul.h"      // TDBMUL and MULCOL classes dcls
 | 
						|
 | 
						|
/* ------------------------- Class TDBMUL ---------------------------- */
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  TABMUL constructors.                                               */
 | 
						|
/***********************************************************************/
 | 
						|
TDBMUL::TDBMUL(PTDB tdbp) : TDBASE(tdbp->GetDef())
 | 
						|
  {
 | 
						|
  Tdbp = tdbp;
 | 
						|
  Filenames = NULL;
 | 
						|
  Rows = 0;
 | 
						|
  Mul = tdbp->GetDef()->GetMultiple();
 | 
						|
  NumFiles = 0;
 | 
						|
  iFile = 0;
 | 
						|
  } // end of TDBMUL standard constructor
 | 
						|
 | 
						|
TDBMUL::TDBMUL(PTDBMUL tdbp) : TDBASE(tdbp)
 | 
						|
  {
 | 
						|
  Tdbp = tdbp->Tdbp;
 | 
						|
  Filenames = tdbp->Filenames;
 | 
						|
  Rows = tdbp->Rows;
 | 
						|
  Mul = tdbp->Mul;
 | 
						|
  NumFiles = tdbp->NumFiles;
 | 
						|
  iFile = tdbp->iFile;
 | 
						|
  } // end of TDBMUL copy constructor
 | 
						|
 | 
						|
// Method
 | 
						|
PTDB TDBMUL::Clone(PTABS t)
 | 
						|
  {
 | 
						|
  PTDBMUL tp;
 | 
						|
  PGLOBAL g = t->G;        // Is this really useful ???
 | 
						|
 | 
						|
  tp = new(g) TDBMUL(this);
 | 
						|
  tp->Tdbp = Tdbp->Clone(t);
 | 
						|
  tp->Columns = tp->Tdbp->GetColumns();
 | 
						|
  return tp;
 | 
						|
  } // end of Clone
 | 
						|
 | 
						|
PTDB TDBMUL::Duplicate(PGLOBAL g)
 | 
						|
  {
 | 
						|
  PTDBMUL tmup = new(g) TDBMUL(this);
 | 
						|
 | 
						|
  tmup->Tdbp = Tdbp->Duplicate(g);
 | 
						|
  return tmup;
 | 
						|
  } // end of Duplicate
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Initializes the table filename list.                               */
 | 
						|
/*  Note: tables created by concatenating the file components without  */
 | 
						|
/*  specifying the LRECL value (that should be restricted to _MAX_PATH)*/
 | 
						|
/*  have a LRECL that is the sum of the lengths of all components.     */
 | 
						|
/*  This is why we use a big filename array to take care of that.      */
 | 
						|
/***********************************************************************/
 | 
						|
 | 
						|
PRAGMA_DISABLE_CHECK_STACK_FRAME
 | 
						|
 | 
						|
bool TDBMUL::InitFileNames(PGLOBAL g)
 | 
						|
{
 | 
						|
#define PFNZ  4096
 | 
						|
#define FNSZ  (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT)
 | 
						|
	PTDBDIR dirp;
 | 
						|
	PSZ     pfn[PFNZ];
 | 
						|
  PSZ     filename;
 | 
						|
  int     rc, n = 0;
 | 
						|
 | 
						|
  if (trace(1))
 | 
						|
    htrc("in InitFileName: fn[]=%d\n", FNSZ);
 | 
						|
 | 
						|
  filename = (char*)PlugSubAlloc(g, NULL, FNSZ);
 | 
						|
 | 
						|
  // The sub table may need to refer to the Table original block
 | 
						|
  Tdbp->SetTable(To_Table);         // Was not set at construction
 | 
						|
 | 
						|
  PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
 | 
						|
 | 
						|
  if (trace(1))
 | 
						|
    htrc("InitFileName: fn='%s'\n", filename);
 | 
						|
 | 
						|
  if (Mul != 2) {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  To_File is a multiple name with special characters             */
 | 
						|
    /*******************************************************************/
 | 
						|
		if (Mul == 1)
 | 
						|
			dirp = new(g) TDBDIR(PlugDup(g, filename));
 | 
						|
		else // Mul == 3 (Subdir)
 | 
						|
		  dirp = new(g) TDBSDR(PlugDup(g, filename));
 | 
						|
 | 
						|
		if (dirp->OpenDB(g))
 | 
						|
			return true;
 | 
						|
 | 
						|
		if (trace(1) && Mul == 3) {
 | 
						|
			int nf = ((PTDBSDR)dirp)->FindInDir(g);
 | 
						|
			htrc("Number of files = %d\n", nf);
 | 
						|
		} // endif trace
 | 
						|
 | 
						|
		while (true)
 | 
						|
			if ((rc = dirp->ReadDB(g)) == RC_OK) {
 | 
						|
#if defined(_WIN32)
 | 
						|
				strcat(strcpy(filename, dirp->Drive), dirp->Direc);
 | 
						|
#else   // !_WIN32
 | 
						|
				strcpy(filename, dirp->Direc);
 | 
						|
#endif  // !_WIN32
 | 
						|
				strcat(strcat(filename, dirp->Fname), dirp->Ftype);
 | 
						|
				pfn[n++] = PlugDup(g, filename);
 | 
						|
			} else
 | 
						|
				break;
 | 
						|
 | 
						|
		dirp->CloseDB(g);
 | 
						|
 | 
						|
		if (rc == RC_FX)
 | 
						|
			return true;
 | 
						|
 | 
						|
  } else {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  To_File is the name of a file containing the file name list    */
 | 
						|
    /*******************************************************************/
 | 
						|
    char *p;
 | 
						|
    FILE *stream;
 | 
						|
 | 
						|
    if (!(stream= global_fopen(g, MSGID_OPEN_MODE_STRERROR, filename, "r")))
 | 
						|
      return true;
 | 
						|
 | 
						|
    while (n < PFNZ) {
 | 
						|
      if (!fgets(filename, FNSZ, stream)) {
 | 
						|
        fclose(stream);
 | 
						|
        break;
 | 
						|
        } // endif fgets
 | 
						|
 | 
						|
      p = filename + strlen(filename) - 1;
 | 
						|
 | 
						|
 | 
						|
      // Data files can have CRLF
 | 
						|
      if (*p == '\n' || *p == '\r') {
 | 
						|
        p--;          // Eliminate ending CR or LF character
 | 
						|
 | 
						|
        if (p >= filename)
 | 
						|
          if (*p == '\n' || *p == '\r')
 | 
						|
            p--;    // Eliminate ending CR or LF character
 | 
						|
 | 
						|
      } // endif p
 | 
						|
      // Trim rightmost blanks
 | 
						|
      for (; p >= filename && *p == ' '; p--) ;
 | 
						|
 | 
						|
      *(++p) = '\0';
 | 
						|
 | 
						|
      // Suballocate the file name
 | 
						|
      pfn[n++] = PlugDup(g, filename);
 | 
						|
    } // endfor n
 | 
						|
 | 
						|
  } // endif Mul
 | 
						|
 | 
						|
  if (n) {
 | 
						|
    Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*));
 | 
						|
 | 
						|
    for (int i = 0; i < n; i++)
 | 
						|
      Filenames[i] = pfn[i];
 | 
						|
 | 
						|
  } else {
 | 
						|
    Filenames = (char**)PlugSubAlloc(g, NULL, sizeof(char*));
 | 
						|
    Filenames[0] = NULL;
 | 
						|
  } // endif n
 | 
						|
 | 
						|
  NumFiles = n;
 | 
						|
  return false;
 | 
						|
  } // end of InitFileNames
 | 
						|
PRAGMA_REENABLE_CHECK_STACK_FRAME
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  The table column list is the sub-table column list.                */
 | 
						|
/***********************************************************************/
 | 
						|
PCOL TDBMUL::ColDB(PGLOBAL g, PSZ name, int num)
 | 
						|
  {
 | 
						|
  PCOL cp;
 | 
						|
 | 
						|
  /*********************************************************************/
 | 
						|
  /*  Because special columns are directly added to the MUL block,     */
 | 
						|
  /*  make sure that the sub-table has the same column list, before    */
 | 
						|
  /*  and after the call to the ColDB function.                        */
 | 
						|
  /*********************************************************************/
 | 
						|
  Tdbp->SetColumns(Columns);
 | 
						|
  cp = Tdbp->ColDB(g, name, num);
 | 
						|
  Columns = Tdbp->GetColumns();
 | 
						|
  return cp;
 | 
						|
} // end of ColDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  MUL GetProgMax: get the max value for progress information.        */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::GetProgMax(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (!Filenames && InitFileNames(g))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  return NumFiles;                // This is a temporary setting
 | 
						|
  } // end of GetProgMax
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  MUL GetProgCur: get the current value for progress information.    */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::GetProgCur(void)
 | 
						|
  {
 | 
						|
  return iFile;                   // This is a temporary setting
 | 
						|
  } // end of GetProgMax
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  MUL Cardinality: returns table cardinality in number of rows.      */
 | 
						|
/*  This function can be called with a null argument to test the       */
 | 
						|
/*  availability of Cardinality implementation (1 yes, 0 no).          */
 | 
						|
/*  Can be used on Multiple FIX table only.                            */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::Cardinality(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (!g)
 | 
						|
    return Tdbp->Cardinality(g);
 | 
						|
 | 
						|
  if (!Filenames && InitFileNames(g))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  int n, card = 0;
 | 
						|
 | 
						|
  for (int i = 0; i < NumFiles; i++) {
 | 
						|
    Tdbp->SetFile(g, Filenames[i]);
 | 
						|
    Tdbp->ResetSize();
 | 
						|
 | 
						|
    if ((n = Tdbp->Cardinality(g)) < 0) {
 | 
						|
//    strcpy(g->Message, MSG(BAD_CARDINALITY));
 | 
						|
      return -1;
 | 
						|
      } // endif n
 | 
						|
 | 
						|
    card += n;
 | 
						|
    } // endfor i
 | 
						|
 | 
						|
  return card;
 | 
						|
  } // end of Cardinality
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Sum up the sizes of all sub-tables.                                */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::GetMaxSize(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (MaxSize < 0) {
 | 
						|
    int i;
 | 
						|
    int mxsz;
 | 
						|
 | 
						|
    if (trace(1))
 | 
						|
      htrc("TDBMUL::GetMaxSize: Filenames=%p\n", Filenames);
 | 
						|
    
 | 
						|
    if (!Filenames && InitFileNames(g))
 | 
						|
      return -1;
 | 
						|
 | 
						|
    if (Use == USE_OPEN) {
 | 
						|
      strcpy(g->Message, MSG(MAXSIZE_ERROR));
 | 
						|
      return -1;
 | 
						|
    } else
 | 
						|
      MaxSize = 0;
 | 
						|
 | 
						|
    for (i = 0; i < NumFiles; i++) {
 | 
						|
      Tdbp->SetFile(g, Filenames[i]);
 | 
						|
      Tdbp->ResetSize();
 | 
						|
 | 
						|
      if ((mxsz = Tdbp->GetMaxSize(g)) < 0) {
 | 
						|
        MaxSize = -1;
 | 
						|
        return mxsz;
 | 
						|
        } // endif mxsz
 | 
						|
 | 
						|
      MaxSize += mxsz;
 | 
						|
      } // endfor i
 | 
						|
 | 
						|
    } // endif MaxSize
 | 
						|
 | 
						|
  return MaxSize;
 | 
						|
  } // end of GetMaxSize
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Reset read/write position values.                                  */
 | 
						|
/***********************************************************************/
 | 
						|
void TDBMUL::ResetDB(void)
 | 
						|
  {
 | 
						|
  for (PCOL colp = Columns; colp; colp = colp->GetNext())
 | 
						|
    if (colp->GetAmType() == TYPE_AM_FILID)
 | 
						|
      colp->COLBLK::Reset();
 | 
						|
 | 
						|
  Tdbp->ResetDB();
 | 
						|
  } // end of ResetDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Returns RowId if b is false or Rownum if b is true.                */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::RowNumber(PGLOBAL g, bool b)
 | 
						|
  {
 | 
						|
  return ((b) ? 0 : Rows)
 | 
						|
       + ((iFile < NumFiles) ? Tdbp->RowNumber(g, b) : 1);
 | 
						|
  } // end of RowNumber
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  MUL Access Method opening routine.                                 */
 | 
						|
/*  Open first file, other will be opened sequencially when reading.   */
 | 
						|
/***********************************************************************/
 | 
						|
bool TDBMUL::OpenDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (trace(1))
 | 
						|
    htrc("MUL OpenDB: tdbp=%p tdb=R%d use=%d key=%p mode=%d\n",
 | 
						|
      this, Tdb_No, Use, To_Key_Col, Mode);
 | 
						|
 | 
						|
  if (Use == USE_OPEN) {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  Table already open, replace it at its beginning.               */
 | 
						|
    /*******************************************************************/
 | 
						|
    if (Filenames[iFile = 0]) {
 | 
						|
      Tdbp->CloseDB(g);
 | 
						|
      Tdbp->SetUse(USE_READY);
 | 
						|
      Tdbp->SetFile(g, Filenames[iFile = 0]);
 | 
						|
      Tdbp->ResetSize();
 | 
						|
      Rows = 0;
 | 
						|
      ResetDB();
 | 
						|
      return Tdbp->OpenDB(g);  // Re-open with new file name
 | 
						|
    } else
 | 
						|
      return false;
 | 
						|
 | 
						|
    } // endif use
 | 
						|
 | 
						|
  /*********************************************************************/
 | 
						|
  /*  We need to calculate MaxSize before opening the query.           */
 | 
						|
  /*********************************************************************/
 | 
						|
  if (GetMaxSize(g) < 0)
 | 
						|
    return true;
 | 
						|
 | 
						|
  /*********************************************************************/
 | 
						|
  /*  Open the first table file of the list.                           */
 | 
						|
  /*********************************************************************/
 | 
						|
//if (!Filenames && InitFileNames(g))     // was done in GetMaxSize
 | 
						|
//  return true;
 | 
						|
 | 
						|
  if (Filenames[iFile = 0]) {
 | 
						|
    Tdbp->SetFile(g, Filenames[0]);
 | 
						|
    Tdbp->SetMode(Mode);
 | 
						|
    Tdbp->ResetDB();
 | 
						|
    Tdbp->ResetSize();
 | 
						|
 | 
						|
    if (Tdbp->OpenDB(g))
 | 
						|
      return true;
 | 
						|
 | 
						|
    } // endif *Filenames
 | 
						|
 | 
						|
  Use = USE_OPEN;
 | 
						|
  return false;
 | 
						|
  } // end of OpenDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  ReadDB: Data Base read routine for MUL access method.              */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::ReadDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  int rc;
 | 
						|
 | 
						|
  if (NumFiles == 0)
 | 
						|
    return RC_EF;
 | 
						|
  else if (To_Kindex) {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  Reading is by an index table.                                  */
 | 
						|
    /*******************************************************************/
 | 
						|
    strcpy(g->Message, MSG(NO_INDEX_READ));
 | 
						|
    rc = RC_FX;
 | 
						|
  } else {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  Now start the reading process.                                 */
 | 
						|
    /*******************************************************************/
 | 
						|
   retry:
 | 
						|
    rc = Tdbp->ReadDB(g);
 | 
						|
 | 
						|
    if (rc == RC_EF) {
 | 
						|
      if (Tdbp->GetDef()->GetPseudo() & 1)
 | 
						|
        // Total number of rows met so far
 | 
						|
        Rows += Tdbp->RowNumber(g) - 1;
 | 
						|
 | 
						|
      if (++iFile < NumFiles) {
 | 
						|
        /***************************************************************/
 | 
						|
        /*  Continue reading from next table file.                     */
 | 
						|
        /***************************************************************/
 | 
						|
        Tdbp->CloseDB(g);
 | 
						|
        Tdbp->SetUse(USE_READY);
 | 
						|
        Tdbp->SetFile(g, Filenames[iFile]);
 | 
						|
        Tdbp->ResetSize();
 | 
						|
        ResetDB();
 | 
						|
 | 
						|
        if (Tdbp->OpenDB(g))     // Re-open with new file name
 | 
						|
          return RC_FX;
 | 
						|
 | 
						|
        goto retry;
 | 
						|
        } // endif iFile
 | 
						|
 | 
						|
    } else if (rc == RC_FX)
 | 
						|
      strcat(strcat(strcat(g->Message, " ("), Tdbp->GetFile(g)), ")");
 | 
						|
 | 
						|
  } // endif To_Kindex
 | 
						|
 | 
						|
  return rc;
 | 
						|
  } // end of ReadDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base write routine for MUL access method.                     */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::WriteDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  return Tdbp->WriteDB(g);
 | 
						|
//  strcpy(g->Message, MSG(TABMUL_READONLY));
 | 
						|
//  return RC_FX;                    // NIY
 | 
						|
  } // end of WriteDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base delete line routine for MUL access method.               */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBMUL::DeleteDB(PGLOBAL g, int)
 | 
						|
  {
 | 
						|
  // When implementing DELETE_MODE InitFileNames must be updated to
 | 
						|
  // eliminate CRLF under Windows if the file is read in binary.
 | 
						|
  strcpy(g->Message, MSG(TABMUL_READONLY));
 | 
						|
  return RC_FX;                                      // NIY
 | 
						|
  } // end of DeleteDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base close routine for MUL access method.                     */
 | 
						|
/***********************************************************************/
 | 
						|
void TDBMUL::CloseDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (NumFiles > 0) {
 | 
						|
    Tdbp->CloseDB(g);
 | 
						|
    iFile = NumFiles;
 | 
						|
    } // endif NumFiles
 | 
						|
 | 
						|
  } // end of CloseDB
 | 
						|
 | 
						|
#if 0
 | 
						|
/* ------------------------- Class TDBMSD ---------------------------- */
 | 
						|
 | 
						|
	// Method
 | 
						|
PTDB TDBMSD::Clone(PTABS t)
 | 
						|
{
 | 
						|
	PTDBMSD tp;
 | 
						|
	PGLOBAL g = t->G;        // Is this really useful ???
 | 
						|
 | 
						|
	tp = new(g) TDBMSD(this);
 | 
						|
	tp->Tdbp = Tdbp->Clone(t);
 | 
						|
	tp->Columns = tp->Tdbp->GetColumns();
 | 
						|
	return tp;
 | 
						|
} // end of Clone
 | 
						|
 | 
						|
PTDB TDBMSD::Duplicate(PGLOBAL g)
 | 
						|
{
 | 
						|
	PTDBMSD tmup = new(g) TDBMSD(this);
 | 
						|
 | 
						|
	tmup->Tdbp = Tdbp->Duplicate(g);
 | 
						|
	return tmup;
 | 
						|
} // end of Duplicate
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Initializes the table filename list.                               */
 | 
						|
/*  Note: tables created by concatenating the file components without  */
 | 
						|
/*  specifying the LRECL value (that should be restricted to _MAX_PATH)*/
 | 
						|
/*  have a LRECL that is the sum of the lengths of all components.     */
 | 
						|
/*  This is why we use a big filename array to take care of that.      */
 | 
						|
/***********************************************************************/
 | 
						|
bool TDBMSD::InitFileNames(PGLOBAL g)
 | 
						|
{
 | 
						|
#define PFNZ  4096
 | 
						|
#define FNSZ  (_MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT)
 | 
						|
	PTDBSDR dirp;
 | 
						|
	PSZ     pfn[PFNZ];
 | 
						|
	PSZ     filename;
 | 
						|
	int     rc, n = 0;
 | 
						|
 | 
						|
	if (trace(1))
 | 
						|
		htrc("in InitFileName: fn[]=%d\n", FNSZ);
 | 
						|
 | 
						|
	filename = (char*)PlugSubAlloc(g, NULL, FNSZ);
 | 
						|
 | 
						|
	// The sub table may need to refer to the Table original block
 | 
						|
	Tdbp->SetTable(To_Table);         // Was not set at construction
 | 
						|
 | 
						|
	PlugSetPath(filename, Tdbp->GetFile(g), Tdbp->GetPath());
 | 
						|
 | 
						|
	if (trace(1))
 | 
						|
		htrc("InitFileName: fn='%s'\n", filename);
 | 
						|
 | 
						|
	dirp = new(g) TDBSDR(filename);
 | 
						|
 | 
						|
	if (dirp->OpenDB(g))
 | 
						|
		return true;
 | 
						|
 | 
						|
	while (true)
 | 
						|
		if ((rc = dirp->ReadDB(g)) == RC_OK) {
 | 
						|
#if defined(_WIN32)
 | 
						|
			strcat(strcpy(filename, dirp->Drive), dirp->Direc);
 | 
						|
#else   // !_WIN32
 | 
						|
			strcpy(filename, dirp->Direc);
 | 
						|
#endif  // !_WIN32
 | 
						|
			strcat(strcat(filename, dirp->Fname), dirp->Ftype);
 | 
						|
			pfn[n++] = PlugDup(g, filename);
 | 
						|
		} else
 | 
						|
			break;
 | 
						|
 | 
						|
	if (rc == RC_FX)
 | 
						|
		return true;
 | 
						|
 | 
						|
	if (n) {
 | 
						|
	  Filenames = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*));
 | 
						|
 | 
						|
	  for (int i = 0; i < n; i++)
 | 
						|
		  Filenames[i] = pfn[i];
 | 
						|
 | 
						|
	} else {
 | 
						|
	  Filenames = (char**)PlugSubAlloc(g, NULL, sizeof(char*));
 | 
						|
	  Filenames[0] = NULL;
 | 
						|
	} // endif n
 | 
						|
 | 
						|
	NumFiles = n;
 | 
						|
	return false;
 | 
						|
} // end of InitFileNames
 | 
						|
#endif // 0
 | 
						|
 | 
						|
	/* --------------------------- Class DIRDEF -------------------------- */
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DefineAM: define specific AM block values from XDB file.           */
 | 
						|
/***********************************************************************/
 | 
						|
bool DIRDEF::DefineAM(PGLOBAL g, LPCSTR, int)
 | 
						|
  {
 | 
						|
  Desc = Fn = GetStringCatInfo(g, "Filename", NULL);
 | 
						|
  Incl = GetBoolCatInfo("Subdir", false);
 | 
						|
	Huge = GetBoolCatInfo("Huge", false);
 | 
						|
	Nodir = GetBoolCatInfo("Nodir", true);
 | 
						|
  return false;
 | 
						|
  } // end of DefineAM
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  GetTable: makes a new Table Description Block.                     */
 | 
						|
/***********************************************************************/
 | 
						|
PTDB DIRDEF::GetTable(PGLOBAL g, MODE)
 | 
						|
  {
 | 
						|
#if 0
 | 
						|
  if (Huge)
 | 
						|
    return new(g) TDBDHR(this);        // Not implemented yet
 | 
						|
  else
 | 
						|
#endif
 | 
						|
  if (Incl)
 | 
						|
    return new(g) TDBSDR(this);        // Including sub-directory files
 | 
						|
  else
 | 
						|
    return new(g) TDBDIR(this);    // Not Including sub-directory files
 | 
						|
 | 
						|
  } // end of GetTable
 | 
						|
 | 
						|
/* ------------------------- Class TDBDIR ---------------------------- */
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  TABDIR constructors.                                               */
 | 
						|
/***********************************************************************/
 | 
						|
void TDBDIR::Init(void)
 | 
						|
{
 | 
						|
	iFile = 0;
 | 
						|
#if defined(_WIN32)
 | 
						|
	Dvalp = NULL;
 | 
						|
	memset(&FileData, 0, sizeof(_finddata_t));
 | 
						|
	hSearch = INVALID_HANDLE_VALUE;
 | 
						|
	*Drive = '\0';
 | 
						|
#else   // !_WIN32
 | 
						|
	memset(&Fileinfo, 0, sizeof(struct stat));
 | 
						|
	Entry = NULL;
 | 
						|
	Dir = NULL;
 | 
						|
	Done = false;
 | 
						|
	*Pattern = '\0';
 | 
						|
#endif  // !_WIN32
 | 
						|
	*Fpath = '\0';
 | 
						|
	*Direc = '\0';
 | 
						|
	*Fname = '\0';
 | 
						|
	*Ftype = '\0';
 | 
						|
}	// end of Init
 | 
						|
 | 
						|
TDBDIR::TDBDIR(PDIRDEF tdp) : TDBASE(tdp)
 | 
						|
{
 | 
						|
  To_File = tdp->Fn;
 | 
						|
	Nodir = tdp->Nodir;
 | 
						|
	Init();
 | 
						|
} // end of TDBDIR standard constructor
 | 
						|
 | 
						|
TDBDIR::TDBDIR(PSZ fpat) : TDBASE((PTABDEF)NULL)
 | 
						|
{
 | 
						|
	To_File = fpat;
 | 
						|
	Nodir = true;
 | 
						|
	Init();
 | 
						|
} // end of TDBDIR constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Initialize/get the components of the search file pattern.          */
 | 
						|
/***********************************************************************/
 | 
						|
char* TDBDIR::Path(PGLOBAL g)
 | 
						|
  {
 | 
						|
    (void) PlgGetCatalog(g);                    // XXX Should be removed?
 | 
						|
    PTABDEF defp = (PTABDEF)To_Def;
 | 
						|
 | 
						|
#if defined(_WIN32)
 | 
						|
  if (!*Drive) {
 | 
						|
    PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL);
 | 
						|
    _splitpath(Fpath, Drive, Direc, Fname, Ftype);
 | 
						|
  } else
 | 
						|
    _makepath(Fpath, Drive, Direc, Fname, Ftype); // Usefull for TDBSDR
 | 
						|
 | 
						|
  return Fpath;
 | 
						|
#else   // !_WIN32
 | 
						|
  if (!Done) {
 | 
						|
    PlugSetPath(Fpath, To_File, defp ? defp->GetPath() : NULL);
 | 
						|
    _splitpath(Fpath, NULL, Direc, Fname, Ftype);
 | 
						|
    strcat(strcpy(Pattern, Fname), Ftype);
 | 
						|
    Done = true;
 | 
						|
    } // endif Done
 | 
						|
 | 
						|
  return Pattern;
 | 
						|
#endif  // !_WIN32
 | 
						|
  } // end of Path
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Allocate DIR column description block.                             */
 | 
						|
/***********************************************************************/
 | 
						|
PCOL TDBDIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
 | 
						|
  {
 | 
						|
  return new(g) DIRCOL(cdp, this, cprec, n);
 | 
						|
  } // end of MakeCol
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DIR GetMaxSize: returns the number of retrieved files.             */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBDIR::GetMaxSize(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (MaxSize < 0) {
 | 
						|
    int n = -1;
 | 
						|
#if defined(_WIN32)
 | 
						|
    int rc;
 | 
						|
    // Start searching files in the target directory.
 | 
						|
		hSearch = FindFirstFile(Path(g), &FileData);
 | 
						|
 | 
						|
    if (hSearch == INVALID_HANDLE_VALUE) {
 | 
						|
			rc = GetLastError();
 | 
						|
 | 
						|
			if (rc != ERROR_FILE_NOT_FOUND) {
 | 
						|
				char buf[512];
 | 
						|
 | 
						|
				FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 | 
						|
					            FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
						|
					NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL);
 | 
						|
				snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), buf);
 | 
						|
				return -1;
 | 
						|
			} // endif rc
 | 
						|
 | 
						|
			return 0;
 | 
						|
		} // endif hSearch
 | 
						|
 | 
						|
		while (true) {
 | 
						|
			if (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
 | 
						|
				n++;
 | 
						|
 | 
						|
			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 -1;
 | 
						|
				} // endif rc
 | 
						|
 | 
						|
				break;
 | 
						|
			} // endif Next
 | 
						|
 | 
						|
		} // endwhile
 | 
						|
 | 
						|
    // Close the search handle.
 | 
						|
		FindClose(hSearch);
 | 
						|
#else   // !_WIN32
 | 
						|
    Path(g);
 | 
						|
 | 
						|
    // Start searching files in the target directory.
 | 
						|
    if (!(Dir = opendir(Direc))) {
 | 
						|
      snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno));
 | 
						|
      return -1;
 | 
						|
      } // endif dir
 | 
						|
 | 
						|
    while ((Entry = readdir(Dir))) {
 | 
						|
      strcat(strcpy(Fpath, Direc), Entry->d_name);
 | 
						|
 | 
						|
      if (lstat(Fpath, &Fileinfo) < 0) {
 | 
						|
        snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno));
 | 
						|
        return -1;
 | 
						|
      } else if (S_ISREG(Fileinfo.st_mode))
 | 
						|
        // Test whether the file name matches the table name filter
 | 
						|
        if (!fnmatch(Pattern, Entry->d_name, 0))
 | 
						|
          n++;      // We have a match
 | 
						|
 | 
						|
      } // endwhile Entry
 | 
						|
 | 
						|
    // Close the DIR handle.
 | 
						|
    closedir(Dir);
 | 
						|
#endif  // !_WIN32
 | 
						|
    MaxSize = n;
 | 
						|
    } // endif MaxSize
 | 
						|
 | 
						|
  return MaxSize;
 | 
						|
  } // end of GetMaxSize
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DIR Access Method opening routine.                                 */
 | 
						|
/*  Open first file, other will be opened sequencially when reading.   */
 | 
						|
/***********************************************************************/
 | 
						|
bool TDBDIR::OpenDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (trace(1))
 | 
						|
    htrc("DIR OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n",
 | 
						|
      this, Tdb_No, Use, Mode);
 | 
						|
 | 
						|
  if (Use == USE_OPEN) {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  Table already open, reopen it.                                 */
 | 
						|
    /*******************************************************************/
 | 
						|
    CloseDB(g);
 | 
						|
    SetUse(USE_READY);
 | 
						|
    } // endif use
 | 
						|
 | 
						|
  Use = USE_OPEN;
 | 
						|
#if !defined(_WIN32)
 | 
						|
  Path(g);                          // Be sure it is done
 | 
						|
  Dir = NULL;                       // For ReadDB
 | 
						|
#endif   // !_WIN32
 | 
						|
  return false;
 | 
						|
  } // end of OpenDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base read routine for DIR access method.                      */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBDIR::ReadDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  int rc = RC_OK;
 | 
						|
 | 
						|
#if defined(_WIN32)
 | 
						|
	do {
 | 
						|
		if (hSearch == INVALID_HANDLE_VALUE) {
 | 
						|
			/*****************************************************************/
 | 
						|
			/*  Start searching files in the target directory. The use of    */
 | 
						|
			/*  the Path function is required when called from TDBSDR.       */
 | 
						|
			/*****************************************************************/
 | 
						|
			hSearch = FindFirstFile(Path(g), &FileData);
 | 
						|
 | 
						|
			if (hSearch == INVALID_HANDLE_VALUE) {
 | 
						|
				rc = RC_EF;
 | 
						|
				break;
 | 
						|
			} else
 | 
						|
				iFile++;
 | 
						|
 | 
						|
		} else {
 | 
						|
			if (!FindNextFile(hSearch, &FileData)) {
 | 
						|
				// Restore file name and type pattern
 | 
						|
				_splitpath(To_File, NULL, NULL, Fname, Ftype);
 | 
						|
				rc = RC_EF;
 | 
						|
				break;
 | 
						|
			} else
 | 
						|
				iFile++;
 | 
						|
 | 
						|
		} // endif hSearch
 | 
						|
 | 
						|
	} while (Nodir && FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
 | 
						|
 | 
						|
  if (rc == RC_OK)
 | 
						|
    _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype);
 | 
						|
 | 
						|
#else   // !Win32
 | 
						|
  rc = RC_NF;
 | 
						|
 | 
						|
  if (!Dir)
 | 
						|
    // Start searching files in the target directory.
 | 
						|
    if (!(Dir = opendir(Direc))) {
 | 
						|
      snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno));
 | 
						|
      rc = RC_FX;
 | 
						|
      } // endif dir
 | 
						|
 | 
						|
  while (rc == RC_NF)
 | 
						|
    if ((Entry = readdir(Dir))) {
 | 
						|
      // We need the Fileinfo structure to get info about the file
 | 
						|
      strcat(strcpy(Fpath, Direc), Entry->d_name);
 | 
						|
 | 
						|
      if (lstat(Fpath, &Fileinfo) < 0) {
 | 
						|
        snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno));
 | 
						|
        rc = RC_FX;
 | 
						|
      } else if (S_ISREG(Fileinfo.st_mode))
 | 
						|
        // Test whether the file name matches the table name filter
 | 
						|
        if (!fnmatch(Pattern, Entry->d_name, 0)) {
 | 
						|
          iFile++;      // We have a match
 | 
						|
          _splitpath(Entry->d_name, NULL, NULL, Fname, Ftype);
 | 
						|
          rc = RC_OK;
 | 
						|
          } // endif fnmatch
 | 
						|
 | 
						|
    } else {
 | 
						|
      // Restore file name and type pattern
 | 
						|
      _splitpath(To_File, NULL, NULL, Fname, Ftype);
 | 
						|
      rc = RC_EF;
 | 
						|
    } // endif Entry
 | 
						|
 | 
						|
#endif  // !_WIN32
 | 
						|
 | 
						|
  return rc;
 | 
						|
  } // end of ReadDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base write routine for DIR access method.                     */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBDIR::WriteDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  strcpy(g->Message, MSG(TABDIR_READONLY));
 | 
						|
  return RC_FX;                    // NIY
 | 
						|
  } // end of WriteDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base delete line routine for DIR access method.               */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBDIR::DeleteDB(PGLOBAL g, int)
 | 
						|
  {
 | 
						|
  strcpy(g->Message, MSG(TABDIR_READONLY));
 | 
						|
  return RC_FX;                                      // NIY
 | 
						|
  } // end of DeleteDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base close routine for MUL access method.                     */
 | 
						|
/***********************************************************************/
 | 
						|
void TDBDIR::CloseDB(PGLOBAL)
 | 
						|
  {
 | 
						|
#if defined(_WIN32)
 | 
						|
  // Close the search handle.
 | 
						|
  FindClose(hSearch);
 | 
						|
	hSearch = INVALID_HANDLE_VALUE;
 | 
						|
#else   // !_WIN32
 | 
						|
  // Close the DIR handle
 | 
						|
  if (Dir) {
 | 
						|
    closedir(Dir);
 | 
						|
    Dir = NULL;
 | 
						|
    } // endif dir
 | 
						|
#endif  // !_WIN32
 | 
						|
  iFile = 0;
 | 
						|
  } // end of CloseDB
 | 
						|
 | 
						|
// ------------------------ DIRCOL functions ----------------------------
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DIRCOL public constructor.                                         */
 | 
						|
/***********************************************************************/
 | 
						|
DIRCOL::DIRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ)
 | 
						|
  : COLBLK(cdp, tdbp, i)
 | 
						|
  {
 | 
						|
  if (cprec) {
 | 
						|
    Next = cprec->GetNext();
 | 
						|
    cprec->SetNext(this);
 | 
						|
  } else {
 | 
						|
    Next = tdbp->GetColumns();
 | 
						|
    tdbp->SetColumns(this);
 | 
						|
  } // endif cprec
 | 
						|
 | 
						|
  // Set additional DIR access method information for column.
 | 
						|
	Tdbp = (PTDBDIR)tdbp;
 | 
						|
  N = cdp->GetOffset();
 | 
						|
  } // end of DIRCOL constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DIRCOL constructor used for copying columns.                       */
 | 
						|
/*  tdbp is the pointer to the new table descriptor.                   */
 | 
						|
/***********************************************************************/
 | 
						|
DIRCOL::DIRCOL(DIRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
 | 
						|
  {
 | 
						|
	Tdbp = (PTDBDIR)tdbp;
 | 
						|
	N = col1->N;
 | 
						|
  } // end of DIRCOL copy constructor
 | 
						|
 | 
						|
#if defined(_WIN32)
 | 
						|
/***********************************************************************/
 | 
						|
/*  Retrieve time information from FileData.                           */
 | 
						|
/***********************************************************************/
 | 
						|
void DIRCOL::SetTimeValue(PGLOBAL g, FILETIME& ftime)
 | 
						|
{
 | 
						|
	char       tsp[24];
 | 
						|
	SYSTEMTIME stp;
 | 
						|
 | 
						|
	if (FileTimeToSystemTime(&ftime, &stp)) {
 | 
						|
		sprintf(tsp, "%04d-%02d-%02d %02d:%02d:%02d",
 | 
						|
			stp.wYear, stp.wMonth, stp.wDay, stp.wHour, stp.wMinute, stp.wSecond);
 | 
						|
 | 
						|
		if (Value->GetType() != TYPE_STRING) {
 | 
						|
			if (!Tdbp->Dvalp)
 | 
						|
				Tdbp->Dvalp = AllocateValue(g, TYPE_DATE, 20, 0, false,
 | 
						|
					"YYYY-MM-DD hh:mm:ss");
 | 
						|
 | 
						|
			Tdbp->Dvalp->SetValue_psz(tsp);
 | 
						|
			Value->SetValue_pval(Tdbp->Dvalp);
 | 
						|
		} else
 | 
						|
			Value->SetValue_psz(tsp);
 | 
						|
 | 
						|
	} else
 | 
						|
		Value->Reset();
 | 
						|
 | 
						|
} // end of SetTimeValue
 | 
						|
#endif   // _WIN32
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  ReadColumn: what this routine does is to access the information    */
 | 
						|
/*  corresponding to this column and convert it to buffer type.        */
 | 
						|
/***********************************************************************/
 | 
						|
void DIRCOL::ReadColumn(PGLOBAL g)
 | 
						|
	{
 | 
						|
  if (trace(1))
 | 
						|
    htrc("DIR ReadColumn: col %s R%d use=%.4X status=%.4X type=%d N=%d\n",
 | 
						|
      Name, Tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N);
 | 
						|
 | 
						|
  /*********************************************************************/
 | 
						|
  /*  Retrieve the information corresponding to the column number.     */
 | 
						|
  /*********************************************************************/
 | 
						|
  switch (N) {
 | 
						|
#if defined(_WIN32)
 | 
						|
    case  0: Value->SetValue_psz(Tdbp->Drive); break;
 | 
						|
#endif   // _WIN32
 | 
						|
    case  1: Value->SetValue_psz(Tdbp->Direc); break;
 | 
						|
    case  2: Value->SetValue_psz(Tdbp->Fname); break;
 | 
						|
    case  3: Value->SetValue_psz(Tdbp->Ftype); break;
 | 
						|
#if defined(_WIN32)
 | 
						|
    case  4: Value->SetValue((int)Tdbp->FileData.dwFileAttributes); break;
 | 
						|
		case  5: Value->SetValue((int)Tdbp->FileData.nFileSizeLow); break;
 | 
						|
    case  6: SetTimeValue(g, Tdbp->FileData.ftLastWriteTime);   break;
 | 
						|
    case  7: SetTimeValue(g, Tdbp->FileData.ftCreationTime);    break;
 | 
						|
    case  8: SetTimeValue(g, Tdbp->FileData.ftLastAccessTime);  break;
 | 
						|
#else   // !_WIN32
 | 
						|
    case  4: Value->SetValue((int)Tdbp->Fileinfo.st_mode);  break;
 | 
						|
    case  5: Value->SetValue((int)Tdbp->Fileinfo.st_size);  break;
 | 
						|
    case  6: Value->SetValue((int)Tdbp->Fileinfo.st_mtime); break;
 | 
						|
    case  7: Value->SetValue((int)Tdbp->Fileinfo.st_ctime); break;
 | 
						|
    case  8: Value->SetValue((int)Tdbp->Fileinfo.st_atime); break;
 | 
						|
    case  9: Value->SetValue((int)Tdbp->Fileinfo.st_uid);   break;
 | 
						|
    case 10: Value->SetValue((int)Tdbp->Fileinfo.st_gid);   break;
 | 
						|
#endif  // !_WIN32
 | 
						|
    default:
 | 
						|
      snprintf(g->Message, sizeof(g->Message), MSG(INV_DIRCOL_OFST), N);
 | 
						|
			throw GetAmType();
 | 
						|
	} // endswitch N
 | 
						|
 | 
						|
  } // end of ReadColumn
 | 
						|
 | 
						|
/* ------------------------- Class TDBSDR ---------------------------- */
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  SDR GetMaxSize: returns the number of retrieved files.             */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBSDR::GetMaxSize(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (MaxSize < 0) {
 | 
						|
    Path(g);
 | 
						|
    MaxSize = FindInDir(g);
 | 
						|
    } // endif MaxSize
 | 
						|
 | 
						|
  return MaxSize;
 | 
						|
  } // end of GetMaxSize
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  SDR FindInDir: returns the number of retrieved files.              */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBSDR::FindInDir(PGLOBAL g)
 | 
						|
  {
 | 
						|
  int    n = 0;
 | 
						|
  size_t m = strlen(Direc);
 | 
						|
 | 
						|
  // Start searching files in the target directory.
 | 
						|
#if defined(_WIN32)
 | 
						|
	int rc;
 | 
						|
	HANDLE h;
 | 
						|
 | 
						|
#if defined(PATHMATCHSPEC)
 | 
						|
	if (!*Drive)
 | 
						|
		Path(g);
 | 
						|
 | 
						|
	_makepath(Fpath, Drive, Direc, "*", "*");
 | 
						|
 | 
						|
	h = FindFirstFile(Fpath, &FileData);
 | 
						|
 | 
						|
  if (h == INVALID_HANDLE_VALUE) {
 | 
						|
		rc = GetLastError();
 | 
						|
 | 
						|
		if (rc != ERROR_FILE_NOT_FOUND) {
 | 
						|
			char buf[512];
 | 
						|
 | 
						|
			FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 | 
						|
				FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
						|
				NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL);
 | 
						|
			snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), buf);
 | 
						|
			return -1;
 | 
						|
		} // endif rc
 | 
						|
 | 
						|
		return 0;
 | 
						|
	} // endif h
 | 
						|
 | 
						|
	while (true) {
 | 
						|
		if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
 | 
						|
			  *FileData.cFileName != '.') {
 | 
						|
			// Look in the name sub-directory
 | 
						|
			strcat(strcat(Direc, FileData.cFileName), "/");
 | 
						|
			n += FindInDir(g);
 | 
						|
			Direc[m] = '\0';         // Restore path
 | 
						|
		} else if (PathMatchSpec(FileData.cFileName, Fpath))
 | 
						|
			n++;
 | 
						|
 | 
						|
		if (!FindNextFile(h, &FileData)) {
 | 
						|
			rc = GetLastError();
 | 
						|
 | 
						|
			if (rc != ERROR_NO_MORE_FILES) {
 | 
						|
				snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc);
 | 
						|
				FindClose(h);
 | 
						|
				return -1;
 | 
						|
			} // endif rc
 | 
						|
 | 
						|
			break;
 | 
						|
		} // endif Next
 | 
						|
 | 
						|
	} // endwhile
 | 
						|
#else   // !PATHMATCHSPEC
 | 
						|
	h = FindFirstFile(Path(g), &FileData);
 | 
						|
 | 
						|
	if (h == INVALID_HANDLE_VALUE) {
 | 
						|
		rc = GetLastError();
 | 
						|
 | 
						|
		if (rc != ERROR_FILE_NOT_FOUND) {
 | 
						|
			char buf[512];
 | 
						|
 | 
						|
			FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 | 
						|
				FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
						|
				NULL, GetLastError(), 0, (LPTSTR)&buf, sizeof(buf), NULL);
 | 
						|
			snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), buf);
 | 
						|
			return -1;
 | 
						|
		} // endif rc
 | 
						|
 | 
						|
		return 0;
 | 
						|
	} // endif hSearch
 | 
						|
 | 
						|
	while (true) {
 | 
						|
		n++;
 | 
						|
 | 
						|
		if (!FindNextFile(h, &FileData)) {
 | 
						|
			rc = GetLastError();
 | 
						|
 | 
						|
			if (rc != ERROR_NO_MORE_FILES) {
 | 
						|
				snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc);
 | 
						|
				FindClose(h);
 | 
						|
				return -1;
 | 
						|
			} // endif rc
 | 
						|
 | 
						|
			break;
 | 
						|
		} // endif Next
 | 
						|
 | 
						|
	} // endwhile
 | 
						|
 | 
						|
	// Now search files in sub-directories.
 | 
						|
	_makepath(Fpath, Drive, Direc, "*", ".");
 | 
						|
	h = FindFirstFile(Fpath, &FileData);
 | 
						|
 | 
						|
	if (h != INVALID_HANDLE_VALUE) {
 | 
						|
		while (true) {
 | 
						|
			if ((FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
 | 
						|
				  *FileData.cFileName != '.') {
 | 
						|
				// Look in the name sub-directory
 | 
						|
				strcat(strcat(Direc, FileData.cFileName), "/");
 | 
						|
				n += FindInDir(g);
 | 
						|
				Direc[m] = '\0';         // Restore path
 | 
						|
			} // endif SUBDIR
 | 
						|
 | 
						|
			if (!FindNextFile(h, &FileData))
 | 
						|
				break;
 | 
						|
 | 
						|
		} // endwhile
 | 
						|
 | 
						|
	} // endif h
 | 
						|
#endif  // !PATHMATCHSPEC
 | 
						|
 | 
						|
  // Close the search handle.
 | 
						|
	FindClose(h);
 | 
						|
#else   // !_WIN32
 | 
						|
  int k;
 | 
						|
  DIR *dir = opendir(Direc);
 | 
						|
 | 
						|
  if (!dir) {
 | 
						|
    snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno));
 | 
						|
    return -1;
 | 
						|
    } // endif dir
 | 
						|
 | 
						|
  while ((Entry = readdir(dir))) {
 | 
						|
    strcat(strcpy(Fpath, Direc), Entry->d_name);
 | 
						|
 | 
						|
    if (lstat(Fpath, &Fileinfo) < 0) {
 | 
						|
      snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno));
 | 
						|
      return -1;
 | 
						|
    } else if (S_ISDIR(Fileinfo.st_mode) && *Entry->d_name != '.') {
 | 
						|
      // Look in the name sub-directory
 | 
						|
      strcat(strcat(Direc, Entry->d_name), "/");
 | 
						|
 | 
						|
      if ((k= FindInDir(g)) < 0)
 | 
						|
        return k;
 | 
						|
      else
 | 
						|
        n += k;
 | 
						|
 | 
						|
      Direc[m] = '\0';         // Restore path
 | 
						|
    } else if (S_ISREG(Fileinfo.st_mode))
 | 
						|
      // Test whether the file name matches the table name filter
 | 
						|
      if (!fnmatch(Pattern, Entry->d_name, 0))
 | 
						|
        n++;      // We have a match
 | 
						|
 | 
						|
    } // endwhile readdir
 | 
						|
 | 
						|
  // Close the DIR handle.
 | 
						|
  closedir(dir);
 | 
						|
#endif  // !_WIN32
 | 
						|
 | 
						|
  return n;
 | 
						|
  } // end of FindInDir
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DIR Access Method opening routine.                                 */
 | 
						|
/*  Open first file, other will be opened sequencially when reading.   */
 | 
						|
/***********************************************************************/
 | 
						|
bool TDBSDR::OpenDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (!Sub) {
 | 
						|
    Path(g);
 | 
						|
    Sub = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR));
 | 
						|
    Sub->Next = NULL;
 | 
						|
    Sub->Prev = NULL;
 | 
						|
#if defined(_WIN32)
 | 
						|
    Sub->H = INVALID_HANDLE_VALUE;
 | 
						|
    Sub->Len = strlen(Direc);
 | 
						|
#else   // !_WIN32
 | 
						|
    Sub->D = NULL;
 | 
						|
    Sub->Len = 0;
 | 
						|
#endif  // !_WIN32
 | 
						|
    } // endif To_Sub
 | 
						|
 | 
						|
  return TDBDIR::OpenDB(g);
 | 
						|
  } // end of OpenDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base read routine for SDR access method.                      */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBSDR::ReadDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  int rc;
 | 
						|
 | 
						|
#if defined(_WIN32)
 | 
						|
 again:
 | 
						|
  rc = TDBDIR::ReadDB(g);
 | 
						|
 | 
						|
  if (rc == RC_EF) {
 | 
						|
    // Are there more files in sub-directories
 | 
						|
   retry:
 | 
						|
    do {
 | 
						|
      if (Sub->H == INVALID_HANDLE_VALUE) {
 | 
						|
//      _makepath(Fpath, Drive, Direc, "*", ".");		 why was this made?
 | 
						|
				_makepath(Fpath, Drive, Direc, "*", NULL);
 | 
						|
				Sub->H = FindFirstFile(Fpath, &FileData);
 | 
						|
      } else if (!FindNextFile(Sub->H, &FileData)) {
 | 
						|
        FindClose(Sub->H);
 | 
						|
        Sub->H = INVALID_HANDLE_VALUE;
 | 
						|
        *FileData.cFileName= '\0';
 | 
						|
				break;
 | 
						|
      } // endif findnext
 | 
						|
 | 
						|
    } while(!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
 | 
						|
    		(*FileData.cFileName == '.' && 
 | 
						|
			  (!FileData.cFileName[1] || FileData.cFileName[1] == '.')));
 | 
						|
 | 
						|
    if (Sub->H == INVALID_HANDLE_VALUE) {
 | 
						|
      // No more sub-directories. Are we in a sub-directory?
 | 
						|
      if (!Sub->Prev)
 | 
						|
        return rc;               // No, all is finished
 | 
						|
 | 
						|
      // here we must continue in the parent directory
 | 
						|
      Sub = Sub->Prev;
 | 
						|
      goto retry;
 | 
						|
    } else {
 | 
						|
      // Search next sub-directory
 | 
						|
      Direc[Sub->Len] = '\0';
 | 
						|
 | 
						|
      if (!Sub->Next) {
 | 
						|
        PSUBDIR sup;
 | 
						|
 | 
						|
        sup = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR));
 | 
						|
        sup->Next = NULL;
 | 
						|
        sup->Prev = Sub;
 | 
						|
        sup->H = INVALID_HANDLE_VALUE;
 | 
						|
        Sub->Next = sup;
 | 
						|
        } // endif Next
 | 
						|
 | 
						|
      Sub = Sub->Next;
 | 
						|
      strcat(strcat(Direc, FileData.cFileName), "/");
 | 
						|
      Sub->Len = strlen(Direc);
 | 
						|
 | 
						|
      // Reset Hsearch used by TDBDIR::ReadDB
 | 
						|
			FindClose(hSearch);
 | 
						|
			hSearch = INVALID_HANDLE_VALUE;
 | 
						|
      goto again;
 | 
						|
    } // endif H
 | 
						|
 | 
						|
    } // endif rc
 | 
						|
#else   // !_WIN32
 | 
						|
  rc = RC_NF;
 | 
						|
 | 
						|
 again:
 | 
						|
  if (!Sub->D)
 | 
						|
    // Start searching files in the target directory.
 | 
						|
    if (!(Sub->D = opendir(Direc))) {
 | 
						|
      snprintf(g->Message, sizeof(g->Message), MSG(BAD_DIRECTORY), Direc, strerror(errno));
 | 
						|
      rc = RC_FX;
 | 
						|
      } // endif dir
 | 
						|
 | 
						|
  while (rc == RC_NF)
 | 
						|
    if ((Entry = readdir(Sub->D))) {
 | 
						|
      // We need the Fileinfo structure to get info about the file
 | 
						|
      strcat(strcpy(Fpath, Direc), Entry->d_name);
 | 
						|
 | 
						|
      if (lstat(Fpath, &Fileinfo) < 0) {
 | 
						|
        snprintf(g->Message, sizeof(g->Message), "%s: %s", Fpath, strerror(errno));
 | 
						|
        rc = RC_FX;
 | 
						|
      } else if (S_ISDIR(Fileinfo.st_mode) && strcmp(Entry->d_name, ".")
 | 
						|
			                                     && strcmp(Entry->d_name, "..")) {
 | 
						|
        // Look in the name sub-directory
 | 
						|
        if (!Sub->Next) {
 | 
						|
          PSUBDIR sup;
 | 
						|
 | 
						|
          sup = (PSUBDIR)PlugSubAlloc(g, NULL, sizeof(SUBDIR));
 | 
						|
          sup->Next = NULL;
 | 
						|
          sup->Prev = Sub;
 | 
						|
          Sub->Next = sup;
 | 
						|
          } // endif Next
 | 
						|
 | 
						|
        Sub = Sub->Next;
 | 
						|
        Sub->D = NULL;
 | 
						|
        Sub->Len = strlen(Direc);
 | 
						|
        strcat(strcat(Direc, Entry->d_name), "/");
 | 
						|
        goto again;
 | 
						|
      } else if (S_ISREG(Fileinfo.st_mode))
 | 
						|
        // Test whether the file name matches the table name filter
 | 
						|
        if (!fnmatch(Pattern, Entry->d_name, 0)) {
 | 
						|
          iFile++;      // We have a match
 | 
						|
          _splitpath(Entry->d_name, NULL, NULL, Fname, Ftype);
 | 
						|
          rc = RC_OK;
 | 
						|
          } // endif fnmatch
 | 
						|
 | 
						|
    } else {
 | 
						|
      // No more files. Close the DIR handle.
 | 
						|
      closedir(Sub->D);
 | 
						|
 | 
						|
      // Are we in a sub-directory?
 | 
						|
      if (Sub->Prev) {
 | 
						|
        // Yes, we must continue in the parent directory
 | 
						|
        Direc[Sub->Len] = '\0';
 | 
						|
        Sub = Sub->Prev;
 | 
						|
      } else
 | 
						|
        rc = RC_EF;              // No, all is finished
 | 
						|
 | 
						|
    } // endif Entry
 | 
						|
 | 
						|
#endif  // !_WIN32
 | 
						|
 | 
						|
  return rc;
 | 
						|
  } // end of ReadDB
 | 
						|
 | 
						|
#if 0
 | 
						|
/* ------------------------- Class TDBDHR ---------------------------- */
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  TABDHR constructors.                                               */
 | 
						|
/***********************************************************************/
 | 
						|
TDBDHR::TDBDHR(PDHRDEF tdp) : TDBASE(tdp)
 | 
						|
  {
 | 
						|
  memset(&FileData, 0, sizeof(WIN32_FIND_DATA));
 | 
						|
  Hsearch = INVALID_HANDLE_VALUE;
 | 
						|
  iFile = 0;
 | 
						|
  *Drive = '\0';
 | 
						|
  *Direc = '\0';
 | 
						|
  *Fname = '\0';
 | 
						|
  *Ftype = '\0';
 | 
						|
  } // end of TDBDHR standard constructor
 | 
						|
 | 
						|
TDBDHR::TDBDHR(PTDBDHR tdbp) : TDBASE(tdbp)
 | 
						|
  {
 | 
						|
  FileData = tdbp->FileData;
 | 
						|
  Hsearch = tdbp->Hsearch;
 | 
						|
  iFile = tdbp->iFile;
 | 
						|
  strcpy(Drive, tdbp->Drive);
 | 
						|
  strcpy(Direc, tdbp->Direc);
 | 
						|
  strcpy(Fname, tdbp->Fname);
 | 
						|
  strcpy(Ftype, tdbp->Ftype);
 | 
						|
  } // end of TDBDHR copy constructor
 | 
						|
 | 
						|
// Method
 | 
						|
PTDB TDBDHR::Clone(PTABS t)
 | 
						|
  {
 | 
						|
  PTDB    tp;
 | 
						|
  PGLOBAL g = t->G;        // Is this really useful ???
 | 
						|
 | 
						|
  tp = new(g) TDBDHR(this);
 | 
						|
  tp->Columns = Columns;
 | 
						|
  return tp;
 | 
						|
  } // end of Clone
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Allocate DHR column description block.                             */
 | 
						|
/***********************************************************************/
 | 
						|
PCOL TDBDHR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
 | 
						|
  {
 | 
						|
  return new(g) DHRCOL(cdp, this, cprec, n);
 | 
						|
  } // end of MakeCol
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DHR GetMaxSize: returns the number of retrieved files.             */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBDHR::GetMaxSize(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (MaxSize < 0) {
 | 
						|
    char    filename[_MAX_PATH];
 | 
						|
    int     i, rc;
 | 
						|
    int    n = -1;
 | 
						|
    HANDLE  h;
 | 
						|
    PDBUSER dup = PlgGetUser(g);
 | 
						|
 | 
						|
    PlugSetPath(filename, To_File, dup->Path);
 | 
						|
 | 
						|
    // Start searching files in the target directory.
 | 
						|
    h = FindFirstFile(filename, &FileData);
 | 
						|
 | 
						|
    if (h == INVALID_HANDLE_VALUE) {
 | 
						|
      switch (rc = GetLastError()) {
 | 
						|
        case ERROR_NO_MORE_FILES:
 | 
						|
        case ERROR_FILE_NOT_FOUND:
 | 
						|
          n = 0;
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 | 
						|
                        FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
						|
                        NULL, rc, 0,
 | 
						|
                        (LPTSTR)&filename, sizeof(filename), NULL);
 | 
						|
          snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), filename);
 | 
						|
        } // endswitch rc
 | 
						|
 | 
						|
    } else {
 | 
						|
      for (n = 1;; n++)
 | 
						|
        if (!FindNextFile(h, &FileData)) {
 | 
						|
          rc = GetLastError();
 | 
						|
 | 
						|
          if (rc != ERROR_NO_MORE_FILES) {
 | 
						|
            snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), rc);
 | 
						|
            n = -1;
 | 
						|
            } // endif rc
 | 
						|
 | 
						|
          break;
 | 
						|
          } // endif FindNextFile
 | 
						|
 | 
						|
      // Close the search handle.
 | 
						|
      if (!FindClose(h) && n != -1)
 | 
						|
        strcpy(g->Message, MSG(SRCH_CLOSE_ERR));
 | 
						|
 | 
						|
    } // endif Hsearch
 | 
						|
 | 
						|
    MaxSize = n;
 | 
						|
    } // endif MaxSize
 | 
						|
 | 
						|
  return MaxSize;
 | 
						|
  } // end of GetMaxSize
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DHR Access Method opening routine.                                 */
 | 
						|
/*  Open first file, other will be opened sequencially when reading.   */
 | 
						|
/***********************************************************************/
 | 
						|
bool TDBDHR::OpenDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  if (trace(1))
 | 
						|
    htrc("DHR OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n",
 | 
						|
      this, Tdb_No, Use, Mode);
 | 
						|
 | 
						|
  if (Use == USE_OPEN) {
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  Table already open, reopen it.                                 */
 | 
						|
    /*******************************************************************/
 | 
						|
    CloseDB(g);
 | 
						|
    SetUse(USE_READY);
 | 
						|
    } // endif use
 | 
						|
 | 
						|
  /*********************************************************************/
 | 
						|
  /*  Direct access needed for join or sorting.                        */
 | 
						|
  /*********************************************************************/
 | 
						|
  if (NeedIndexing(g)) {
 | 
						|
    // Direct access of DHR tables is not implemented yet
 | 
						|
    snprintf(g->Message, sizeof(g->Message), MSG(NO_DIR_INDX_RD), "DHR");
 | 
						|
    return true;
 | 
						|
    } // endif NeedIndexing
 | 
						|
 | 
						|
  Use = USE_OPEN;
 | 
						|
  return false;
 | 
						|
  } // end of OpenDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base read routine for DHR access method.                      */
 | 
						|
/***********************************************************************/
 | 
						|
int TDBDHR::ReadDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  int   rc = RC_OK;
 | 
						|
  DWORD erc;
 | 
						|
 | 
						|
  if (Hsearch == INVALID_HANDLE_VALUE) {
 | 
						|
    char   *filename[_MAX_PATH];
 | 
						|
    PDBUSER dup = PlgGetUser(g);
 | 
						|
 | 
						|
    PlugSetPath(filename, To_File, dup->Path);
 | 
						|
    _splitpath(filename, Drive, Direc, NULL, NULL);
 | 
						|
 | 
						|
    /*******************************************************************/
 | 
						|
    /*  Start searching files in the target directory.                 */
 | 
						|
    /*******************************************************************/
 | 
						|
    Hsearch = FindFirstFile(filename, &FileData);
 | 
						|
 | 
						|
    if (Hsearch != INVALID_HANDLE_VALUE)
 | 
						|
      iFile = 1;
 | 
						|
    else switch (erc = GetLastError()) {
 | 
						|
      case ERROR_NO_MORE_FILES:
 | 
						|
      case ERROR_FILE_NOT_FOUND:
 | 
						|
//    case ERROR_PATH_NOT_FOUND:               ???????
 | 
						|
        rc = RC_EF;
 | 
						|
        break;
 | 
						|
      default:
 | 
						|
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 | 
						|
                      FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
						|
                      NULL, erc,  0,
 | 
						|
                      (LPTSTR)&filename, sizeof(filename), NULL);
 | 
						|
        snprintf(g->Message, sizeof(g->Message), MSG(BAD_FILE_HANDLE), filename);
 | 
						|
        rc = RC_FX;
 | 
						|
      } // endswitch erc
 | 
						|
 | 
						|
  } else {
 | 
						|
    if (!FindNextFile(Hsearch, &FileData)) {
 | 
						|
      DWORD erc = GetLastError();
 | 
						|
 | 
						|
      if (erc != ERROR_NO_MORE_FILES) {
 | 
						|
        snprintf(g->Message, sizeof(g->Message), MSG(NEXT_FILE_ERROR), erc);
 | 
						|
        FindClose(Hsearch);
 | 
						|
        rc = RC_FX;
 | 
						|
      } else
 | 
						|
        rc = RC_EF;
 | 
						|
 | 
						|
    } else
 | 
						|
      iFile++;
 | 
						|
 | 
						|
  } // endif Hsearch
 | 
						|
 | 
						|
  if (rc == RC_OK)
 | 
						|
    _splitpath(FileData.cFileName, NULL, NULL, Fname, Ftype);
 | 
						|
 | 
						|
  return rc;
 | 
						|
  } // end of ReadDB
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  Data Base close routine for MUL access method.                     */
 | 
						|
/***********************************************************************/
 | 
						|
void TDBDHR::CloseDB(PGLOBAL g)
 | 
						|
  {
 | 
						|
  // Close the search handle.
 | 
						|
  if (!FindClose(Hsearch)) {
 | 
						|
    strcpy(g->Message, MSG(SRCH_CLOSE_ERR));
 | 
						|
		throw GetAmType();
 | 
						|
	} // endif FindClose
 | 
						|
 | 
						|
  iFile = 0;
 | 
						|
  Hsearch = INVALID_HANDLE_VALUE;
 | 
						|
  } // end of CloseDB
 | 
						|
 | 
						|
// ------------------------ DHRCOL functions ----------------------------
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DHRCOL public constructor.                                         */
 | 
						|
/***********************************************************************/
 | 
						|
DHRCOL::DHRCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
 | 
						|
      : COLBLK(cdp, tdbp, i)
 | 
						|
  {
 | 
						|
  if (cprec) {
 | 
						|
    Next = cprec->GetNext();
 | 
						|
    cprec->SetNext(this);
 | 
						|
  } else {
 | 
						|
    Next = tdbp->GetColumns();
 | 
						|
    tdbp->SetColumns(this);
 | 
						|
  } // endif cprec
 | 
						|
 | 
						|
  // Set additional DHR access method information for column.
 | 
						|
  N = cdp->GetOffset();
 | 
						|
  } // end of DOSCOL constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  DHRCOL constructor used for copying columns.                       */
 | 
						|
/*  tdbp is the pointer to the new table descriptor.                   */
 | 
						|
/***********************************************************************/
 | 
						|
DHRCOL::DHRCOL(DHRCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
 | 
						|
  {
 | 
						|
  N = col1->N;
 | 
						|
  } // end of DHRCOL copy constructor
 | 
						|
 | 
						|
/***********************************************************************/
 | 
						|
/*  ReadColumn: what this routine does is to access the information    */
 | 
						|
/*  corresponding to this column and convert it to buffer type.        */
 | 
						|
/***********************************************************************/
 | 
						|
void DHRCOL::ReadColumn(PGLOBAL g)
 | 
						|
  {
 | 
						|
  int     rc;
 | 
						|
  PTDBDHR tdbp = (PTDBDHR)To_Tdb;
 | 
						|
 | 
						|
  if (trace(1))
 | 
						|
    htrc("DHR ReadColumn: col %s R%d use=%.4X status=%.4X type=%d N=%d\n",
 | 
						|
      Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type, N);
 | 
						|
 | 
						|
  /*********************************************************************/
 | 
						|
  /*  Retrieve the information corresponding to the column number.     */
 | 
						|
  /*********************************************************************/
 | 
						|
  switch (N) {
 | 
						|
    case 0:                                // Drive
 | 
						|
      Value->SetValue(Drive, _MAX_DRIVE);
 | 
						|
      break;
 | 
						|
    case 1:                                // Path
 | 
						|
      Value->SetValue(Direc, _MAX_DHR);
 | 
						|
      break;
 | 
						|
    case 2:                                // Name
 | 
						|
      Value->SetValue(Fname, _MAX_FNAME);
 | 
						|
      break;
 | 
						|
    case 3:                                // Extention
 | 
						|
      Value->SetValue(Ftype, _MAX_EXT);
 | 
						|
      break;
 | 
						|
    case 4:                                // Extention
 | 
						|
      Value->SetValue(tdbp->FileData.cAlternateFileName, 14);
 | 
						|
      break;
 | 
						|
    case 5:
 | 
						|
      Value->SetValue(tdbp->FileData.dwFileAttributes);
 | 
						|
      break;
 | 
						|
    case 6:
 | 
						|
      Value->SetValue(..................
 | 
						|
  } // end of ReadColumn
 | 
						|
#endif // 0
 | 
						|
 |