/*
  -----------------------------------------------------------------------------

  module: vcn42.cpp

  -----------------------------------------------------------------------------

  responsible:  BerndV

  special area: DBMServer File Access

  description:  DBMServer File Access - Implementation

  -----------------------------------------------------------------------------



    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end




*/

/*
  -----------------------------------------------------------------------------
  includes
  -----------------------------------------------------------------------------
 */

#include <stdio.h>
#include <stdlib.h>

#include "heo06.h"
#include "geo43_0.h"

#include "hcn20.h"
#include "hcn54.h"
#include "hcn90.h"
#include "hcn42.h"

/*
  -----------------------------------------------------------------------------
  specification private macros
  -----------------------------------------------------------------------------
 */
#define SEEK_MODE_CUR         "CUR"
#define OPEN_SWITCH           '-'
#define OPEN_MODE_BIN         'b'
#define OPEN_MODE_ASCII       'a'
#define OPEN_MODE_READ        'r'
#define OPEN_MODE_WRITE       'w'
#define OPEN_MODE_APPEND      'x'

// diagnose files handling
#define DIAG_HIST_PATTERN     "_????????_?\?-?\?-??"
#define DIAG_POS_DATE         1
#define DIAG_LEN_DATE         8
#define DIAG_POS_HOUR         10
#define DIAG_LEN_HOUR         2
#define DIAG_POS_MINUTE       13
#define DIAG_LEN_MINUTE       2
#define DIAG_POS_SECOND       16
#define DIAG_LEN_SECOND       2
#define DIAG_CLASS_PRT        "protocol"
#define DIAG_CLASS_BKP        "backup"
#define DIAG_CLASS_CFG        "config"
#define DIAG_CLASS_DUMP       "dump"
#define DIAG_CLASS_LVC        "lvc"
#define DIAG_CLASS_ALL        "all"
#define DIAG_CLASS_HIST       "hist"
#define DIAG_CLASS_SEP        ","
#define DIAG_FILE             "FILE="
#define DIAG_file             "file="
#define DIAG_FILE_L           5
#define DIAG_DATE             "DATE="
#define DIAG_date             "date="
#define DIAG_DATE_L           5
#define DIAG_CLASS            "CLASS="
#define DIAG_class            "class="
#define DIAG_CLASS_L          6

#define FILE_OPT_NOCLOSE      "NOCLOSE"

#define FILEINFO_MULTI        "-m"
#define FILEINFO_TITLE        "filename,exists,readable,writable,islink,size,date_modified,time_modified,media_kind\n"
#define FILELIST_TITLE        "keyname,mode,size,date,time,comment,filename\n"
#define FILEINFO_MEDIATYPE    { "Unknown",          \
                                "File",             \
                                "Pipe",             \
                                "Raw",              \
                                "Tape (Norewind)",  \
                                "Tape (Rewind)",    \
                                "Tape",             \
                                "Directory" }

#define CONT_FLAG_END         "     END"
#define CONT_FLAG_CONTINUE    "CONTINUE"

#define FGET_TOKENDEL         FGET_TOKENDEL_CN42
#define FGET_WILDCARD         "*"
#define FGET_WILDCARDSTAR     '*'
#define FGET_WILDCARDQUE      '?'
#define FGET_UPPER            ".."
#define FGET_SLASH            "/"
#define FGET_BACKSLASH        "\\"
#define FGET_DRIVE            ":"
#define FGET_NODE             "@"

#define FGET_MODE_LINE        "LINE="
#define FGET_MODE_DATE        "DATE="
#define FGET_MODE_TYPE        "TYPE="
#define FGET_MODE_OPERATION   "OP="

#define FGET_OP_SHRINK        "SHRINK"
#define FGET_OP_DELETE        "DELETE"

#define FGET_TYPE_ASCII       "ASCII"
#define FGET_TYPE_BINARY      "BINARY"

// directory IDs
#define FGET_LOC_DBROOT       1
#define FGET_LOC_WRK          2
#define FGET_LOC_RUNDIR       3
#define FGET_LOC_CONFIG       4
#define FGET_LOC_SAP          5
#define FGET_LOC_DBA          6
#define FGET_LOC_HISTDIR      7
#define FGET_LOC_ANALYZER     8
#define FGET_LOC_ENV          9

// fiel types
#define FGET_TYP_UNKNOWN      0
#define FGET_TYP_ASCII        1
#define FGET_TYP_BINARY       2
#define FGET_TYP_DIRECTORY    3

#define FGET_TYPT_UNKNOWN     "UNKNOWN"
#define FGET_TYPT_ASCII       "ASCII"
#define FGET_TYPT_BINARY      "BINARY"
#define FGET_TYPT_DIRECTORY   "DIRECTORY"

// special directories
#define FGET_LOC_SAP_TXT      "sap"
#define FGET_LOC_DBA_TXT      "dbahist"
#define FGET_LOC_ENV_TXT      "env"

#define FGET_NAME_DB          ((const char *) 1)
#define FGET_ORG_EXT          ((const char *) 1)

// show this file in list (command file_getlist)
#define FGET_SHOW_NEVER     1000
#define FGET_SHOW_ALWAYS    0

#ifdef WIN32
  #define LO_EXT      ".prt"
  #define LCICMD_EXT  ".bat"
#else
  #define LO_EXT      ".prot"
  #define LCICMD_EXT  ""
#endif

// Timestampfeatures
#define CHAR_YEAR        'Y'
#define CHAR_MONTH       'M'
#define CHAR_DAY          'D'
#define CHAR_HOUR         'h'
#define CHAR_MINUTE       'm'
#define CHAR_SECOND       's'
#define MILLENIUM_PRE    2000
#define MILLENIUM_MIN     100
#define STAMP_FMT         "%04d%02d%02d%02d%02d%02d"

#define CHAR_SLASH            '/'
#define CHAR_BACKSLASH        '\\'
#define CHAR_DRIVE            ':'
#define REGEXP_ESCAPE         '\\'
#define REGEXP_CHAR           '.'
#define REGEXP_MULTIPLE       '*'

typedef struct tcn42FGetFiles {
    const char   * szType;
    long           nShow;
    long           nType;
    long           nOrgType;
    bool           bRemove;
    const char   * szXParam;
    const char   * szName;
    const char   * szExt;
    long           nLocation;
    const char   * szBaName;
    const char   * szBaExt;
    long           nBaLocation;
    const char   * szClass;
    const char   * szComment;
    long           nHeader;
    long           nTimestampPos;
    const char   * szTimestampFmt;
    bool           bRemoveEmptyLines;
    bool           bOperation;
} tcn42FGetFiles;

//  File                   show               type                orgtype            remove   XParam                name                ext          location          backupname     backupext       backuplocation     class             comment                              Hea nTi szTimestampFmt         bRemoveLi bOperation
static tcn42FGetFiles sFGetFiles[] = {                            
  {FGET_KNLDIAG_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_KERNELDIAGFILE"   , NULL              , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Database Messages"                , 0 , 0 , NULL                  , true  , false},
  {FGET_KNLDIAGERR_CN42 , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_KERNELDIAGFILE"   , NULL              , ".err"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Database Errors"                  , 0 , 0 , NULL                  , false , false},
  {FGET_KNLDIAGOLD_CN42 , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_KERNELDIAGFILE"   , NULL              , ".old"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Database Messages (OLD)"          , 0 , 0 , NULL                  , true  , false},
  {FGET_KNLTRC_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , "_KERNELTRACEFILE"  , NULL              , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "Database Trace"                   , 0 , 0 , NULL                  , false , false},
  {FGET_KNLTRCDAT_CN42  , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , "_KERNELTRACEFILE"  , NULL              , ".dat"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , NULL            , "Database Trace Dat"               , 0 , 0 , NULL                  , false , false},
  {FGET_KNLDUMP_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , "_KERNELDUMPFILE"   , NULL              , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "Database Dump"                    , 0 , 0 , NULL                  , false , false},
  {FGET_KNLEVT_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_EVENTFILE"        , NULL              , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Database Events"                  , 0 , 0 , NULL                  , false , false},
  {FGET_RTEDUMP_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_RTEDUMPFILE"      , NULL              , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "Runtime Environment Dump"         , 0 , 0 , NULL                  , false , false},
  {FGET_UTLPRT_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_UTILITY_PROTFILE" , NULL              , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Utility Statements"               , 0 , 0 , NULL                  , true  , false},
  {FGET_BACKHIST_CN42   , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_BACKUP_HISTFILE"  , NULL              , NULL       , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_WRK     , DIAG_CLASS_BKP  , "Backup History"                   , 0 , 0 , NULL                  , false , false},
  {FGET_BACKMDF_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , "_BACKUP_MED_DEF"   , NULL              , NULL       , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_WRK     , DIAG_CLASS_BKP  , "Backup Media History"             , 0 , 0 , NULL                  , false , false},
  {FGET_BACKEBF_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbm"             , ".ebf"     , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_WRK     , DIAG_CLASS_BKP  , "External Backup History"          , 0 , 0 , NULL                  , false , false},
  {FGET_BACKEBP_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbm"             , ".ebp"     , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_WRK     , DIAG_CLASS_BKP  , "External Backup Protocol"         , 0 , 0 , NULL                  , false , false},
  {FGET_BACKEBL_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbm"             , ".ebl"     , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_WRK     , DIAG_CLASS_BKP  , "External Backup Log"              , 0 , 0 , NULL                  , false , false},
  {FGET_LOADPRT_CN42    , FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "load"            , LO_EXT     , FGET_LOC_RUNDIR  , "dbm"        , ".ins"         , FGET_LOC_RUNDIR  , NULL            , "XLoad Protocol"                   , 0 , 0 , NULL                  , false , false},
  {FGET_XSRVPRT_CN42    , FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "xserver_@"       , ".prt"     , FGET_LOC_WRK     , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "XServer Messages"                 , 0 , 0 , NULL                  , true  , false},
  {FGET_XSRVPRTOLD_CN42 , FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "xserver_@"       , ".old"     , FGET_LOC_WRK     , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "XServer Messages (OLD)"           , 0 , 0 , NULL                  , true  , false},
  {FGET_REPMAN_CN42     , FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "loader"          , ".prt"     , FGET_LOC_WRK     , "dbm"        , ".ins"         , FGET_LOC_RUNDIR  , NULL            , "Replication Manager Protocol"     , 0 , 0 , NULL                  , false , false},
  {FGET_DBMPRT_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbm"             , ".prt"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Database Manager Protocol"        , 3 , 0 , "YYYY-MM-DD hh:mm:ss" , false , false},
  {FGET_DBMMDF_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbm"             , ".mmm"     , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_CONFIG  , DIAG_CLASS_CFG  , "Database Manager Media"           , 0 , 0 , NULL                  , false , false},
  {FGET_DBMPAHI_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , FGET_NAME_DB      , ".pah"     , FGET_LOC_CONFIG  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Database Parameter History"       , 0 , 0 , NULL                  , false , false},
  {FGET_CTRLMDF_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "control"         , ".med"     , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_CONFIG  , NULL            , "XControl Media"                   , 0 , 0 , NULL                  , false , false},
  {FGET_CTRLLOG_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "control"         , ".log"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , NULL            , "XControl Protocol"                , 0 , 0 , NULL                  , false , false},
  {FGET_DBMCFG_CN42     , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "dbm"             , ".cfg"     , FGET_LOC_RUNDIR  , FGET_NAME_DB , FGET_ORG_EXT   , FGET_LOC_CONFIG  , DIAG_CLASS_CFG  , "Database Manager Configuration"   , 0 , 0 , NULL                  , false , false},
  {FGET_PARAM_CN42      , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , false , NULL                , FGET_NAME_DB      , NULL       , FGET_LOC_CONFIG  , "param"      , FGET_ORG_EXT   , FGET_LOC_RUNDIR  , DIAG_CLASS_CFG  , "Database Parameters"              , 0 , 0 , NULL                  , false , false},
  {FGET_LCINIT_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "lcinit"          , ".log"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_LVC  , "LiveCache Initialisation"         , 0 , 0 , NULL                  , false , false},
  {FGET_LCINITCMD_CN42  , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "lcinit"          , LCICMD_EXT , FGET_LOC_SAP     , NULL         , NULL           , 0                , DIAG_CLASS_LVC  , "LiveCache Initialisation Script"  , 0 , 0 , NULL                  , false , false},
  {FGET_LCINITHIS_CN42  , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "lcinit"          , ".his"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_LVC  , "LiveCache Initialisation History" , 0 , 0 , NULL                  , false , false},
  {FGET_INSTPRT_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbm"             , ".ins"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Installation Protocol"            , 0 , 0 , NULL                  , false , false},
  {FGET_USER_CN42       , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , FGET_NAME_DB      , ".upc"     , FGET_LOC_CONFIG  , "dbm"        , FGET_ORG_EXT   , FGET_LOC_RUNDIR  , NULL            , "User Profiles"                    , 0 , 0 , NULL                  , false , false},
  {FGET_KNLTRCPRT_CN42  , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , FGET_NAME_DB      , ".prt"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Kernel Trace Protocol"            , 0 , 0 , NULL                  , false , false},
  {FGET_WIZOVER_CN42    , 1                 , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "*"               , ".wiz"     , FGET_LOC_SAP     , NULL         , NULL           , 0                , NULL            , "Wizard Overview"                  , 0 , 0 , NULL                  , false , true },
  {FGET_WIZDETAIL_CN42  , 1                 , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "*"               , ".wtc"     , FGET_LOC_SAP     , NULL         , NULL           , 0                , NULL            , "Wizard Detail"                    , 0 , 0 , NULL                  , false , true },
  {FGET_DBAHIST_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbahist"         , ".prt"     , FGET_LOC_DBA     , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "DBA Action Log"                   , 3 , 15, "YYYYMMDDhhmmss"      , false , true },
  {FGET_DBADTL_CN42     , FGET_SHOW_NEVER+1 , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dba*"            , NULL       , FGET_LOC_DBA     , NULL         , NULL           , 0                , NULL            , "DBA Action Log Details"           , 0 , 0 , NULL                  , false , true },
  {FGET_DBMSRV_CN42     , FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "dbmsrv_@"        , ".prt"     , FGET_LOC_WRK     , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Global Database Manager Protocol" , 3 , 0 , "YYYY-MM-DD hh:mm:ss" , false , false},
  {FGET_AKDMP_CN42      , 1                 , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "AK"              , ".dmp"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "AK Diagnose Dump"                 , 0 , 0 , NULL                  , false , false},
  {FGET_AKBUF_CN42      , 1                 , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "AK"              , ".buf"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "AK Diagnose Buffer"               , 0 , 0 , NULL                  , false , false},
  {FGET_AKSTM_CN42      , 1                 , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "AK"              , ".stm"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "AK Diagnose Statement"            , 0 , 0 , NULL                  , false , false},
  {FGET_KNLCOR_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "*"               , ".cor"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "\"cor\" file for problem analysis"  , 0 , 0 , NULL                  , false , false},
  {FGET_KNLBAD_CN42     , FGET_SHOW_ALWAYS  , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "*"               , ".bad"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_DUMP , "\"bad\" file for problem analysis"  , 0 , 0 , NULL                  , false , false},
  {FGET_DIAGPACK_CN42   , FGET_SHOW_ALWAYS  , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , "diagpkg"         , ".tgz"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , NULL            , "Diagnose Package"                 , 0 , 0 , NULL                  , false , false},
  {FGET_DIAGHIST_CN42   , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , true  , NULL                , FGET_NAME_DB      , "_*"       , FGET_LOC_HISTDIR , NULL         , NULL           , 0                , NULL            , "Diagnose History File"            , 0 , 0 , NULL                  , false , false},
  {FGET_DIAGDIR_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_DIRECTORY ,FGET_TYP_DIRECTORY , false , NULL                , ""                , NULL       , FGET_LOC_HISTDIR , NULL         , NULL           , 0                , NULL            , "Diagnose History File"            , 0 , 0 , NULL                  , false , false},
  {FGET_ANALYZER_CN42   , FGET_SHOW_ALWAYS  , FGET_TYP_DIRECTORY ,FGET_TYP_DIRECTORY , false , NULL                , "analyzer"        , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , NULL            , "DB Analyzer File"                 , 0 , 21, "YYYY-MM-DD hh:mm:ss" , false , true },
  {FGET_LCTRC_CN42      , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "lc*"             , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , NULL            , "LiveCache Trace (ASCII)"          , 0 , 0 , NULL                  , false , true },
  {FGET_ATP_CN42        , FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "atp*"            , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , NULL            , "LiveCache Trace (ASCII)"          , 0 , 0 , NULL                  , false , true },
  {FGET_SDBINFO_CN42    , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "sdbinfo"         , ".prt"     , FGET_LOC_WRK     , NULL         , NULL           , 0                , DIAG_CLASS_PRT  , "Operating System Information"     , 0 , 0 , NULL                  , false , true },
  {FGET_ANAPID_CN42     , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , false , NULL                , "DBAN"            , ".pid"     , FGET_LOC_ANALYZER, NULL         , NULL           , 0                , NULL            , "DBanalyzer process ID"            , 0 , 0 , NULL                  , false , false},
  {FGET_ANASID_CN42     , FGET_SHOW_NEVER   , FGET_TYP_BINARY    ,FGET_TYP_BINARY    , false , NULL                , "DBAN"            , ".sid"     , FGET_LOC_ANALYZER, NULL         , NULL           , 0                , NULL            , "DBanalyzer session ID"            , 0 , 0 , NULL                  , false , false},
  {FGET_EVTDISPCONF_CN42, FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbmevtdisp"      , ".cfg"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_CFG  , "Event Dispatcher Configuration"   , 0 , 0 , NULL                  , false , false},
  {FGET_EVTDISPCDEF_CN42, FGET_SHOW_NEVER   , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , false , NULL                , "dbmevtdisp"      , ".cfg"     , FGET_LOC_ENV     , NULL         , NULL           , 0                , DIAG_CLASS_CFG  , "Event Dispatcher Configuration"   , 0 , 0 , NULL                  , false , false},
  {FGET_EVTDISPPRT_CN42,  FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbmevtdisp"      , ".prt"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_CFG  , "Event Dispatcher Protocol"        , 0 , 0 , NULL                  , false , false},
  {FGET_EXTDBPRT_CN42,    FGET_SHOW_ALWAYS  , FGET_TYP_ASCII     ,FGET_TYP_ASCII     , true  , NULL                , "dbmevthndl_extendDB", ".prt"  , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_CFG  , "Event Handler ExtendDB Protocol"  , 0 , 0 , NULL                  , false , false},
//  {FGET_APOCOMTRC_CN42  , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII    , FGET_TYP_ASCII     , true  , NULL                , "apo_com_trace*"  , ".txt"     , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_LVC  , "APO Trace"                        , 0 , 0 , NULL                  , false , false},
//  {FGET_LCBIN_CN42      , FGET_SHOW_ALWAYS  , FGET_TYP_ASCII    , FGET_TYP_ASCII     , true  , NULL                , "lc*"             , NULL       , FGET_LOC_RUNDIR  , NULL         , NULL           , 0                , DIAG_CLASS_LVC  , "LiveCache Trace (binary)"         , 0 , 0 , NULL                  , false , false},
  {NULL                 , FGET_SHOW_NEVER   , FGET_TYP_UNKNOWN   ,FGET_TYP_UNKNOWN   , false , NULL                , NULL              , NULL       , 0                , NULL         , NULL           , 0                , NULL            , ""                                 , 0 , 0 , NULL                  , false , false}
};


/*
  -----------------------------------------------------------------------------
  specification private functions
  -----------------------------------------------------------------------------
 */
static void cn42_PrintFileInfo
      ( char       *szName,
        char       *szBuffer );

static tcn00_Error cn42_FileRead
      ( const char    * szArguments,
        char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const bool      bNext);

static tcn00_Error cn42_FileReadNext
      ( char             * replyData,
        int              * replyLen,
        const int          replyLenMax,
        const tsp00_Int4     hFile,
        const tsp00_Longint  nSize,
        const bool         bNoClose,
        const bool         bAscii,
        const bool         bRemoveEmptyLines,
        const int          nIndex);

static tcn00_Error cn42_FileReadFirst
      ( char             * replyData,
        int              * replyLen,
        const int          replyLenMax,
        const tsp00_Int4     hFile,
        const tsp00_Longint  nSize,
        const int          nIndex,
        const char *       pDate,
        int                nLine);

static tcn00_Error cn42_FileWrite
      ( const char    * szArguments,
        char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const bool      bNext);

static tcn00_Error cn42_FileWriteNext
      ( char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const tsp00_Int4  hFile,
        const bool      bAscii,
        const long      nData,
        const char    * pData );

static bool cn42_FileMatch
      ( tsp00_Pathc        szFileName,
        tsp00_Pathc        szRealName,
        tsp00_Pathc      & szToken);

static bool cn42_DiagFileMatch
      ( const char       * szDBName,
        const char       * szFile );

static tcn00_Error cn42_ReadDir
      ( void               * hDirectory,
        char               * szFirst,
        char               * replyData,
        int                  replyLenMax,
        tsp05_RteFileError * pRteFileErr);

static tcn00_Error cn42_GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        int                 & nIndex);

static tcn00_Error cn42_GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        int                 & nIndex,
        tsp00_Pathc         & szFileDir);

static tcn00_Error cn42_GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        tsp00_Pathc         & szBackupName,
        int                 & nIndex,
        tsp00_Pathc         & szFileDir);

static void cn42_ReadTimeStamp
      ( const char *       szSource,
        const char *       szFormat,
        tsp00_Timestampc & sTimeStamp );

static bool cn42_IsLineEmpty
      ( const char *       pLine);

static tcn00_Error cn40_FileOperation
      ( char       *       replyData,
        int        *       replyLen,
        const char *       szFileName,
        const char *       szDate,
        int                nLine,
        int                nIndex,
        bool               bDelete);

static tcn00_Error cn40_FileDelete
      ( char       *       replyData,
        int        *       replyLen,
        const char *       szFileName,
        const char *       szDate);


static tcn00_Error cn40_FileShrink
      ( char       *       replyData,
        int        *       replyLen,
        const char *       szFileName,
        const char *       szDate,
        int                nLine,
        int                nIndex);

static tcn00_Error cn40_FileGetListDir 
      ( char               * replyData,
        long                 nIndex,
        tsp00_Path         & szFileDir,
        tsp00_Pathc        & szFileName,
        tsp00_Path         & szBaseDir,
        char              *& pCurrent,
        int                  replyLenMax);

static const char * cn40_FileType
      ( const tsp05_RteFileInfo  & rteFileInfo,
      long                       nType );

// extern pascal functions
externPascal void s49build_pattern (
    void                  *  pat_buffer,
    pasbool                              isAscii,
    tsp00_Int4                             start,
    tsp00_Int4                             stop,
    char                                 escape_char,
    pasbool                              escape,
    pasbool                              string,
    tsp00_SqlMode_Param                    sqlmode,
    pasbool               VAR_VALUE_REF  ok);

externPascal pasbool s49patmatch (
    void                  *  val,
    tsp00_Int4                             val_offset,
    tsp00_Int4                             val_len,
    void                  *  pat,
    tsp00_Int4                             pat_offset,
    tsp00_Int4                             pat_len,
    char                                 pat_defbyte);


/*
  -----------------------------------------------------------------------------
  implementation public functions
  -----------------------------------------------------------------------------
 */

/*
  -----------------------------------------------------------------------------
  public function cn42DirCreate
  -----------------------------------------------------------------------------
*/
tcn00_Error cn42DirCreate
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error    nFuncReturn = OK_CN00;
  char           szDirectory [PARAMETER_MAXLEN_CN90];
  tsp01_RteError aRteError;

  if (nFuncReturn == OK_CN00) {
    if (!cn90GetToken(command->args, szDirectory, 1, PARAMETER_MAXLEN_CN90) || cn90GetToken(command->args, NULL, 2, -1)) {
      nFuncReturn = ERR_PARAM_CN00;
    } /* end if */
  } /* end if */

  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn90DirCreate(szDirectory, &aRteError);
  } /* end if */

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } else if (nFuncReturn == ERR_RTEEXT_CN00) {
    cn90AnswerNewRTEError (replyData, replyLen, nFuncReturn, &aRteError );
  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  return nFuncReturn;
} /* end cn42DirCreate */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn42DirOpen
 * ------------------------------------------------------------------
 */
tcn00_Error cn42DirOpen
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  void              * hDirectory  = NULL;
  tsp00_C256            szDirectory;
  tsp00_C256            szFirst;
  tsp05_RteFileError  rteFileErr;
  bool                bOpen       = false;
  unsigned int        nIndex      = 0;

  /* read the parameters */
  if (nFuncReturn == OK_CN00) {
    if (!cn90GetToken(command->args, szDirectory, 1, sizeof(szDirectory)) || cn90GetToken(command->args, NULL, 2, -1)) {
      nFuncReturn = ERR_PARAM_CN00;
    } /* end if */
  } /* end if */

  /* open dir */
  if (nFuncReturn == OK_CN00) {

    cn90ChangePathDelimiter(szDirectory);
    sqlfopendirc ( &szDirectory, &hDirectory,  &szFirst, &rteFileErr);
    if  ( rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
    } else {
      bOpen = true;
    } /* end if */
  } /* end if */

  /* dir is open */
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn42_ReadDir(hDirectory, szFirst, replyData, replyLenMax, &rteFileErr);
  } /* end if */

  /* check result */
  if (nFuncReturn == OK_CN00) {
    *replyLen = (int)strlen(replyData);
  } else if (nFuncReturn == ERR_RTE_CN00) {
    cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  /* close on error */
  if (nFuncReturn != OK_CN00 && bOpen) {
    sqlfclosedirc (hDirectory, &rteFileErr);
  } /* end if */

  return nFuncReturn;
} /* end cn42DirOpen */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn42DirReadNext
 * ------------------------------------------------------------------
 */
tcn00_Error cn42DirReadNext
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szDirectory [PARAMETER_MAXLEN_CN90];
  void              * hDirectory  = NULL;
  tsp05_RteFileError  rteFileErr;

  /* read the parameters */
  if (nFuncReturn == OK_CN00) {
    if (!cn90GetToken(command->args, szDirectory, 1, PARAMETER_MAXLEN_CN90) || cn90GetToken(command->args, NULL, 2, -1)) {
      nFuncReturn = ERR_PARAM_CN00;
    } /* end if */
  } /* end if */

  /* read dir */
  if (nFuncReturn == OK_CN00) {
    sscanf(szDirectory, "%x", &hDirectory);
    rteFileErr.sp5fe_result.becomes(vf_ok);
    nFuncReturn = cn42_ReadDir(hDirectory, NULL, replyData, replyLenMax, &rteFileErr);
  } /* end if */

  /* check result */
  if (nFuncReturn == OK_CN00) {
    *replyLen = (int)strlen(replyData);
  } else if (nFuncReturn == ERR_RTE_CN00) {
    cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  /* close on error */
  if (nFuncReturn != OK_CN00 && hDirectory != NULL) {
    sqlfclosedirc (hDirectory, &rteFileErr);
  } /* end if */

  return nFuncReturn;
} /* end cn42DirReadNext */

/* ------------------------------------------------------------------
 * IMPLEMENTATION PUBLIC FUNCTION cn42DirClose
 * ------------------------------------------------------------------
 */
tcn00_Error cn42DirClose
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szDirectory [PARAMETER_MAXLEN_CN90];
  void              * hDirectory  = NULL;
  tsp05_RteFileError  rteFileErr;

  /* read the parameters */
  if (nFuncReturn == OK_CN00) {
    if (!cn90GetToken(command->args, szDirectory, 1, PARAMETER_MAXLEN_CN90) || cn90GetToken(command->args, NULL, 2, -1)) {
      nFuncReturn = ERR_PARAM_CN00;
    } /* end if */
  } /* end if */

  /* close dir */
  if (nFuncReturn == OK_CN00) {
    sscanf(szDirectory, "%x", &hDirectory);
    sqlfclosedirc (hDirectory, &rteFileErr);
    if  ( rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
    } /* end if */
  } /* end if */

  /* check result */
  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } else if (nFuncReturn == ERR_RTE_CN00) {
    cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  return nFuncReturn;
} /* end cn42DirClose */

/*
  -----------------------------------------------------------------------------
  function:     cn42FileSeek
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileSeek
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Int4            hFile;
  tsp00_Longint         nPosition;
  char                szHandle [PARAMETER_MAXLEN_CN90];
  char                szPosition [PARAMETER_MAXLEN_CN90];
  char                szMode [PARAMETER_MAXLEN_CN90];
  void              * hDirectory  = NULL;
  tsp05_RteFileError  rteFileErr;
  tsp05_RteSeekKind_Enum  rteSeekMode;

  /* read the parameters */
  if (nFuncReturn == OK_CN00) {
    if ( !cn90GetToken(command->args, szHandle,   1, PARAMETER_MAXLEN_CN90) ||
         !cn90GetToken(command->args, szPosition, 2, PARAMETER_MAXLEN_CN90)    ) {
      nFuncReturn = ERR_PARAM_CN00;
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } /* end if */
  } /* end if */

  /* read parameters and execute seek*/
  if (nFuncReturn == OK_CN00) {
    hFile     = atol ( szHandle );
    nPosition = atol ( szPosition );
    if (strcmp(szMode, SEEK_MODE_CUR) == 0) {
      rteSeekMode = sp5vf_seek_cur;
    } else {
      rteSeekMode = sp5vf_seek_begin;
    } /* end if */

    sqlfseekc(hFile, nPosition, rteSeekMode, &rteFileErr);

    if (rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } /* end if */

  } /* end if */

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } /* end if */

  return nFuncReturn;
} /* end cn42FileSeek */

/*
  -----------------------------------------------------------------------------
  function:     cn42FileOpen
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileOpen
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  bool                bBinary = false;
  bool                bAscii  = false;
  bool                bRead   = false;
  bool                bWrite  = false;
  bool                bAppend = false;
  char                szName  [PARAMETER_MAXLEN_CN90] = "";
  char                szToken [PARAMETER_MAXLEN_CN90] = "";
  long                nIndex;
  long                nSwitch;
  tsp00_Int4            hFile;

  tsp05_RteFileError       rteFileErr;
  tsp05_RteFileInfo        rteFInfo;
  tsp05_RteDataKind_Enum   rteDatakind;
  tsp05_RteFileMode_Enum   rteFilemode;
  tsp05_RteBufferingKind_Enum rteBuffering;

  /* read the parameters */
  nIndex = 1;
  while ( cn90GetToken(command->args, szToken, nIndex, PARAMETER_MAXLEN_CN90) ) {
    nSwitch = 0;
    if (szToken[nSwitch] == OPEN_SWITCH) {
      nSwitch++;
      while (szToken[nSwitch] != CHAR_STRINGTERM_CN90) {
        switch (szToken[nSwitch]) {
          case OPEN_MODE_BIN:
            bBinary = true;
            break;
          case OPEN_MODE_ASCII:
            bAscii = true;
            break;
          case OPEN_MODE_READ:
            bRead = true;
            break;
          case OPEN_MODE_WRITE:
            bWrite = true;
            break;
          case OPEN_MODE_APPEND:
            bAppend = true;
            break;
          default:
            nFuncReturn = ERR_PARAM_CN00;
            break;
        } /* end switch */
        nSwitch++;
      } /* end while */
    } else {
      SAPDB_strcpy(szName, szToken);
    } /* end if */
    nIndex++;
  } /* end while */
  if (strlen(szName) == 0) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  /* execute fileopen */
  if (nFuncReturn == OK_CN00) {

    rteDatakind  = (bBinary) ? sp5vf_binary : sp5vf_text;

    if (bAppend) {
      rteFilemode  = sp5vf_append;
    } else if (bRead && bWrite) {
      rteFilemode  = sp5vf_readwrite;
    } else if (bWrite) {
      rteFilemode  = sp5vf_write;
    } else if (bRead) {
      rteFilemode  = sp5vf_read;
    } else {
      rteFilemode  = sp5vf_read;
    } /* end if */

    rteBuffering = sp5bk_unbuffered;

    sqlfinfoc (szName, &rteFInfo, &rteFileErr );
    if (rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } else {
      sqlfopenc (szName, rteDatakind, rteFilemode, rteBuffering, &hFile, &rteFileErr );

      if (rteFileErr.sp5fe_result != vf_ok) {
        nFuncReturn = ERR_RTE_CN00;
        cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      } /* end if */
    } /* end if */

  } /* end if */

  if (nFuncReturn == OK_CN00) {
    /* print OK and handle of file */
    sprintf (replyData, "%s%s%5d%s%lu%s", ANSWER_OK_CN00,      LINE_SEPSTRING_CN00,
                                          hFile,               LINE_SEPSTRING_CN00,
                                          (unsigned long) rteFInfo.sp5fi_size, LINE_SEPSTRING_CN00);
  } /* end if */

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;
} /* end cn42FileOpen */

/*
  -----------------------------------------------------------------------------
  function:     cn42FileErase
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileErase
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szName  [PARAMETER_MAXLEN_CN90] = "";
  tsp05_RteFileError  rteFileErr;

  // read the parameters
  if ( !cn90GetToken(command->args, szName, 1, PARAMETER_MAXLEN_CN90) ||
       cn90GetToken(command->args, NULL,    2, -1                   )    ) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } // end if

  // execute delete
  if (nFuncReturn == OK_CN00) {
    sqlferasec (szName, &rteFileErr);
    if (rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } else {
      cn90AnswerOK (replyData, replyLen, NULL);
    } // end if
  } // end if

  return nFuncReturn;

} // end cn42FileErase

/*
  -----------------------------------------------------------------------------
  function:     cn42FileClose
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileClose
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Int4            hFile;
  char                szHandle [PARAMETER_MAXLEN_CN90];
  void              * hDirectory  = NULL;
  tsp05_RteFileError  rteFileErr;

  // read the parameters
  if ( !cn90GetToken(command->args, szHandle, 1, PARAMETER_MAXLEN_CN90)) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } // end if

  // execute close
  if (nFuncReturn == OK_CN00) {
    hFile     = atol ( szHandle );
    sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );

    if (rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } else {
      cn90AnswerOK (replyData, replyLen, NULL);
    } // end if
  } // end if

  return nFuncReturn;

} // cn42FileClose

/*
  -----------------------------------------------------------------------------
  function:     cn42FileInfo
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileInfo
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szName  [PARAMETER_MAXLEN_CN90] = "";
  char              * pCurrPos;
  long                nToken = 1;

  // read the parameters
  if ( !cn90GetToken(command->args, szName, nToken, PARAMETER_MAXLEN_CN90)) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } else {
    // skip multi option
    if (strcmp (szName, FILEINFO_MULTI) == 0) {
      nToken++;
    } // end if
    // print OK and FileInfoTitle
    sprintf (replyData, "%s%s%s%s", ANSWER_OK_CN00,      LINE_SEPSTRING_CN00,
                                    FILEINFO_TITLE,      LINE_SEPSTRING_CN00);
    pCurrPos = replyData + strlen(replyData);
  } // end if

  if (nFuncReturn == OK_CN00) {
    while (cn90GetToken(command->args, szName, nToken, PARAMETER_MAXLEN_CN90)) {
      cn42_PrintFileInfo(szName, pCurrPos);
      pCurrPos = pCurrPos + strlen(pCurrPos);
      nToken++;
    } // end while
  } // end if

  *replyLen = (int)strlen(replyData);

  return nFuncReturn;

} // end cn42FileInfo

/*
  -----------------------------------------------------------------------------
  function:     cn42FileRead
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileRead
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn42_FileRead ( command->args, replyData, replyLen, replyLenMax, false);
} // end cn42FileRead

/*
  -----------------------------------------------------------------------------
  function:     cn42FileReadNext
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileReadNext
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn42_FileRead ( command->args, replyData, replyLen, replyLenMax, true);
} // end cn42FileReadNext

/*
  -----------------------------------------------------------------------------
  function:     cn42FileWrite
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileWrite
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn42_FileWrite ( command->args, replyData, replyLen, replyLenMax, false);
} // end cn42FileWrite

/*
  -----------------------------------------------------------------------------
  function:     cn42FileWriteNext
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileWriteNext
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  return cn42_FileWrite ( command->args, replyData, replyLen, replyLenMax, true);
} // end cn42FileWriteNext

/*
  -----------------------------------------------------------------------------
  function:     cn42FileGet
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileGet
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szFilekey;
  tsp00_Pathc         szParam;
  tsp00_Pathc         szFileName;
  tsp00_Pathc         szFileDirC;
  const char        * pLine      = NULL;
  tsp00_Pathc         szLine;
  const char        * pDate      = NULL;
  tsp00_Pathc         szDate;
  const char        * pType      = NULL;
  tsp00_Pathc         szType;
  long                nType      = FGET_TYP_UNKNOWN;
  int                 nIndex;
  int                 nParam;
  tsp00_Int4          hFile;

  tsp05_RteFileError  rteFileErr;
  tsp05_RteFileInfo   rteFInfo;

  // read the parameters
  cn90GetToken(command->args, szFilekey, 1, szFilekey.size());
  cn90StripQuotes(szFilekey);

  // check for qualifier
  nParam = 2;
  while (cn90GetToken(command->args, szParam, nParam, szParam.size())) {
    if (strnicmp(szParam, FGET_MODE_LINE, strlen(FGET_MODE_LINE)) == 0) {
      szLine.rawAssign(szParam);
      pLine = szLine.asCharp();
      pLine = pLine + strlen(FGET_MODE_LINE);
    } else if (strnicmp(szParam, FGET_MODE_DATE, strlen(FGET_MODE_DATE)) == 0) {
      szDate.rawAssign(szParam);
      pDate = szDate.asCharp();
      pDate = pDate + strlen(FGET_MODE_DATE);
    } else if (strnicmp(szParam, FGET_MODE_TYPE, strlen(FGET_MODE_TYPE)) == 0) {
      szType.rawAssign(szParam);
      pType = szType.asCharp();
      pType = pType + strlen(FGET_MODE_TYPE);
      if (stricmp(pType, FGET_TYPE_ASCII) == 0) {
        nType = FGET_TYP_ASCII;
      } else if (stricmp(pType, FGET_TYPE_BINARY) == 0) {
        nType = FGET_TYP_BINARY;
      } // end if
    } else {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
      break;
    } // end if
    ++nParam;
  } // end while

  // look for file
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn42_GetFileName(vcontrol->dbname, szFilekey, szFileName, nIndex, szFileDirC);
    

    if (nFuncReturn != OK_CN00) {
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } else {
      if (nType != FGET_TYP_UNKNOWN) {
        sFGetFiles[nIndex].nType = nType;
      } // end if
    } // end if
  } // end if

  // check file type
  if (nFuncReturn == OK_CN00) {
    if ( ( ((pDate != NULL) || (pLine != NULL)) && (sFGetFiles[nIndex].nType != FGET_TYP_ASCII) ) ||
         ( (pDate != NULL) && (sFGetFiles[nIndex].szTimestampFmt == NULL)     )    ) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    // execute fileopen
    sqlfinfoc (szFileName, &rteFInfo, &rteFileErr );
    if (rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } // end if

  } // end if

  // read contents
  if (nFuncReturn == OK_CN00) {

    if (rteFInfo.sp5fi_media_kind == vf_t_directory) {

      char        * pCurrent  = replyData;
      char        * pLenPos   = NULL;
      char        * pLenStart = NULL;
      tsp00_Path    szFileDir;
      tsp00_Path    szBaseDir;
      char          szTmp[PARAMETER_MAXLEN_CN90];

      // init OK Answer
      sprintf (pCurrent, "%s%s%5d%s", ANSWER_OK_CN00,      LINE_SEPSTRING_CN00,
                                      1,                   LINE_SEPSTRING_CN00);
      pCurrent = pCurrent + strlen(pCurrent);

      sprintf ( pCurrent , "%s%s" , CONT_FLAG_END, LINE_SEPSTRING_CN00 );
      pCurrent = pCurrent + strlen(pCurrent);
      pLenPos  = pCurrent;

      sprintf ( pLenPos, "%20ld%20ld%s" , (long) 0, (long) 0, LINE_SEPSTRING_CN00 );
      pCurrent  = pCurrent + strlen(pCurrent);

      sprintf (pCurrent, "%s", (char   *) FILELIST_TITLE);
      pLenStart = pCurrent;
      pCurrent = pCurrent + strlen(pCurrent);

      SAPDB_strcpy(szBaseDir, szFileDirC);
      SAPDB_strcpy(szFileDir,  szFileName);
      #if defined(_WIN32) || defined(OS2) 
        strcat(szFileDir, "\\");
      #else
        strcat(szFileDir, "/");
      #endif
      SAPDB_strcpy(szFileName, szFileDirC);
      #if defined(_WIN32) || defined(OS2) 
        strcat(szFileName, "*");
      #else
        strcat(szFileName, "*");
      #endif

      nFuncReturn = cn40_FileGetListDir(replyData, nIndex, szFileDir, szFileName, szBaseDir, pCurrent, replyLenMax - (int)(pCurrent - replyData));

      if (nFuncReturn == OK_CN00) {
        sprintf ( szTmp, "%20ld%20ld%s" , (long) strlen(pLenStart), (long) strlen(pLenStart), LINE_SEPSTRING_CN00 );
        strncpy(pLenPos, szTmp, strlen(szTmp));
      } // end if

      *replyLen = (int)strlen(replyData);

    } else {
      
      sqlfopenc (szFileName, ((sFGetFiles[nIndex].nType != FGET_TYP_ASCII) ? sp5vf_binary : sp5vf_text),
                 sp5vf_read, sp5bk_unbuffered, &hFile, &rteFileErr );

      if (rteFileErr.sp5fe_result != vf_ok) {
        nFuncReturn = ERR_RTE_CN00;
        cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      } else {
        if ((pLine != NULL) || (pDate != NULL)) {
          nFuncReturn = cn42_FileReadFirst( replyData,
                                            replyLen,
                                            replyLenMax,
                                            hFile,
                                            rteFInfo.sp5fi_size,
                                            nIndex,
                                            pDate,
                                            (pLine == NULL) ? 0 : atoi(pLine));
        } else {
          nFuncReturn = cn42_FileReadNext( replyData,
                                           replyLen,
                                           replyLenMax,
                                           hFile,
                                           rteFInfo.sp5fi_size,
                                           false,
                                           sFGetFiles[nIndex].nType == FGET_TYP_ASCII,
                                           sFGetFiles[nIndex].bRemoveEmptyLines,
                                           nIndex);
        } // end if
      } // end if

    } // end if
  } // end if


  return nFuncReturn;

} // end cn42FileGet

/*
  -----------------------------------------------------------------------------
  function:     cn42FileGetNext
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileGetNext
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szType;
  tsp00_Pathc         szFileName;
  char                szHandle   [PARAMETER_MAXLEN_CN90] = "";
  int                 nIndex;

  // read the parameters
  if (!cn90GetToken(command->args, szType,   1, szType.size())    ||
      !cn90GetToken(command->args, szHandle, 2, PARAMETER_MAXLEN_CN90)    ||
       cn90GetToken(command->args, NULL,     3, -1)    ||
       vcontrol->dbname[0] == CHAR_STRINGTERM_CN90    ) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } // end if
  cn90StripQuotes(szType);

  // look for file
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn42_GetFileName(vcontrol->dbname, szType, szFileName, nIndex);
  } // end if

  // read contents
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn42_FileReadNext( replyData,
                                     replyLen,
                                     replyLenMax,
                                     atol(szHandle),
                                     0,
                                     false,
                                     sFGetFiles[nIndex].nType == FGET_TYP_ASCII,
                                     sFGetFiles[nIndex].bRemoveEmptyLines,
                                     nIndex);
  } else {
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } // end if

  return nFuncReturn;

} // end cn42FileGetNext

/*
  -----------------------------------------------------------------------------
  function:     cn42FileGetList
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileGetList
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1(__FILE__"::cn42FileGetList");

  tcn00_Error         nFuncReturn  = OK_CN00;
  long                nIndex       = 0;
  char              * pCurrent     = replyData;
  tsp05_RteFileInfo   rteFileInfo;
  tsp05_RteFileError  rteFileErr;
  tsp00_Pathc         szFileName;
//  tsp00_Pathc         szToken;
//  tsp00_Path          szRealName;
  tsp00_Pathc         szFullReal;
  tsp00_Path          szFileDir;
  tsp00_Pathc         szTemp;
  char                szShow[10];
  int                 nShow = 0;
  int                 nFileIndex;
  tsp00_Pathc         szType;
  void              * hDirectory  = NULL;
  int                 nLength;

  if (cn90GetToken(command->args, szShow, 1, sizeof(szShow))) {
    nShow = atoi(szShow);
  } // end if

  // init OK Answer
  _stprintf (pCurrent, "%s%s%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00, (char   *) FILELIST_TITLE);
  pCurrent = pCurrent + strlen(pCurrent);

    // search for Type in file array
  while ((sFGetFiles[nIndex].szType != NULL) && (nFuncReturn == OK_CN00)) {
    SAPDB_strcpy(szType, sFGetFiles[nIndex].szType);
    if ((sFGetFiles[nIndex].nShow <= nShow) &&
        (cn42_GetFileName(vcontrol->dbname, szType, szFileName, nFileIndex, szTemp) == OK_CN00)) {

      SAPDB_strcpy(szFileDir, szTemp);

      if (strstr(szFileName, FGET_WILDCARD) != NULL) {
/*
        sqlfopendirc (&szFileDir, &hDirectory, &szRealName, &rteFileErr);

        while ((rteFileErr.sp5fe_result == vf_ok) && (nFuncReturn == OK_CN00)) {

          SAPDB_strcpy(szFullReal, szFileDir);
          strcat(szFullReal, szRealName);
          if (cn42_FileMatch(szFileName, szFullReal, szToken)) {
            sqlfinfoc (szFullReal, &rteFileInfo, &rteFileErr );

            if (rteFileInfo.sp5fi_exists) {
              // check buffer size
              nLength = (int) (strlen(sFGetFiles[nIndex].szType) +
                               strlen(FGET_TOKENDEL) +
                               strlen(szToken) +
                               (6 * strlen(VALUE_SEPSTRING_CN00)) +
                               strlen(ASCII_OR_BINARY(sFGetFiles[nFileIndex].bBinary)) +
                               20 + // rteFileInfo.sp5fi_size
                               sizeof (rteFileInfo.sp5fi_date_modified) +
                               sizeof (rteFileInfo.sp5fi_time_modified) +
                               strlen(sFGetFiles[nIndex].szComment) +
                               strlen(szFullReal  + _tcslen(szFileDir)) +
                               strlen(LINE_SEPSTRING_CN00) );
              if ((replyLenMax - (pCurrent - replyData)) < nLength) {
                teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_TOOMANYFILES_CN00_1);
                nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
                break;
              } else {
                _stprintf (pCurrent, "%s%s%s%s%s%s%ld%s%.*s%s%.*s%s%s%s%s%s",
                                     (char   *) sFGetFiles[nIndex].szType,
                                     (char   *) FGET_TOKENDEL,
                                     (char   *) szToken,
                                     VALUE_SEPSTRING_CN00,
                                     (char   *) ((rteFileInfo.sp5fi_media_kind == vf_t_directory) ? DIRECTORY : ASCII_OR_BINARY(sFGetFiles[nFileIndex].bBinary)),
                                     VALUE_SEPSTRING_CN00,
                                     (long) rteFileInfo.sp5fi_size,
                                     VALUE_SEPSTRING_CN00,
                                     sizeof (rteFileInfo.sp5fi_date_modified), (char   *) rteFileInfo.sp5fi_date_modified,
                                     VALUE_SEPSTRING_CN00,
                                     sizeof (rteFileInfo.sp5fi_time_modified), (char   *) rteFileInfo.sp5fi_time_modified,
                                     VALUE_SEPSTRING_CN00,
                                     (char   *) sFGetFiles[nIndex].szComment,
                                     VALUE_SEPSTRING_CN00,
                                     (char   *) szFullReal  + strlen(szFileDir),
                                     LINE_SEPSTRING_CN00);
                pCurrent = pCurrent + strlen(pCurrent);
              } // end if
            } // end if
          } // end if

          sqlfreaddirc(hDirectory, &szRealName, &rteFileErr);
        } // end while 

        sqlfclosedirc (hDirectory, &rteFileErr);
*/
        nFuncReturn = cn40_FileGetListDir(replyData, nIndex, szFileDir, szFileName, szFileDir, pCurrent, replyLenMax - (int) (pCurrent - replyData));
      } else {
        sqlfinfoc (szFileName, &rteFileInfo, &rteFileErr );

        if (rteFileInfo.sp5fi_exists) {
          // check buffer size
          nLength = (int) (strlen(sFGetFiles[nIndex].szType) +
                           (6 * strlen(VALUE_SEPSTRING_CN00)) +
                           strlen(cn40_FileType(rteFileInfo, sFGetFiles[nFileIndex].nType)) +
                           20 + // rteFileInfo.sp5fi_size
                           sizeof (rteFileInfo.sp5fi_date_modified) +
                           sizeof (rteFileInfo.sp5fi_time_modified) +
                           strlen(sFGetFiles[nIndex].szComment) +
                           strlen(szFullReal  + _tcslen(szFileDir)) +
                           strlen(LINE_SEPSTRING_CN00) );
          if ((replyLenMax - (pCurrent - replyData)) < nLength) {
            // error
            teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_TOOMANYFILES_CN00_1);
            nFuncReturn = cn90AnswerEvent(replyData, replyLen, aEvent);
          } else {
            _stprintf (pCurrent, "%s%s%s%s%ld%s%.*s%s%.*s%s%s%s%s%s",
                                 (char   *) sFGetFiles[nIndex].szType,
                                 VALUE_SEPSTRING_CN00,
                                 (char   *) cn40_FileType(rteFileInfo, sFGetFiles[nFileIndex].nType),
                                 VALUE_SEPSTRING_CN00,
                                 (long) rteFileInfo.sp5fi_size,
                                 VALUE_SEPSTRING_CN00,
                                 sizeof (rteFileInfo.sp5fi_date_modified), (char   *) rteFileInfo.sp5fi_date_modified,
                                 VALUE_SEPSTRING_CN00,
                                 sizeof (rteFileInfo.sp5fi_time_modified), (char   *) rteFileInfo.sp5fi_time_modified,
                                 VALUE_SEPSTRING_CN00,
                                 (char   *) sFGetFiles[nIndex].szComment,
                                 VALUE_SEPSTRING_CN00,
                                 (char   *) szFileName + strlen(szFileDir),
                                 LINE_SEPSTRING_CN00);
            pCurrent = pCurrent + strlen(pCurrent);
          } // end if
        } // end if
      } // end if

    } // end if

    nIndex++;
  } // end while

  *replyLen = (int)strlen(replyData);

  return OK_CN00;
} // end cn42FileGetList

/*
  -----------------------------------------------------------------------------
  function:     cn42FileOperation
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileOperation
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szType;
  tsp00_Pathc         szFileName;
  tsp00_Pathc         szParam;
  int                 nToken;
  int                 nIndex;
  tsp00_C40c          szDate;
  tsp00_C40c          szOperation;
  tsp00_C40c          szLine;

  // read file id
  cn90GetToken(command->args, szType, 1, szType.size());

  // read qualifiers
  nToken = 2;
  szDate.Init();
  szLine.Init();
  szOperation.Init();
  while (cn90GetToken(command->args, szParam, nToken, szParam.size())) {
    if (strncmp(szParam, FGET_MODE_DATE, strlen(FGET_MODE_DATE)) == 0) {
      szDate.rawAssign(szParam.asCharp() + strlen(FGET_MODE_DATE));
    } else if (strncmp(szParam, FGET_MODE_OPERATION, strlen(FGET_MODE_OPERATION)) == 0) {
      szOperation.rawAssign(szParam.asCharp() + strlen(FGET_MODE_OPERATION));
    } else if (strncmp(szParam, FGET_MODE_LINE, strlen(FGET_MODE_LINE)) == 0) {
      szLine.rawAssign(szParam.asCharp() + strlen(FGET_MODE_LINE));
    } else {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
    ++nToken;
  } // end while

  // check operation
  if (nFuncReturn == OK_CN00) {
    if (szOperation.length() == 0 ||
        ((strcmp(szOperation, FGET_OP_SHRINK) != 0) && (strcmp(szOperation, FGET_OP_DELETE) != 0))) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  // look for file
  if (nFuncReturn == OK_CN00) {
    nFuncReturn = cn42_GetFileName(vcontrol->dbname, szType, szFileName, nIndex);
    if (nFuncReturn != OK_CN00) {
      cn90AnswerIError(replyData, replyLen, nFuncReturn);
    } // end if
  } // end if

  // check operation flag
  if (nFuncReturn == OK_CN00) {
    if (!sFGetFiles[nIndex].bOperation ) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  // check file type and timestamp settings
  if (nFuncReturn == OK_CN00) {
    if ( ( ((strlen(szDate) != 0) || (strlen(szLine) != 0)) && (sFGetFiles[nIndex].nType != FGET_TYP_ASCII) ) ||
         ( (strlen(szDate) != 0) && (sFGetFiles[nIndex].szTimestampFmt == NULL) && (strcmp(szOperation, FGET_OP_SHRINK) == 0) ) ) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  // execute operation
  if (nFuncReturn == OK_CN00) {
    if (strcmp(szOperation, FGET_OP_DELETE) == 0) {
      nFuncReturn = cn40_FileOperation( replyData, replyLen, szFileName, szDate, atoi(szLine), nIndex, true);
    } else if (strcmp(szOperation, FGET_OP_SHRINK) == 0) {
      nFuncReturn = cn40_FileOperation( replyData, replyLen, szFileName, szDate, atoi(szLine), nIndex, false);
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  *replyLen = (int) strlen(replyData);

  return nFuncReturn;

} // end cn42FileOperation

/*
  -----------------------------------------------------------------------------
  function:     cn42FileBackup
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileBackup
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szType;

  // read the parameters
  cn90GetToken(command->args, szType, 1, szType.size());

  return cn42BackupFile(vcontrol->dbname, szType, replyData, *replyLen);
} // end cn42FileBackup

/*
  -----------------------------------------------------------------------------
  function:     cn42FileRestore
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42FileRestore
      ( VControlDataT * vcontrol,
        CommandT      * command,
        char          * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szType;

  // read the parameters
  cn90GetToken(command->args, szType, 1, szType.size());

  return cn42RestoreFile(vcontrol->dbname, szType, replyData, *replyLen);
} // end cn42FileRestore

/*
  -----------------------------------------------------------------------------
  function:     cn42DiagHistList
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42DiagHistList
      ( VControlDataT * vcontrol,
        CommandT      * command,
        _TCHAR        * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("vcn42.cpp :: cn42DiagHistList");

  tcn00_Error         nFuncReturn = OK_CN00;
  tcn002_XpValueString szDiagPath;
  tsp00_C256          szDiagPathP;
  tsp00_C256          szFile;
  tsp00_Pathc         szDiagFile;
  tsp05_RteFileError  rteFileErr;
  tsp05_RteFileInfo   rteFInfo;
  char *              pCurrent = replyData;
  int                 nOffset     = vcontrol->dbname.length();
  void              * hDirectory  = NULL;  
  char                szTimestamp [PARAMETER_MAXLEN_CN90] = "";
  unsigned int        i = 0;
  unsigned int        j = 0;

  // get the diag directory
  if (cn20XParamGetValue(vcontrol->dbname, PAN_CRASH_HISTORY_PATH, szDiagPath) == OK_CN00) {

    // init OK Answer
    _stprintf (pCurrent, "%s%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00);
    pCurrent = pCurrent + strlen(pCurrent);

    if (cn90GetToken(command->args, szTimestamp, 1, PARAMETER_MAXLEN_CN90)) {
      // list the directory 
      sprintf(szDiagPathP, "%s%c%s%s", szDiagPath.asCharp(), 
                                      PATH_DELIMITER_CN90,
                                      vcontrol->dbname.asCharp(),
                                      DIAG_HIST_PATTERN);
      for (i = 0,j= 0; i < strlen(szDiagPathP); ++i) {
        szDiagPathP[i] = (szDiagPathP[i] == '?') ? szTimestamp[j++] : szDiagPathP[i];
      } // end if

      sqlfopendirc (&szDiagPathP, &hDirectory, &szFile, &rteFileErr);
      if (rteFileErr.sp5fe_result == vf_ok) {
        while (rteFileErr.sp5fe_result == vf_ok) {

            if ((replyLenMax - (pCurrent - replyData)) > (2 + (int) strlen(szFile))) {
              sprintf(szDiagFile, "%s%c%s",
                                  szDiagPathP.asCharp(),
                                  PATH_DELIMITER_CN90,
                                  szFile.asCharp());

              sqlfinfoc (szDiagFile.asCharp(), &rteFInfo, &rteFileErr );
              if (rteFileErr.sp5fe_result == vf_ok) {
                if (rteFInfo.sp5fi_media_kind == vf_t_file) {
                  sprintf(pCurrent, "%s%s%s%c%s%s",
                                     FGET_DIAGHIST_CN42.asCharp(),
                                     FGET_TOKENDEL,
                                     &szDiagPathP[strlen(szDiagPathP) - strlen(DIAG_HIST_PATTERN) + 1],
                                     PATH_DELIMITER_CN90,
                                     szFile.asCharp(),
                                     LINE_SEPSTRING_CN00);
                  pCurrent = pCurrent + strlen(pCurrent);
                } // end if
              } // end if
            } // end if

          sqlfreaddirc(hDirectory, &szFile, &rteFileErr);
        } // end while

        sqlfclosedirc (hDirectory, &rteFileErr);
      } // end if

    } else {

      // list the directory 
      SAPDB_strcpy(szDiagPathP, szDiagPath);
      sqlfopendirc (&szDiagPathP, &hDirectory, &szFile, &rteFileErr);
      if (rteFileErr.sp5fe_result == vf_ok) {
        while (rteFileErr.sp5fe_result == vf_ok) {
      
          // search for the database directories an list them
          if (cn42_DiagFileMatch(vcontrol->dbname.asCharp(), szFile)) {

            if ((replyLenMax - (pCurrent - replyData)) > (18 + (int) strlen(szFile))) {
              sprintf(pCurrent, "%.*s%.*s%.*s%.*s %s%s%c%s%s",
                                 DIAG_LEN_DATE,
                                 &szFile[nOffset + DIAG_POS_DATE],
                                 DIAG_LEN_HOUR,
                                 &szFile[nOffset + DIAG_POS_HOUR],
                                 DIAG_LEN_MINUTE,
                                 &szFile[nOffset + DIAG_POS_MINUTE],
                                 DIAG_LEN_SECOND,
                                 &szFile[nOffset + DIAG_POS_SECOND],
                                 VALUE_SEPSTRING_CN00,
                                 szDiagPath.asCharp(),
                                 PATH_DELIMITER_CN90,
                                 szFile.asCharp(),
                                 LINE_SEPSTRING_CN00);
              pCurrent = pCurrent + strlen(pCurrent);
            } // end if
          } // end if

          sqlfreaddirc(hDirectory, &szFile, &rteFileErr);
        } // end while

        sqlfclosedirc (hDirectory, &rteFileErr);
      } // end if
    
    } // end if

    if (rteFileErr.sp5fe_result == vf_notok) {
      teo200_EventList aFile(FUNCTION_NAME_MCN00_1, 1, TERR_CN00_1, "DBM", szDiagPathP.asCharp());
      teo200_EventList aRTE(aFile, FUNCTION_NAME_MCN00_1, rteFileErr.sp5fe_result, TERR_CN00_1, "DBM", "%.*s", rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_text.asCharp());
      teo200_EventList aDBM(aRTE, FUNCTION_NAME_MCN00_1, ERR_FILE_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBM);
    } // end if

  } else {
    teo200_EventList aParam(FUNCTION_NAME_MCN00_1, 1, TERR_CN00_1, "DBM", PAN_CRASH_HISTORY_PATH);
    teo200_EventList aDBM  (aParam, FUNCTION_NAME_MCN00_1, ERR_XPNOTFOUND_CN00_1);
    nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBM);
  } // end if

  *replyLen = (int) strlen(replyData);

  return nFuncReturn;
} // end cn42DiagHistList

/*
  -----------------------------------------------------------------------------
  function:     cn42DiagPack
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42DiagPack
      ( VControlDataT * vcontrol,
        CommandT      * command,
        _TCHAR        * replyData,
        int           * replyLen,
        int             replyLenMax)
{
  FUNCTION_DBG_MCN00_1("vcn42.cpp :: cn42DiagPack");

  tcn00_Error         nFuncReturn = OK_CN00;
  char                szToken     [PARAMETER_MAXLEN_CN90] = "";
  const char *        pClass;
  tsp00_Timestampc    szTimestamp;
  tsp00_Pathc         szArchive;
  tsp00_Pathc         szDiagFile;
  tsp00_Pathc         szDiagFileTarget;
  int                 nToken = 1;
  bool                bPRT   = false;
  bool                bLVC   = false;
  bool                bBKP   = false;
  bool                bCFG   = false;
  bool                bDUMP  = false;
  bool                bHIST  = false;
  cn54DBMTgz        * pTGZ   = NULL;

  // read the command parameters
  szArchive.Init();
  szTimestamp.Init();
  while (cn90GetToken(command->args, szToken, nToken, PARAMETER_MAXLEN_CN90) && (nFuncReturn == OK_CN00)) {
    if (strncmp(szToken, DIAG_FILE, DIAG_FILE_L) == 0 || strncmp(szToken, DIAG_file, DIAG_FILE_L) == 0 ) { 
      // read filename
      szArchive.rawAssign(&szToken[DIAG_FILE_L]);
    } else if (strncmp(szToken, DIAG_DATE, DIAG_DATE_L) == 0 || strncmp(szToken, DIAG_date, DIAG_DATE_L) == 0 ) { 
      // read timestamp
      szTimestamp.rawAssign(&szToken[DIAG_DATE_L]);
    } else if (strncmp(szToken, DIAG_CLASS, DIAG_CLASS_L) == 0 || strncmp(szToken, DIAG_class, DIAG_CLASS_L) == 0 ) { 
      // read classes
      pClass = strtok( &szToken[DIAG_CLASS_L], DIAG_CLASS_SEP );
      while( pClass != NULL ) {
        if (cn90Stricmp(pClass, DIAG_CLASS_PRT) == 0) {
          bPRT = true;
        } else if (cn90Stricmp(pClass, DIAG_CLASS_LVC) == 0) {
          bLVC = true;
        } else if (cn90Stricmp(pClass, DIAG_CLASS_BKP) == 0) {
          bBKP = true;
        } else if (cn90Stricmp(pClass, DIAG_CLASS_CFG) == 0) {
          bCFG = true;
        } else if (cn90Stricmp(pClass, DIAG_CLASS_DUMP) == 0) {
          bDUMP = true;
        } else if (cn90Stricmp(pClass, DIAG_CLASS_HIST) == 0) {
          bHIST = true;
        } else if (cn90Stricmp(pClass, DIAG_CLASS_ALL) == 0) {
          bPRT = true;
          bLVC = true;
          bBKP = true;
          bCFG = true;
          bDUMP = true;
        } else {
          nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
        } // end if
        pClass = strtok( NULL, DIAG_CLASS_SEP );
      } // end while
    } else  { 
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
    ++nToken;
  } // end while

  // default class
  if (nFuncReturn == OK_CN00) {
    if (!bPRT && !bLVC && !bBKP && !bCFG  && !bDUMP && !bHIST) {
      bPRT = true;
    } // end if
  } // end if

  // check hist + timestamp
  if (nFuncReturn == OK_CN00) {
    if ( (bHIST && (szTimestamp.length() == 0)) || (!bHIST && (szTimestamp.length() != 0)) ) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_PARAM_CN00);
    } // end if
  } // end if

  // check the archive name
  if ((nFuncReturn == OK_CN00) && (szArchive.length() == 0)) {
    nFuncReturn = cn90AnswerIError(replyData, replyLen, cn42GetFileName(vcontrol->dbname, FGET_DIAGPACK_CN42, szArchive));
  } // end if

  // open the archive
  if (nFuncReturn == OK_CN00) {
    pTGZ = new cn54DBMTgz(szArchive);
    if (pTGZ == NULL) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_MEM_CN00);
    } else if (pTGZ->lastEvent()) {
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, pTGZ->lastEvent());
    } // end if
  } // end if

  // HISTORY files 
  if ((nFuncReturn == OK_CN00) && bHIST) {
    tsp05_RteFileError  rteFileErr;
    tsp05_RteFileInfo   rteFInfo;
    void              * hDirectory  = NULL;  
    tcn002_XpValueString szDiagPath;
    tsp00_C256          szDiagPathP;
    unsigned int        i      = 0;
    unsigned int        j      = 0;
    tsp00_C256          szFile;

    if (cn20XParamGetValue(vcontrol->dbname, PAN_CRASH_HISTORY_PATH, szDiagPath) == OK_CN00) {
      // create the directory name
      sprintf(szDiagPathP, "%s%c%s%s", szDiagPath.asCharp(), 
                                      PATH_DELIMITER_CN90,
                                      vcontrol->dbname.asCharp(),
                                      DIAG_HIST_PATTERN);
      for (i = 0,j= 0; i < strlen(szDiagPathP); ++i) {
        szDiagPathP[i] = (szDiagPathP[i] == '?') ? szTimestamp[j++] : szDiagPathP[i];
      } // end if

      // read the directory
      sqlfopendirc (&szDiagPathP, &hDirectory, &szFile, &rteFileErr);
      if (rteFileErr.sp5fe_result == vf_ok) {
        while ((rteFileErr.sp5fe_result == vf_ok) && (nFuncReturn == OK_CN00)) {
          sprintf(szDiagFile,       "%s%c%s", szDiagPathP.asCharp(), PATH_DELIMITER_CN90, szFile.asCharp());
          szDiagFileTarget.rawAssign(&szDiagFile[szDiagFile.length()       - 
                                                 strlen(szFile)            -
                                                 vcontrol->dbname.length() -
                                                 strlen(DIAG_HIST_PATTERN) -
                                                 1]);
          sqlfinfoc (szDiagFile.asCharp(), &rteFInfo, &rteFileErr );
          if (rteFileErr.sp5fe_result == vf_ok) {
            if (rteFInfo.sp5fi_media_kind == vf_t_file) {
              if (!pTGZ->append(szDiagFile, szDiagFileTarget)) {
                nFuncReturn = cn90AnswerEvent(replyData, replyLen, pTGZ->lastEvent());
              } // end if
            } // end if
          } // end if
          sqlfreaddirc(hDirectory, &szFile, &rteFileErr);
        } // end while

        sqlfclosedirc (hDirectory, &rteFileErr);
      } // end if
      if (rteFileErr.sp5fe_result != vf_ok) {
        teo200_EventList aFile(FUNCTION_NAME_MCN00_1, 1, TERR_CN00_1, "DBM", szDiagPathP.asCharp());
        teo200_EventList aRTE(aFile, FUNCTION_NAME_MCN00_1, rteFileErr.sp5fe_result, TERR_CN00_1, "DBM", "%.*s", rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_text.asCharp());
        teo200_EventList aDBM(aRTE, FUNCTION_NAME_MCN00_1, ERR_FILE_CN00_1);
        nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBM);
      } // end if

    } else {
      teo200_EventList aParam(FUNCTION_NAME_MCN00_1, 1, TERR_CN00_1, "DBM", PAN_CRASH_HISTORY_PATH);
      teo200_EventList aDBM  (aParam, FUNCTION_NAME_MCN00_1, ERR_XPNOTFOUND_CN00_1);
      nFuncReturn = cn90AnswerEvent(replyData, replyLen, aDBM);
    } // end if
  } // end if

  // search for the other files
  if ((nFuncReturn == OK_CN00) && (bPRT || bLVC || bBKP || bCFG || bDUMP)) {
    int                 nIndex = 0;
    tsp00_Pathc         szType;
    tsp00_Pathc         szFileName;
    int                 nFileIndex;
    tsp00_Pathc         szFileDir;
    tsp00_C256          szFileDirP;
    tsp00_C256          szRealName;
    void              * hDirectory  = NULL;  
    tsp05_RteFileInfo   rteFileInfo;
    tsp05_RteFileError  rteFileErr;
    tsp00_Pathc         szToken;
    tsp00_Pathc         szFullReal;

    while ((sFGetFiles[nIndex].szType != NULL) && (nFuncReturn == OK_CN00)) {
      if (sFGetFiles[nIndex].szClass != NULL) {
        if ( ((strcmp(sFGetFiles[nIndex].szClass, DIAG_CLASS_PRT)  == 0) && bPRT)  ||
             ((strcmp(sFGetFiles[nIndex].szClass, DIAG_CLASS_LVC)  == 0) && bLVC)  ||
             ((strcmp(sFGetFiles[nIndex].szClass, DIAG_CLASS_BKP)  == 0) && bBKP)  ||
             ((strcmp(sFGetFiles[nIndex].szClass, DIAG_CLASS_CFG)  == 0) && bCFG)  ||
             ((strcmp(sFGetFiles[nIndex].szClass, DIAG_CLASS_DUMP) == 0) && bDUMP)    ) {
          // class match
          szType.rawAssign(sFGetFiles[nIndex].szType);
          if (cn42_GetFileName(vcontrol->dbname, szType, szFileName, nFileIndex, szFileDir) == OK_CN00) {

            if (strstr(szFileName, FGET_WILDCARD) != NULL) {

              // multi file append (scan directory for matches)
              SAPDB_strcpy(szFileDirP, szFileDir);
              sqlfopendirc (&szFileDirP, &hDirectory, &szRealName, &rteFileErr);
              if (rteFileErr.sp5fe_result == vf_ok) {
                while (rteFileErr.sp5fe_result == vf_ok) {
                  SAPDB_strcpy(szFullReal, szFileDir);
                  strcat(szFullReal, szRealName);
                  if (cn42_FileMatch(szFileName, szFullReal, szToken)) {
                    szDiagFile.rawAssign(szFullReal.asCharp());
                    szDiagFileTarget.rawAssign(&szFullReal[szFileDir.length()]);
                    if (!pTGZ->append(szDiagFile, szDiagFileTarget)) {
                      nFuncReturn = cn90AnswerEvent(replyData, replyLen, pTGZ->lastEvent());
                    } // end if
                  } // end if
                  sqlfreaddirc(hDirectory, &szRealName, &rteFileErr);
                } // end while
                sqlfclosedirc (hDirectory, &rteFileErr);
              } // end if

            } else {

              // single file append
              sqlfinfoc (szFileName, &rteFileInfo, &rteFileErr );
              if (rteFileInfo.sp5fi_exists) {
                szDiagFile.rawAssign(szFileName.asCharp());
                szDiagFileTarget.rawAssign(&szFileName[szFileDir.length()]);
                if (!pTGZ->append(szDiagFile, szDiagFileTarget)) {
                  nFuncReturn = cn90AnswerEvent(replyData, replyLen, pTGZ->lastEvent());
                } // end if
              } // end if

            } // end if

          } // end if
        } // end if
      } // end if
      ++nIndex;
    } // end while
  } // end if

  // answer
  if (pTGZ != NULL) {
    delete pTGZ;
  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, replyLen, NULL);
  } // end if

  return nFuncReturn;
} // end cn42DiagPack

/*
  -----------------------------------------------------------------------------
  function:     cn42BackupFile
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42BackupFile
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType)
{
  tsp00_Int4 replyLen;

  return cn42BackupFile(szDbName, szType, NULL, replyLen);
} // end cn42BackupFile
/*
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42BackupFile
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        char              * replyData,
        tsp00_Int4        & replyLen )
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szFileName;
  tsp00_Pathc         szBackupName;
  tsp01_RteError      aNewRteError;
  tsp05_RteFileError  aRteFileError;
  tsp05_RteFileInfo   aRteFileInfo;

  char                szReply[PARAMETER_MAXLEN_CN90];
  replyData = (replyData == NULL) ? &szReply[0] : replyData;

  // backup one file
  cn42GetFileName(szDbName, szType, szFileName, szBackupName);

  if (strlen(szBackupName) == 0) {

    // can't compute backupname (invalid type or backup impossible)
    nFuncReturn = ERR_PARAM_CN00;
    if (replyData != NULL) {
      cn90AnswerIError(replyData, &replyLen, nFuncReturn);
    } // end if

  } else {

    sqlfinfoc (szFileName, &aRteFileInfo, &aRteFileError);

    if (aRteFileError.sp5fe_result == vf_ok) {

      if (aRteFileInfo.sp5fi_exists) {
        // copy the file
        if (!sqlfilecopyc( szFileName, szBackupName, &aNewRteError )) {
          nFuncReturn = ERR_RTEEXT_CN00;
          if (replyData != NULL) {
            cn90AnswerNewRTEError (replyData, &replyLen, nFuncReturn, &aNewRteError );
          } // end if
        } // end if
      } // end if

    } else {

      nFuncReturn = ERR_RTE_CN00;
      if (replyData != NULL) {
        cn90AnswerRTEError (replyData, &replyLen, nFuncReturn, aRteFileError.sp5fe_text, aRteFileError.sp5fe_text.length(), aRteFileError.sp5fe_result);
      } // end if

    } // end if

  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, &replyLen, NULL);
  } // end if

  return nFuncReturn;
} // end cn42BackupFile

/*
  -----------------------------------------------------------------------------
  function:     cn42RestoreFile
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42RestoreFile
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType)
{
  tsp00_Int4 replyLen;

  return cn42RestoreFile(szDbName, szType, NULL, replyLen);
} // end cn42RestoreFile
/*
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42RestoreFile
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        char                * replyData,
        tsp00_Int4          & replyLen )
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szFileName;
  tsp00_Pathc         szBackupName;
  tsp01_RteError      aNewRteError;
  tsp05_RteFileError  aRteFileError;
  tsp05_RteFileInfo   aRteFileInfo;

  char                szReply[PARAMETER_MAXLEN_CN90];
  replyData = (replyData == NULL) ? &szReply[0] : replyData;

  // backup one file
  cn42GetFileName(szDbName, szType, szFileName, szBackupName);

  if (strlen(szBackupName) == 0) {

    // can't compute backupname (invalid type or backup impossible)
    nFuncReturn = ERR_PARAM_CN00;
    if (replyData != NULL) {
      cn90AnswerIError(replyData, &replyLen, nFuncReturn);
    } // end if

  } else {

    sqlfinfoc (szBackupName, &aRteFileInfo, &aRteFileError);

    if (aRteFileError.sp5fe_result == vf_ok) {

      if (aRteFileInfo.sp5fi_exists) {
        // copy the file
        if (!sqlfilecopyc( szBackupName, szFileName, &aNewRteError )) {
          nFuncReturn = ERR_RTEEXT_CN00;
          if (replyData != NULL) {
            cn90AnswerNewRTEError (replyData, &replyLen, nFuncReturn, &aNewRteError );
          } // end if
        } // end if
      } // end if

    } else {

      nFuncReturn = ERR_RTE_CN00;
      if (replyData != NULL) {
        cn90AnswerRTEError (replyData, &replyLen, nFuncReturn, aRteFileError.sp5fe_text, aRteFileError.sp5fe_text.length(), aRteFileError.sp5fe_result);
      } // end if

    } // end if

  } // end if

  if (nFuncReturn == OK_CN00) {
    cn90AnswerOK (replyData, &replyLen, NULL);
  } // end if

  return nFuncReturn;
} // end cn42RestoreFile

/*
  -----------------------------------------------------------------------------
  public function cn42GetFileName
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        tsp00_Pathc         & szBackupName)
{
  tsp00_Pathc szFileDir;
  int         nIndex;

  return cn42_GetFileName ( szDbName, szType, szFileName, szBackupName, nIndex, szFileDir);
} // end cn42GetFileName
/*
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName)
{
  tsp00_Pathc szBackupName;
  tsp00_Pathc szFileDir;
  int         nIndex;

  return cn42_GetFileName ( szDbName, szType, szFileName, szBackupName, nIndex, szFileDir);
} // end cn42GetFileName

/*
  -----------------------------------------------------------------------------
  private function cn42_GetFileName
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        int                 & nIndex)
{
  tsp00_Pathc szBackupName;
  tsp00_Pathc szFileDir;

  return cn42_GetFileName ( szDbName, szType, szFileName, szBackupName, nIndex, szFileDir);
} // end cn42GetFileName
/*
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        int                 & nIndex,
        tsp00_Pathc         & szFileDir)
{
  tsp00_Pathc szBackupName;

  return cn42_GetFileName ( szDbName, szType, szFileName, szBackupName, nIndex, szFileDir);
} // end cn42GetFileName
/*
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_GetFileName
      ( const tsp00_DbNamec & szDbName,
        const tsp00_Pathc   & szType,
        tsp00_Pathc         & szFileName,
        tsp00_Pathc         & szBackupName,
        int                 & nIndex,
        tsp00_Pathc         & szFileDir)
{
  tcn00_Error         nFuncReturn  = OK_CN00;
  char              * pExtension   = NULL;
  tsp00_C256          szPath;
  tcn002_XpValueString szValue;
  char                szTemp  [PARAMETER_MAXLEN_CN90] = "";
  const char        * pToken  = 0;
  char              * pToken2 = 0;
  int                 nLength = 0;
  bool                bOValid  = true;
  bool                bBValid  = true;
  tsp00_DbNamec       szLocDbName;
  tsp01_RteError      aRteError;

  SAPDB_strcpy(szFileName, "");
  SAPDB_strcpy(szFileDir,  "");
  SAPDB_strcpy(szBackupName, "");

  pToken = strstr(szType, FGET_TOKENDEL);
  if (pToken == NULL) {
    nLength = (int)strlen(szType);
  } else {
    nLength = (int)(pToken - &szType[0]);
    pToken++;
    if ( (strstr(pToken, FGET_UPPER)     != NULL) ||
//         (strstr(pToken, FGET_SLASH)     != NULL) ||
//         (strstr(pToken, FGET_BACKSLASH) != NULL) ||
         (strstr(pToken, FGET_DRIVE)     != NULL)    ) {
      nFuncReturn = ERR_PARAM_CN00;
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    szLocDbName.rawAssign(szDbName.asCharp());


    // search for Type in file array
    nIndex = 0;
    while (sFGetFiles[nIndex].szType != NULL) {

      // match?
      if (strncmp(sFGetFiles[nIndex].szType, szType, nLength) == 0) {

        sFGetFiles[nIndex].nType = sFGetFiles[nIndex].nOrgType;

        // init out values
        SAPDB_strcpy(szFileName,   "");

        // compute source directory
        switch (sFGetFiles[nIndex].nLocation) {
          case FGET_LOC_DBROOT:
            // dir of dbmserver
            SAPDB_strcpy(szFileName, "");
            break;
          case FGET_LOC_WRK:
            // work dir
            cn90GetWrkPath(szPath);
            SAPDB_strcpy(szFileName, szPath);
            break;
          case FGET_LOC_SAP:
            // sap dir
            SAPDB_strcpy(szFileName, FGET_LOC_SAP_TXT);
            strcat(szFileName, "/");
            break;
          case FGET_LOC_ENV:
            // env dir
            cn90GetVersionEnvPath(szPath);
            SAPDB_strcpy(szFileName, szPath);
            break;
          case FGET_LOC_DBA:
            // dba protocol dir
            if (cn20XParamGetValue(szLocDbName, PAN_RUNDIR, szValue) == OK_CN00) {
              SAPDB_strcpy(szFileName, szValue);
              strcat(szFileName, "/");
              strcat(szFileName, FGET_LOC_DBA_TXT);
              cn90DirCreate(szFileName, &aRteError);
              strcat(szFileName, "/");
            } else {
              bOValid = false;
            } // end if
            break;
          case FGET_LOC_RUNDIR:
            // rundirectory
            if (cn20XParamGetValue(szLocDbName, PAN_RUNDIR, szValue) == OK_CN00) {
              SAPDB_strcpy(szFileName, szValue);
              strcat(szFileName, "/");
            } else {
              bOValid = false;
            } // end if
            break;
          case FGET_LOC_CONFIG:
            // config dir
            cn90GetCfgPath(szPath);
            SAPDB_strcpy(szFileName, (char   *) szPath);
            break;
          case FGET_LOC_ANALYZER:
            if (cn42GetFileName(szLocDbName, FGET_ANALYZER_CN42, szFileName) != OK_CN00) {
              bOValid = false;
            } else {
              strcat(szFileName, "/");
            } // end if
            break;
          case FGET_LOC_HISTDIR:
            // rundirectory
            if (cn20XParamGetValue(szDbName, (*(tsp00_XpKeyTypec *) PAN_CRASH_HISTORY_PATH), szValue) == OK_CN00) {
              SAPDB_strcpy(szFileName, szValue);
              strcat(szFileName, "/");
            } else {
              bOValid = false;
            } // end if
            break;
          default:
            bOValid = false;
            break;
        } // end switch

        SAPDB_strcpy(szFileDir, szFileName);
        cn90ChangePathDelimiter(szFileDir);

        // compute source filename
        if (sFGetFiles[nIndex].szXParam != NULL) {
          // look for xparam
          if (cn20XParamGetValue(szLocDbName, *(tsp00_XpKeyTypec *) sFGetFiles[nIndex].szXParam, szValue) == OK_CN00) {
            strcat(szFileName, szValue);
          } else {
            bOValid = false;
          } // end if
        } else if (sFGetFiles[nIndex].szName == FGET_NAME_DB) {
          // use dbname
          strcat(szFileName, szLocDbName);
        } else if (sFGetFiles[nIndex].szName != NULL) {

          const char * pNode = strstr(sFGetFiles[nIndex].szName, FGET_NODE);
          if (pNode != NULL) {
            int nNode    = pNode - &(sFGetFiles[nIndex].szName[0]);

            if ((nNode > 0) && (sFGetFiles[nIndex].szName[nNode-1] == '\\')) {
              // use szName
              strcat(szFileName, sFGetFiles[nIndex].szName);
            } else {
              strcat(szFileName, sFGetFiles[nIndex].szName);
              szFileName[strlen(szFileName) - (strlen(sFGetFiles[nIndex].szName) - nNode)] = CHAR_STRINGTERM_CN90;
              char  szHostName [ sizeof ( tsp00_NodeId ) + 1 ];
              int rc = sql43_get_my_host_name ( szHostName, sizeof(tsp00_NodeId) );
              if ( rc == 0 ) {
                strcat(szFileName, szHostName);
              } // end if
              strcat(szFileName, pNode+1);
            } // end if

          } else {
            // use szName
            strcat(szFileName, sFGetFiles[nIndex].szName);
          } // end if
        } // end if

        // compute source extension
        if (sFGetFiles[nIndex].szExt != NULL) {
          // use szExt-Field
          strcat(szFileName, sFGetFiles[nIndex].szExt);
        } // end if

        pToken2 = strstr(szFileName, FGET_WILDCARD);
        if (pToken != NULL && pToken2 != NULL) {
          *pToken2 = 0;
          pToken2++;
          SAPDB_strcpy(szTemp, szFileName);
          strcat(szTemp, pToken);
          strcat(szTemp, pToken2);
          SAPDB_strcpy(szFileName, szTemp);
        } else if ((pToken != NULL) && (sFGetFiles[nIndex].nType == FGET_TYP_DIRECTORY)) {
          SAPDB_strcpy(szTemp, szFileName);
          strcat(szTemp, pToken);
          SAPDB_strcpy(szFileName, szTemp);
        } // end if

        cn90ChangePathDelimiter(szFileName);

        // backupname required and possible
        if (sFGetFiles[nIndex].szBaName != NULL) {

          // init out values
          SAPDB_strcpy(szBackupName, "");

          // compute backup directory
          switch (sFGetFiles[nIndex].nBaLocation) {
            case FGET_LOC_DBROOT:
              // dir of dbmserver
              SAPDB_strcpy(szBackupName, "");
              break;
            case FGET_LOC_WRK:
              // work dir
              cn90GetWrkPath(szPath);
              SAPDB_strcpy(szBackupName, (char   *) szPath);
              break;
            case FGET_LOC_ENV:
              // env dir
              cn90GetVersionEnvPath(szPath);
              SAPDB_strcpy(szBackupName, (char   *) szPath);
              break;
            case FGET_LOC_RUNDIR:
              // rundirectory
              if (cn20XParamGetValue(szLocDbName, PAN_RUNDIR, szValue) == OK_CN00) {
                SAPDB_strcpy(szBackupName, szValue);
                strcat(szBackupName, "/");
              } else {
                bBValid = false;
              } // end if
              break;
            case FGET_LOC_CONFIG:
              // config dir
              cn90GetCfgPath(szPath);
              SAPDB_strcpy(szBackupName, (char   *) szPath);
              break;
          case FGET_LOC_ANALYZER:
            if (cn42GetFileName(szLocDbName, FGET_ANALYZER_CN42, szBackupName) != OK_CN00) {
              bBValid = false;
            } else {
              strcat(szBackupName, "/");
            } // end if
            break;
           default:
              bBValid = false;
              break;
          } // end switch

          // compute backup filename
          if (sFGetFiles[nIndex].szBaName == FGET_NAME_DB) {
            // use dbname
            strcat(szBackupName, szLocDbName);
          } else if (sFGetFiles[nIndex].szBaName != NULL) {
            // use szName
            strcat(szBackupName, sFGetFiles[nIndex].szBaName);
          } // end if

          // compute backup extension
          if (sFGetFiles[nIndex].szBaExt == FGET_ORG_EXT) {
            // use extension form original file
            pExtension = strrchr(szFileName, '.');
            if (pExtension != NULL) {
               strcat(szBackupName, pExtension);
            } // end if
          } else if (sFGetFiles[nIndex].szBaExt != NULL) {
            // use szExt
            strcat(szBackupName, sFGetFiles[nIndex].szBaExt);
          } // end if

          cn90ChangePathDelimiter(szBackupName);

        } // end if

        if (!bOValid) {
          SAPDB_strcpy(szFileName, "");
          SAPDB_strcpy(szFileDir,  "");
        } else if ((strlen(szFileName) > 0)  && 
                   ((szFileName[strlen(szFileName) - 1] == '\\') || 
                    (szFileName[strlen(szFileName) - 1] == '/' )    )) {
            szFileName[strlen(szFileName) - 1] = 0;
        } // end if
        if (!bBValid) {
          SAPDB_strcpy(szBackupName, "");
        } else if ((strlen(szBackupName) > 0)  && 
                   ((szBackupName[strlen(szBackupName) - 1] == '\\') || 
                    (szBackupName[strlen(szBackupName) - 1] == '/' )    )) {
            szBackupName[strlen(szBackupName) - 1] = 0;
        } // end if
        break;
      } // end if

      nIndex++;
    } // end while

    if (sFGetFiles[nIndex].szType == NULL) {
      nFuncReturn = ERR_PARAM_CN00;
    } // end if

  } // end if

  return nFuncReturn;
} // end cn42_GetFileName

/*
  -----------------------------------------------------------------------------
  function:     cn42RemoveFiles
  -----------------------------------------------------------------------------
 */
void cn42RemoveFiles
      ( const tsp00_DbNamec & szDbName)
{
  long                nIndex       = 0;
  tsp00_Pathc         szType;
  tsp00_Pathc         szFileName;
  tsp00_Pathc         szBackupName;
  char                replyData[1024];
  int                 replyLen;
  tsp05_RteFileError  rteFileErr;

  while (sFGetFiles[nIndex].szType != NULL) {
    if (sFGetFiles[nIndex].bRemove) {
      SAPDB_strcpy(szType, sFGetFiles[nIndex].szType);
      strcat(szType, FGET_TOKENDEL);
      strcat(szType, FGET_WILDCARD);

      if (cn42GetFileName(szDbName, szType, szFileName, szBackupName) == OK_CN00) {
        cn40_FileOperation( replyData, &replyLen, szFileName, "", 0, nIndex, true);
        if (strlen(szBackupName) > 0) {
          sqlferasec(szBackupName, &rteFileErr);
        } // end if
      } // end if

    } // end if
    nIndex++;
  } // end while

} // end cn42RemoveFiles

/*
  -----------------------------------------------------------------------------
  public function:     cn42OpenFile
  -----------------------------------------------------------------------------
 */
tcn00_Error cn42OpenFile
      ( const tsp00_DbNamec    & szDbName,
        const tsp00_Pathc      & szType,
        tsp05_RteFileMode_Param  fileMode,
        tsp00_Int4             & hFile,
        tsp05_RteFileError     & errFile)
{
  tcn00_Error         nReturn = OK_CN00;
  tsp00_Pathc         szFile;
  tsp00_Pathc         szBackupFile;
  tsp00_Pathc         szFileDir;
  int                 nIndex = 0;

  // prepare file name
  nReturn = cn42_GetFileName(szDbName, szType, szFile, szBackupFile, nIndex, szFileDir);

  if (nReturn == OK_CN00) {
    // open file for write
    sqlfopenc(szFile, (sFGetFiles[nIndex].nType != FGET_TYP_ASCII) ? sp5vf_binary : sp5vf_text, fileMode, sp5bk_buffered, &hFile, &errFile );
    if ((errFile.sp5fe_result != vf_ok) && (strlen(szBackupFile) > 0)) {
      cn42RestoreFile(szDbName, FGET_DBMCFG_CN42);
      sqlfopenc(szFile, (sFGetFiles[nIndex].nType != FGET_TYP_ASCII) ? sp5vf_binary : sp5vf_text, fileMode, sp5bk_buffered, &hFile, &errFile );
      if (errFile.sp5fe_result != vf_ok) {
        sqlfopenc(szBackupFile, (sFGetFiles[nIndex].nType != FGET_TYP_ASCII) ? sp5vf_binary : sp5vf_text, fileMode, sp5bk_buffered, &hFile, &errFile );
      }  // end if
    }  // end if
    if (errFile.sp5fe_result != vf_ok) {
      nReturn = ERR_FILE_CN00;
    }  // end if
  }  // end if

  return nReturn;
} /* end cn42OpenFile */

/*
  -----------------------------------------------------------------------------
  implementation private functions
  -----------------------------------------------------------------------------
 */

/*
  -----------------------------------------------------------------------------
  function:     cn42_PrintFileInfo
  -----------------------------------------------------------------------------
 */
static void cn42_PrintFileInfo
      ( char         *szName,
        char         *szBuffer)
{
    tsp05_RteFileInfo     rteFileInfo;
    tsp05_RteFileError    rteFileErr;
    static const char     * mediastr [] = FILEINFO_MEDIATYPE;

    sqlfinfoc (szName, &rteFileInfo, &rteFileErr );

    if (rteFileInfo.sp5fi_exists) {
      sprintf (szBuffer,
               "\"%s\",true,%s,%s,%s,%ld,\"%.*s\",\"%.*s\",\"%s\"\n",
               szName,
               BOOLSTR_CN00 (rteFileInfo.sp5fi_readable),
               BOOLSTR_CN00 (rteFileInfo.sp5fi_writeable),
               BOOLSTR_CN00 (rteFileInfo.sp5fi_is_link),
               rteFileInfo.sp5fi_size,
               sizeof (rteFileInfo.sp5fi_date_modified), (char   *) rteFileInfo.sp5fi_date_modified,
               sizeof (rteFileInfo.sp5fi_time_modified), (char   *) rteFileInfo.sp5fi_time_modified,
               mediastr [rteFileInfo.sp5fi_media_kind]);
    } else {
      sprintf  (szBuffer, "\"%s\",false,,,,,,,\n", szName);
    } // end if

} // end cn42_PrintFileInfo

/*
  -----------------------------------------------------------------------------
  function:     cn42_FileRead
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_FileRead
      ( const char    * szArguments,
        char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const bool      bNext)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szName     [PARAMETER_MAXLEN_CN90] = "";
  char                szToken    [PARAMETER_MAXLEN_CN90] = "";
  bool                bNoClose   = false;
  long                nIndex;
  long                nSwitch;
  tsp00_Int4            hFile;

  tsp05_RteFileError       rteFileErr;
  tsp05_RteFileInfo        rteFInfo;
  tsp05_RteDataKind_Enum   rteDatakind   = sp5vf_text;
  tsp05_RteFileMode_Enum   rteFilemode   = sp5vf_read;
  tsp05_RteBufferingKind_Enum rteBuffering  = sp5bk_unbuffered;

  /* read the parameters */
  nIndex = 1;
  while ( cn90GetToken(szArguments, szToken, nIndex, PARAMETER_MAXLEN_CN90) ) {
    nSwitch = 0;
    if (szToken[nSwitch] == OPEN_SWITCH) {
      nSwitch++;
      while (szToken[nSwitch] != CHAR_STRINGTERM_CN90) {
        switch (szToken[nSwitch]) {
          case OPEN_MODE_BIN:
            rteDatakind  = sp5vf_binary;
            break;
          case OPEN_MODE_ASCII:
            rteDatakind  = sp5vf_text;
            break;
          default:
            nFuncReturn = ERR_PARAM_CN00;
            break;
        } /* end switch */
        nSwitch++;
      } /* end while */
    } else {
      if (strlen(szName) == 0) {
        SAPDB_strcpy(szName, szToken);
      } else {
        if (strcmp(szToken, FILE_OPT_NOCLOSE) == 0) {
          bNoClose = true;
        } else {
          nFuncReturn = ERR_PARAM_CN00;
        } // end if
      } /* end if */
    } /* end if */
    nIndex++;
  } /* end while */

  if (strlen(szName) == 0 || nFuncReturn == ERR_PARAM_CN00) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  if (nFuncReturn == OK_CN00) {

    if (bNext) {
      // read handle
      hFile = atol(szName);
    } else {

      // execute fileopen
      sqlfinfoc (szName, &rteFInfo, &rteFileErr );
      if (rteFileErr.sp5fe_result != vf_ok) {
        nFuncReturn = ERR_RTE_CN00;
        cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      } else {
        sqlfopenc (szName, rteDatakind, rteFilemode, rteBuffering, &hFile, &rteFileErr );

        if (rteFileErr.sp5fe_result != vf_ok) {
          nFuncReturn = ERR_RTE_CN00;
          cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
        } // end if
      } // end if

    } // end if

    // read contents
    if (nFuncReturn == OK_CN00) {
      nFuncReturn = cn42_FileReadNext( replyData,
                                       replyLen,
                                       replyLenMax,
                                       hFile,
                                       rteFInfo.sp5fi_size,
                                       bNoClose,
                                       (rteDatakind == sp5vf_text),
                                       false,
                                       -1);
    } /* end if */
  } /* end if */

  return nFuncReturn;

} // end cn42_FileRead

/*
  -----------------------------------------------------------------------------
  function:     cn42_FileReadNext
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_FileReadNext
      ( char             * replyData,
        int              * replyLen,
        const int          replyLenMax,
        const tsp00_Int4     hFile,
        const tsp00_Longint  nSize,
        const bool         bNoClose,
        const bool         bAscii,
        const bool         bRemoveEmptyLines,
        const int          nIndex)
{
  tcn00_Error            nFuncReturn = OK_CN00;
  char                 * pCurrPos;
  char                 * pFlagPos;
  char                 * pLenPos;
  tsp00_Longint            nLength = 0;
  tsp00_Longint            nOutLen = 0;
  tsp05_RteFileError     rteFileErr;
  char                   szTmp[PARAMETER_MAXLEN_CN90];

  /* print OK and handle of file */
  sprintf (replyData, "%s%s%5d%s", ANSWER_OK_CN00,      LINE_SEPSTRING_CN00,
                                   hFile,               LINE_SEPSTRING_CN00);

  pFlagPos = replyData + strlen(replyData);
  sprintf ( pFlagPos , "%s%s" , CONT_FLAG_CONTINUE, LINE_SEPSTRING_CN00 );

  pLenPos = replyData + strlen(replyData);
  sprintf ( pLenPos, "%20ld%20ld%s" , (long) 0, (long) 0, LINE_SEPSTRING_CN00 );

  pCurrPos  = replyData + strlen(replyData);
  *replyLen = (int)strlen(replyData);

  // for test only
  // replyLenMax = 150;

  // fill buffer
  do {
    sqlfreadc(hFile, pCurrPos, replyLenMax - *replyLen - ((bAscii) ? 2 : 0), &nOutLen, &rteFileErr);

    if (!(bAscii && bRemoveEmptyLines && cn42_IsLineEmpty(pCurrPos))) {
      *replyLen = *replyLen + (int)nOutLen;
      nLength   = nLength   + nOutLen;

      if  ( rteFileErr.sp5fe_warning == sp5vfw_no_warning &&
            rteFileErr.sp5fe_result  == vf_ok             &&
            bAscii) {
        *replyLen = *replyLen + 2;
        nLength   = nLength   + 2;
        replyData[*replyLen-2] = '\r';
        replyData[*replyLen-1] = '\n';
      } // end if

      pCurrPos = replyData + *replyLen;
    } // end if

  } while ( *replyLen + ((bAscii) ? 2 : 0) <  replyLenMax       &&
            rteFileErr.sp5fe_warning       == sp5vfw_no_warning &&
            rteFileErr.sp5fe_result        == vf_ok                );

  // end handling
  replyData[*replyLen] = '\0';
  sprintf ( szTmp, "%20ld%20ld", (long) nSize, (long) nLength);
  strncpy(pLenPos, szTmp, strlen(szTmp));

  if ( rteFileErr.sp5fe_result == vf_eof ) {
    sprintf ( szTmp, "%s", CONT_FLAG_END );
    strncpy(pFlagPos, szTmp, strlen(szTmp));

    if (!bNoClose) {
      sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
    } // end if
  } else {
    if (nIndex > -1) {
      // prepare next command for file get
      sprintf(cn00DBMServerData::vcontrol()->szNextCommand, "file_getnext %s %d", sFGetFiles[nIndex].szType ,hFile);
      cn00DBMServerData::vcontrol()->nNextCommandSkip = 3;
    } // end if
  } // end if

  if (rteFileErr.sp5fe_result == vf_notok) {
    nFuncReturn = ERR_RTE_CN00;
    cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
  } // end if

  return nFuncReturn;

} // end cn42_FileReadNext

/*
  -----------------------------------------------------------------------------
  function:     cn42_FileReadFirst
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_FileReadFirst
      ( char             * replyData,
        int              * replyLen,
        const int          replyLenMax,
        const tsp00_Int4     hFile,
        const tsp00_Longint  nSize,
        const int          nIndex,
        const char *       pDate,
        int                nLine)
{
  tcn00_Error            nFuncReturn = OK_CN00;
  char                 * pCurrPos;
  char                 * pFlagPos;
  char                 * pLenPos;
  tsp00_Longint            nLength = 0;
  tsp00_Longint            nOutLen = 0;
  tsp05_RteFileError     rteFileErr;
  char                   szTmp[PARAMETER_MAXLEN_CN90];
  int                    nHeader = sFGetFiles[nIndex].nHeader;
  tsp00_Longint            nCurrPos   = 0;
  tsp00_Longint          * aLinePos   = NULL;
  int                    nLineIndex = 0;
  tsp00_Timestampc       sTimeStamp;
  tsp00_Timestampc       sReqTimeStamp;

  /* print OK and handle of file */
  sprintf (replyData, "%s%s%5d%s", ANSWER_OK_CN00,      LINE_SEPSTRING_CN00,
                                   hFile,               LINE_SEPSTRING_CN00);

  pFlagPos = replyData + strlen(replyData);
  sprintf ( pFlagPos , "%s%s" , CONT_FLAG_CONTINUE, LINE_SEPSTRING_CN00 );

  pLenPos = replyData + strlen(replyData);
  sprintf ( pLenPos, "%20ld%20ld%s" , (long) 0, (long) 0, LINE_SEPSTRING_CN00 );

  pCurrPos  = replyData + strlen(replyData);
  *replyLen = (int)strlen(replyData);

  // step 1 read the header
  if (nHeader > 0) {
    do {
      sqlfreadc(hFile, pCurrPos, replyLenMax - *replyLen - ((sFGetFiles[nIndex].nType == FGET_TYP_ASCII) ? 2 : 0), &nOutLen, &rteFileErr);
      *replyLen = *replyLen + (int)nOutLen;
      nLength   = nLength   + nOutLen;

      if  ( (rteFileErr.sp5fe_warning == sp5vfw_no_warning) &&
            (rteFileErr.sp5fe_result  == vf_ok            ) &&
            (sFGetFiles[nIndex].nType == FGET_TYP_ASCII   )    ) {
        *replyLen = *replyLen + 2;
        nLength   = nLength   + 2;
        replyData[*replyLen-2] = '\r';
        replyData[*replyLen-1] = '\n';
      } // end if

      pCurrPos = replyData + *replyLen;

      --nHeader;
    } while ( (*replyLen + ((sFGetFiles[nIndex].nType == FGET_TYP_ASCII) ? 2 : 0) <  replyLenMax)  &&
              (rteFileErr.sp5fe_warning       == sp5vfw_no_warning               )  &&
              (rteFileErr.sp5fe_result        == vf_ok                           )  &&
              (nHeader                         > 0                                )    );

    if (rteFileErr.sp5fe_result == vf_notok) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
    } // end if
  } // end if

  // step 2 navigate to the requested line

  // make a array for position save
  if ((nFuncReturn == OK_CN00) && (nLine != 0)) {
    aLinePos = new tsp00_Longint[nLine];
    if (aLinePos == NULL) {
      nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_MEM_CN00);
    } // end if
  } // end if
  if ((nFuncReturn == OK_CN00) && (pDate != NULL)) {
    //                     YYYYMMDDhhmmss
    SAPDB_strcpy(sReqTimeStamp, "00000000000000");
    strncpy(sReqTimeStamp, pDate, strlen(pDate));
  } // end if

  // save first position
  if ((nFuncReturn == OK_CN00) && (nLine != 0)) {
    // read first position
    sqlftellc (hFile, &nCurrPos, &rteFileErr);
    if (rteFileErr.sp5fe_result == vf_notok) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
    } else {
      for (nLineIndex = 0; nLineIndex < nLine; ++nLineIndex) {
        aLinePos[nLineIndex] = nCurrPos;
      } // end for
    } // end if
  } // end if

  if (nFuncReturn == OK_CN00) {
    nLineIndex = 0;
    do {
      //  read position
      sqlftellc (hFile, &nCurrPos, &rteFileErr);

      if  ( (rteFileErr.sp5fe_warning == sp5vfw_no_warning) &&
            (rteFileErr.sp5fe_result  == vf_ok            )    ) {
        // read line
        sqlfreadc(hFile, szTmp, PARAMETER_MAXLEN_CN90, &nOutLen, &rteFileErr);

        if  ( (rteFileErr.sp5fe_warning == sp5vfw_no_warning) &&
            (rteFileErr.sp5fe_result  == vf_ok            )    ) {
          // check line
          if (pDate != NULL) {
            // check the date
            if ( strlen(szTmp) >= (sFGetFiles[nIndex].nTimestampPos + strlen(sFGetFiles[nIndex].szTimestampFmt)) ) {
              cn42_ReadTimeStamp ( &szTmp[sFGetFiles[nIndex].nTimestampPos],
                                   sFGetFiles[nIndex].szTimestampFmt,
                                   sTimeStamp);
              if (strcmp(sTimeStamp, sReqTimeStamp) >= 0) {
              // if match then break do...while
                break;
              } // end if
            } // end if

          } else if (nLine != 0) {
            // save the line position (ignore empty lines if requested)
            if (!(sFGetFiles[nIndex].bRemoveEmptyLines && cn42_IsLineEmpty(szTmp))) {
              aLinePos[nLineIndex] = nCurrPos;
              nLineIndex = (nLineIndex + 1) % nLine;
            } // end if
          } // end if
        } // end if
      } // end if

    } while ( (rteFileErr.sp5fe_warning       == sp5vfw_no_warning               ) &&
              (rteFileErr.sp5fe_result        == vf_ok                           )    );

    if (rteFileErr.sp5fe_result == vf_notok) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
    } else {
      // navigate to correct position
      if (nLine > 0) {
        nCurrPos = aLinePos[nLineIndex];
        delete [] aLinePos;
        aLinePos = NULL;
      } // end if
      sqlfseekc (hFile, nCurrPos, sp5vf_seek_begin, &rteFileErr);
      if (rteFileErr.sp5fe_result == vf_notok) {
        nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_RTE_CN00, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
        sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
      } // end if
    } // end if
  } // end if

  // step 3 read the file content
  if ( (*replyLen + ((sFGetFiles[nIndex].nType == FGET_TYP_ASCII) ? 2 : 0) <  replyLenMax)  && (nFuncReturn == OK_CN00)) {

    do {
      sqlfreadc(hFile, pCurrPos, replyLenMax - *replyLen - ((sFGetFiles[nIndex].nType == FGET_TYP_ASCII) ? 2 : 0), &nOutLen, &rteFileErr);

      if (!(sFGetFiles[nIndex].bRemoveEmptyLines && cn42_IsLineEmpty(pCurrPos))) {

        *replyLen = *replyLen + (int)nOutLen;
        nLength   = nLength   + nOutLen;

        if  ( rteFileErr.sp5fe_warning == sp5vfw_no_warning &&
              rteFileErr.sp5fe_result  == vf_ok             &&
              (sFGetFiles[nIndex].nType == FGET_TYP_ASCII)) {
          *replyLen = *replyLen + 2;
          nLength   = nLength   + 2;
          replyData[*replyLen-2] = '\r';
          replyData[*replyLen-1] = '\n';
        } // end if

        pCurrPos = replyData + *replyLen;

      } // end if

    } while ( (*replyLen + ((sFGetFiles[nIndex].nType == FGET_TYP_ASCII) ? 2 : 0) <  replyLenMax) &&
              (rteFileErr.sp5fe_warning       == sp5vfw_no_warning               ) &&
              (rteFileErr.sp5fe_result        == vf_ok                           )    );

    if (rteFileErr.sp5fe_result == vf_notok) {
      nFuncReturn = ERR_RTE_CN00;
      cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
    } // end if

  } // end if

  if (nFuncReturn == OK_CN00) {
    // end handling
    replyData[*replyLen] = '\0';
    sprintf ( szTmp, "%20ld%20ld", (long) nSize, (long) nLength);
    strncpy(pLenPos, szTmp, strlen(szTmp));

    if ( rteFileErr.sp5fe_result == vf_eof ) {
      sprintf ( szTmp, "%s", CONT_FLAG_END );
      strncpy(pFlagPos, szTmp, strlen(szTmp));

      sqlfclosec ( hFile, sp5vf_close_normal, &rteFileErr );
    } else {
      // prepare next command
      sprintf(cn00DBMServerData::vcontrol()->szNextCommand, "file_getnext %s %d", sFGetFiles[nIndex].szType ,hFile);
      cn00DBMServerData::vcontrol()->nNextCommandSkip = 3;
    } // end if
  } // end if

  return nFuncReturn;

} // end cn42_FileReadFirst

/*
  -----------------------------------------------------------------------------
  function:     cn42_FileWrite
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_FileWrite
      ( const char    * szArguments,
        char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const bool      bNext)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  char                szName     [PARAMETER_MAXLEN_CN90] = "";
  char                szToken    [PARAMETER_MAXLEN_CN90] = "";
  char                szLocalArgs [PARAMETER_MAXLEN_CN90]  = "";
  bool                bNoClose   = false;
  long                nIndex;
  long                nSwitch;
  tsp00_Int4            hFile;
  long                nData   = 0;
  const char        * pData   = NULL;

  tsp05_RteFileError       rteFileErr;
  tsp05_RteDataKind_Enum   rteDatakind   = sp5vf_text;
  tsp05_RteFileMode_Enum   rteFilemode   = sp5vf_write;
  tsp05_RteBufferingKind_Enum rteBuffering  = sp5bk_buffered;

  if (strstr(szArguments, LINE_SEPSTRING_CN00) != NULL) {
    memset(szLocalArgs, CHAR_STRINGTERM_CN90, sizeof(szLocalArgs));
    strncpy(szLocalArgs, szArguments, strstr(szArguments, LINE_SEPSTRING_CN00) - &szArguments[0]);
  } else {
    SAPDB_strcpy(szLocalArgs, szArguments);
  } // end if

  /* read the parameters */
  nIndex = 1;
  while ( cn90GetToken(szLocalArgs, szToken, nIndex, PARAMETER_MAXLEN_CN90) ) {
    nSwitch = 0;
    if (szToken[nSwitch] == OPEN_SWITCH) {
      nSwitch++;
      while (szToken[nSwitch] != CHAR_STRINGTERM_CN90) {
        switch (szToken[nSwitch]) {
          case OPEN_MODE_BIN:
            rteDatakind  = sp5vf_binary;
            break;
          case OPEN_MODE_ASCII:
            rteDatakind  = sp5vf_text;
            break;
          default:
            nFuncReturn = ERR_PARAM_CN00;
            break;
        } /* end switch */
        nSwitch++;
      } /* end while */
    } else {
      if (strlen(szName) == 0) {
        SAPDB_strcpy(szName, szToken);
      } else {
        if (strcmp(szToken, FILE_OPT_NOCLOSE) == 0) {
          bNoClose = true;
        } else {
          nFuncReturn = ERR_PARAM_CN00;
        } // end if
      } /* end if */
    } /* end if */
    nIndex++;
  } /* end while */

  // look for data size and data
  pData = strstr(szArguments, LINE_SEPSTRING_CN00) + strlen(LINE_SEPSTRING_CN00);
  nData = (pData == NULL) ? 0 : atol(pData);
  pData = strstr(pData, LINE_SEPSTRING_CN00) + strlen(LINE_SEPSTRING_CN00);

  if (strlen(szName) == 0 || nFuncReturn == ERR_PARAM_CN00 || pData == NULL || nData == 0) {
    nFuncReturn = ERR_PARAM_CN00;
    cn90AnswerIError(replyData, replyLen, nFuncReturn);
  } /* end if */

  if (nFuncReturn == OK_CN00) {

    if (bNext) {
      // read handle
      hFile = atol(szName);
    } else {

      sqlfopenc (szName, rteDatakind, rteFilemode, rteBuffering, &hFile, &rteFileErr );

      if (rteFileErr.sp5fe_result != vf_ok) {
        nFuncReturn = ERR_RTE_CN00;
        cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
      } // end if

    } // end if

    // read contents
    if (nFuncReturn == OK_CN00) {
      nFuncReturn = cn42_FileWriteNext( replyData,
                                        replyLen,
                                        replyLenMax,
                                        hFile,
                                        (rteDatakind == sp5vf_text),
                                        nData,
                                        pData);
    } /* end if */
  } /* end if */

  return nFuncReturn;

} // end cn42_FileWrite

/*
  -----------------------------------------------------------------------------
  function:     cn42_FileWriteNext
  -----------------------------------------------------------------------------
 */
static tcn00_Error cn42_FileWriteNext
      ( char          * replyData,
        int           * replyLen,
        const int       replyLenMax,
        const tsp00_Int4  hFile,
        const bool      bAscii,
        const long      nData,
        const char    * pData )
{
  tcn00_Error  nFuncReturn = OK_CN00;
  char       * pNewline    = NULL;
  const char   * pCurrent    = pData;
  long         nOutput     = 0;
  long         nWrite      = 0;

  tsp05_RteFileError       rteFileErr;

  do {

    if (bAscii) {

      // skip newline
      pNewline = (char   *) memchr (pCurrent, '\n', nData - nOutput);
      if (pNewline == NULL) {
        nWrite = nData - nOutput;
      } else if (pNewline == pCurrent) {
        nWrite = 0;
        nOutput++;
      } else {
        nWrite = pNewline - pCurrent - (pNewline[-1] == '\r') ? 1 : 0;
        nOutput++;
      } // end if

      sqlfwritec (hFile, pCurrent, nWrite, &rteFileErr );
      nOutput = nOutput + nWrite;
      pCurrent = (pNewline != NULL) ? pNewline + 1 : pCurrent + nWrite;

    } else {
      nWrite = nData;
      sqlfwritec (hFile, pCurrent, nWrite, &rteFileErr );
      nOutput = nOutput + nWrite;
    } // end if

  } while ((nOutput < nData) && (rteFileErr.sp5fe_result == vf_ok));

  if (rteFileErr.sp5fe_result != vf_ok) {
    nFuncReturn = ERR_RTE_CN00;
    cn90AnswerRTEError (replyData, replyLen, nFuncReturn, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
  } else {
    /* print OK and handle of file */
    sprintf (replyData, "%s%s%5d%s", ANSWER_OK_CN00,      LINE_SEPSTRING_CN00,
                                     hFile,               LINE_SEPSTRING_CN00);
    *replyLen = (int)strlen(replyData);
  } // end if

  return nFuncReturn;

} // end cn42_FileWriteNext

/*
  -----------------------------------------------------------------------------
  function:     cn42_FileMatch
  -----------------------------------------------------------------------------
 */
static bool cn42_FileMatch
      ( tsp00_Pathc        szFileName,
        tsp00_Pathc        szRealName,
        tsp00_Pathc      & szToken)
{

  char   * pPostfix   = strstr(szFileName, FGET_WILDCARD);
  char   * pPrefix    = szFileName;
  char   * pReal      = szRealName;
  bool     bReturn    = false;

  if (pPostfix != NULL) {
    pPostfix++;

    if (strncmp(pPrefix,  pReal,  pPostfix - pPrefix -1 )                                 == 0  &&
        strncmp(pPostfix, pReal + strlen(pReal) - strlen(pPostfix) , strlen(pPostfix)) == 0     ) {
      bReturn = true;
      memset(szToken, CHAR_STRINGTERM_CN90, szToken.size());
      strncpy(szToken, pReal + (pPostfix - pPrefix - 1), strlen(pReal) - strlen(pPrefix) + 1);
    } // end if
  } // end if

  return bReturn;
} // end cn42_FileMatch

/*
  -----------------------------------------------------------------------------
  function:     cn42_DiagFileMatch
  -----------------------------------------------------------------------------
 */
static bool cn42_DiagFileMatch
      ( const char       * szDBName,
        const char       * szFile )
{
  bool        bReturn    = false;
  tsp00_Pathc szPattern;

  SAPDB_strcpy(szPattern, szDBName);
  strcat(szPattern, DIAG_HIST_PATTERN);

  if (strlen(szPattern) == strlen(szFile) ) {
    bReturn = true;
    for (int nIndex = 0; szFile[nIndex] != 0; ++nIndex) {
      switch (szPattern[nIndex]) {
      case '?':
        bReturn = bReturn && (isdigit(szFile[nIndex]));
        break;
      default:
        bReturn = bReturn && (szPattern[nIndex] == szFile[nIndex]);
        break;
      } // end switch
    } // end if
  } // end if

  return bReturn;
} // end cn42_DiagFileMatch

/* ------------------------------------------------------------------
 * IMPLEMENTATION PRIVATE FUNCTION cn42_ReadDir
 * ------------------------------------------------------------------
 */
static tcn00_Error cn42_ReadDir
      ( void               * hDirectory,
        char               * szFirst,
        char               * replyData,
        int                  replyLenMax,
        tsp05_RteFileError * pRteFileErr)
{
  tcn00_Error nFuncReturn = OK_CN00;
  char    *   pCurrent    = replyData;
  char    *   pContinue   = NULL;
  tsp00_C256    szFile;

  /* print OK and handle of dir */
  sprintf (pCurrent, "%s%s%p%s", ANSWER_OK_CN00, LINE_SEPSTRING_CN00,
                                 hDirectory,     LINE_SEPSTRING_CN00);

  /* print CONTINUE */
  pContinue = replyData + strlen(replyData);
  sprintf (pContinue, "%s%s", KEY_DIRCONTINUE_CN00, LINE_SEPSTRING_CN00);

  /* print first file if exist */
  if (szFirst != NULL) {
    pCurrent = replyData + strlen(replyData);
    sprintf(pCurrent, "%s%s", szFirst, LINE_SEPSTRING_CN00);
  } /* end if */

  /* print files in loop */
  while ((pRteFileErr->sp5fe_result == vf_ok) && (replyLenMax > (int)(strlen(replyData) + sizeof(szFile) + 2))) {

    sqlfreaddirc(hDirectory,  &szFile, pRteFileErr);

    if (pRteFileErr->sp5fe_result == vf_ok) {
      pCurrent = replyData + strlen(replyData);
      sprintf(pCurrent, "%s%s", (char   *) szFile, LINE_SEPSTRING_CN00);
    } /* end if */

  } /* end while */

  /* if EOF replace continue with end */
  if (pRteFileErr->sp5fe_result != vf_ok) {
    strncpy(pContinue, KEY_DIREND_CN00, strlen(KEY_DIREND_CN00));
  } /* end if */

  return nFuncReturn;

} /* end cn42_ReadDir */

/*
  -----------------------------------------------------------------------------
  private function cn42_ReadTimeStamp
  -----------------------------------------------------------------------------
*/
static void cn42_ReadTimeStamp
      ( const char *       szSource,
        const char *       szFormat,
        tsp00_Timestampc & sTimeStamp )
{
  int nIndex  = 0;

  int nYear   = 0;
  int nMonth  = 0;
  int nDay    = 0;

  int nHour   = 0;
  int nMinute = 0;
  int nSecond = 0;

  bool bValid = true;

  sTimeStamp.rawAssign("");

  if ( (szSource != NULL) && (szFormat != NULL) ) {
    while ((szSource[nIndex] != CHAR_STRINGTERM_CN90) &&
           (szFormat[nIndex] != CHAR_STRINGTERM_CN90) && bValid ) {
      switch(szFormat[nIndex]) {
      case CHAR_YEAR:
        if (isdigit(szSource[nIndex]) == 0) {
          bValid = false;
        } else {
          nYear   = (nYear   * 10 ) + (szSource[nIndex] - 0x30);
        } // end if
        break;
      case CHAR_MONTH:
        if (isdigit(szSource[nIndex]) == 0) {
          bValid = false;
        } else {
          nMonth  = (nMonth  * 10 ) + (szSource[nIndex] - 0x30);
        } // end if
        break;
      case CHAR_DAY:
        if (isdigit(szSource[nIndex]) == 0) {
          bValid = false;
        } else {
          nDay    = (nDay    * 10 ) + (szSource[nIndex] - 0x30);
        } // end if
        break;
      case CHAR_HOUR:
        if (isdigit(szSource[nIndex]) == 0) {
          bValid = false;
        } else {
          nHour   = (nHour   * 10 ) + (szSource[nIndex] - 0x30);
        } // end if
        break;
      case CHAR_MINUTE:
        if (isdigit(szSource[nIndex]) == 0) {
          bValid = false;
        } else {
          nMinute =  (nMinute * 10 ) + (szSource[nIndex] - 0x30);
        } // end if
        break;
      case CHAR_SECOND:
        if (isdigit(szSource[nIndex]) == 0) {
          bValid = false;
        } else {
          nSecond = (nSecond * 10 ) + (szSource[nIndex] - 0x30);
        } // end if
        break;
      default:
        if (szFormat[nIndex] != szSource[nIndex]) {
          bValid = false;
        } // end if
        break;
      } // end switch
      ++nIndex;
    } // end while
  } // end if

  nYear = (nYear < MILLENIUM_MIN) ? nYear + MILLENIUM_PRE : nYear;

  if (bValid) {
    sprintf(sTimeStamp, STAMP_FMT, nYear, nMonth, nDay, nHour, nMinute, nSecond);
  } else {
    sprintf(sTimeStamp, "00000000000000");
  } // end if

} // end cn42_ReadTimeStamp

/*
  -----------------------------------------------------------------------------
  private function cn42_IsLineEmpty
  -----------------------------------------------------------------------------
*/
static bool cn42_IsLineEmpty(const char * pLine)
{
  bool bEmpty = true;

  while (*pLine != 0) {
    if ((*pLine != ' ') && (*pLine != '\t')) {
      bEmpty = false;
      break;
    } // end if
    ++pLine;
  }

  return bEmpty;
} // end cn42_IsLineEmpty

/*
  -----------------------------------------------------------------------------
  private function cn40_FileOperation
  -----------------------------------------------------------------------------
*/
static tcn00_Error cn40_FileOperation
      ( char       *       replyData,
        int        *       replyLen,
        const char *       szFile,
        const char *       szDate,
        int                nLine,
        int                nIndex,
        bool               bDelete)
{
  tcn00_Error        nFuncReturn = OK_CN00;

  if ( (strchr(szFile, FGET_WILDCARDSTAR) != NULL) ||
       (strchr(szFile, FGET_WILDCARDQUE ) != NULL)    ) {

    tsp00_C256           szDir;
    tsp00_Pathc          szPattern;
    tsp00_C256           szFoundFile;
    tsp00_Pathc          szFullFile;
    int                  nIndex;
    tsp05_RteFileError   rteFileErr;
    void               * hDirectory  = NULL;
    pasbool              cPatOK;

    // extract path and filename
    for (nIndex = (int) strlen(szFile); nIndex >= 0; --nIndex) {
      if ((szFile[nIndex] == CHAR_SLASH    ) ||
          (szFile[nIndex] == CHAR_BACKSLASH)    ) {
        break;
      } // end if
    } // end for
    if (nIndex >= 0) {
      szDir.rawAssign(szFile);
      szDir[nIndex] = CHAR_STRINGTERM_CN90;
      szPattern.rawAssign(&(szFile[nIndex + 1]));
    } else {
      szDir.rawAssign(".");
      szPattern.rawAssign(szFile);
    } // end if

    // prepare reg expression
    s49build_pattern (szPattern.asCharp(),
                      true,
                      1,
                      szPattern.length(),
                      '\0',
                      false,
                      true,
                      sqlm_internal,
                      cPatOK);

    // open and iterate trough dir
    sqlfopendirc ( &szDir, &hDirectory,  &szFoundFile, &rteFileErr);

    if ( rteFileErr.sp5fe_result == vf_ok) {

      while  ( rteFileErr.sp5fe_result == vf_ok) {

        if (s49patmatch (szFoundFile.asCharp(), 0, (tsp00_Int4) strlen(szFoundFile), szPattern.asCharp(), 0, szPattern.length(), '\0')) {
          SAPDB_strcpy(szFullFile, szDir);
#ifdef _WIN32
          strcat(szFullFile, FGET_BACKSLASH);
#else
          strcat(szFullFile, FGET_SLASH);
#endif
          strcat(szFullFile, szFoundFile);

          if (bDelete) {
            nFuncReturn = cn40_FileDelete( replyData, replyLen, szFullFile, szDate);
          } else {
            nFuncReturn = cn40_FileShrink( replyData, replyLen, szFullFile, szDate, nLine, nIndex);
          } // end if

        } // end if

        sqlfreaddirc(hDirectory, &szFoundFile, &rteFileErr);
      } // end while

      sqlfclosedirc (hDirectory, &rteFileErr);

    } else {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } // end if

  } else {

    if (bDelete) {
      nFuncReturn = cn40_FileDelete( replyData, replyLen, szFile, szDate);
    } else {
      nFuncReturn = cn40_FileShrink( replyData, replyLen, szFile, szDate, nLine, nIndex);
    } // end if

  } // end if

  return nFuncReturn;
} // end cn40_FileOperation

/*
  -----------------------------------------------------------------------------
  private function cn40_FileDelete
  -----------------------------------------------------------------------------
*/
static tcn00_Error cn40_FileDelete( char       * replyData,
                                    int        * replyLen,
                                    const char * szFileName,
                                    const char * szDate)
{
  tcn00_Error        nFuncReturn = OK_CN00;
  bool               bDelete     = true;
  tsp05_RteFileError rteFileErr;

  if (strlen(szDate) > 0) {
    tsp00_Timestampc       sReqTimeStamp;
    tsp00_Timestampc       sTimeStamp;
    tsp05_RteFileInfo      rteFInfo;

    SAPDB_strcpy(sReqTimeStamp, "00000000000000");
    strncpy(sReqTimeStamp, szDate, strlen(szDate));

    sqlfinfoc (szFileName, &rteFInfo, &rteFileErr );

    if (rteFInfo.sp5fi_exists) {
      sprintf(sTimeStamp, "%.8s%.8s", rteFInfo.sp5fi_date_modified.asCharp(),
                                      rteFInfo.sp5fi_date_modified.asCharp());

      if (strcmp(sTimeStamp, sReqTimeStamp) > 0) {
        bDelete = false;
      } // end if
    } // end if
  } // end if

  if (bDelete) {
    sqlferasec (szFileName, &rteFileErr);
    if (rteFileErr.sp5fe_result != vf_ok) {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, rteFileErr.sp5fe_text, rteFileErr.sp5fe_text.length(), rteFileErr.sp5fe_result );
    } // end if
  } // end if

  return nFuncReturn;
} // end cn40_FileDelete

/*
  -----------------------------------------------------------------------------
  private function cn40_FileShrink
  -----------------------------------------------------------------------------
*/
static tcn00_Error cn40_FileShrink
      ( char       *       replyData,
        int        *       replyLen,
        const char *       szFileName,
        const char *       szDate,
        int                nLine,
        int                nIndex)
{
  tcn00_Error         nFuncReturn = OK_CN00;
  tsp00_Pathc         szTemp;
  tsp00_Pathc         szOrg;
  tsp01_RteError      rteError;
  tsp05_RteFileError  fileError;
  tsp00_Int4            hSource;
  tsp00_Int4            hTarget;
  int                 nHeader = sFGetFiles[nIndex].nHeader;
  char                szBuffer[PARAMETER_MAXLEN_CN90];
  tsp00_Longint         nOutLen    = 0;
  tsp00_Longint         nCurrPos   = 0;
  tsp00_Longint       * aLinePos   = NULL;
  int                 nLineIndex = 0;
  tsp00_Timestampc    sTimeStamp;
  tsp00_Timestampc    sReqTimeStamp;

  szTemp.rawAssign(szFileName);
  szOrg.rawAssign(szFileName);

  strcat(szTemp.asCharp(), ".1");

  // copy oldfile to temp
  if (sqlfilecopyc(szOrg.asCharp(), szTemp.asCharp(), &rteError)) {

    // open temp as source
    sqlfopenc (szTemp.asCharp(), sp5vf_text, sp5vf_read, sp5bk_buffered, &hSource, &fileError);

    if (fileError.sp5fe_result == vf_ok) {
      // open old file as target
      sqlfopenc (szOrg.asCharp(), sp5vf_text, sp5vf_write, sp5bk_buffered, &hTarget, &fileError);

      if (fileError.sp5fe_result == vf_ok) {
        // all files are open

        // step 1 read the header
        if (nHeader > 0) {
          do {
            sqlfreadc(hSource, szBuffer, PARAMETER_MAXLEN_CN90, &nOutLen, &fileError);
            if  ( (fileError.sp5fe_warning == sp5vfw_no_warning) &&
                  (fileError.sp5fe_result  == vf_ok            )    ) {
              sqlfwritec (hTarget, szBuffer, -1, &fileError);
            } // end if
            --nHeader;
          } while ( (fileError.sp5fe_warning == sp5vfw_no_warning ) &&
                    (fileError.sp5fe_result  == vf_ok             ) &&
                    (nHeader                  >  0                 )    );

          if (fileError.sp5fe_result == vf_notok) {
            nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
          } // end if
        } // end if

        // step 2 navigate to the requested line

        // make a array for position save
        if ((nFuncReturn == OK_CN00) && (nLine != 0)) {
          aLinePos = new tsp00_Longint[nLine];
          if (aLinePos == NULL) {
            nFuncReturn = cn90AnswerIError(replyData, replyLen, ERR_MEM_CN00);
          } // end if
        } // end if
        if ((nFuncReturn == OK_CN00) && (strlen(szDate) > 0)) {
          //                     YYYYMMDDhhmmss
          SAPDB_strcpy(sReqTimeStamp, "00000000000000");
          strncpy(sReqTimeStamp, szDate, strlen(szDate));
        } // end if

        // save first position
        if ((nFuncReturn == OK_CN00) && (nLine != 0)) {
          // read first position
          sqlftellc (hSource, &nCurrPos, &fileError);
          if (fileError.sp5fe_result == vf_notok) {
            nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
          } else {
            for (nLineIndex = 0; nLineIndex < nLine; ++nLineIndex) {
              aLinePos[nLineIndex] = nCurrPos;
            } // end for
          } // end if
        } // end if

        if (nFuncReturn == OK_CN00) {
          nLineIndex = 0;
          do {
            //  read position
            sqlftellc (hSource, &nCurrPos, &fileError);

            if  ( (fileError.sp5fe_warning == sp5vfw_no_warning) &&
                  (fileError.sp5fe_result  == vf_ok            )    ) {
              // read line
              sqlfreadc(hSource, szBuffer, PARAMETER_MAXLEN_CN90, &nOutLen, &fileError);

              if  ( (fileError.sp5fe_warning == sp5vfw_no_warning) &&
                    (fileError.sp5fe_result  == vf_ok            )    ) {
                // check line
                if (strlen(szDate) > 0) {
                  // check the date
                  if ( strlen(szBuffer) > (sFGetFiles[nIndex].nTimestampPos + strlen(sFGetFiles[nIndex].szTimestampFmt)) ) {
                    cn42_ReadTimeStamp ( &szBuffer[sFGetFiles[nIndex].nTimestampPos],
                                         sFGetFiles[nIndex].szTimestampFmt,
                                         sTimeStamp);
                    if (strcmp(sTimeStamp, sReqTimeStamp) >= 0) {
                      // if match then break do...while
                      break;
                    } // end if
                  } // end if

                } else if (nLine != 0) {
                  // save the line position
                  aLinePos[nLineIndex] = nCurrPos;
                  nLineIndex = (nLineIndex + 1) % nLine;
                } // end if
              } // end if
            } // end if

          } while ( (fileError.sp5fe_warning == sp5vfw_no_warning) &&
                    (fileError.sp5fe_result  == vf_ok            )    );

          if (fileError.sp5fe_result == vf_notok) {
            nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
          } else {
            // navigate to correct position
            if (nLine > 0) {
              nCurrPos = aLinePos[nLineIndex];
              delete [] aLinePos;
              aLinePos = NULL;
            } // end if
            sqlfseekc (hSource, nCurrPos, sp5vf_seek_begin, &fileError);
            if (fileError.sp5fe_result == vf_notok) {
              nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
            } // end if
          } // end if
        } // end if

        // step 3 read the file content
        if (nFuncReturn == OK_CN00) {
          do {
            sqlfreadc(hSource, szBuffer, PARAMETER_MAXLEN_CN90, &nOutLen, &fileError);
              if  ( (fileError.sp5fe_warning == sp5vfw_no_warning) &&
                    (fileError.sp5fe_result  == vf_ok            )    ) {
                sqlfwritec (hTarget, szBuffer, -1, &fileError);
              } // end if
          } while ( (fileError.sp5fe_warning == sp5vfw_no_warning ) &&
                    (fileError.sp5fe_result  == vf_ok             )    );

          if (fileError.sp5fe_result == vf_notok) {
            nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
          } // end if
        } // end if

        if (nFuncReturn == OK_CN00) {
          sqlfclosec (hTarget, sp5vf_close_normal, &fileError);
          if (fileError.sp5fe_result == vf_notok) {
            nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
          } // end if
        } else {
          sqlfclosec (hTarget, sp5vf_close_normal, &fileError);
        } // end if

      } else {
        nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
      } // end if

      sqlfclosec (hSource, sp5vf_close_normal, &fileError);

    } else {
      nFuncReturn = cn90AnswerRTEError (replyData, replyLen, ERR_FILE_CN00, fileError.sp5fe_text, fileError.sp5fe_text.length(), fileError.sp5fe_result );
    } // end if

    // restore old file from temp
    if (nFuncReturn != OK_CN00) {
      sqlfilecopyc(szTemp.asCharp(), szOrg.asCharp(), &rteError);
    } // end if
    // delete temp
    sqlferasec(szTemp, &fileError);

  } else {
    nFuncReturn = cn90AnswerNewRTEError (replyData, replyLen, ERR_FILE_CN00, &rteError );
  } // end if

  return nFuncReturn;
} // end cn40_FileShrink

/*
  -----------------------------------------------------------------------------
  private function cn40_FileGetListDir
  -----------------------------------------------------------------------------
*/
static tcn00_Error cn40_FileGetListDir 
      ( char               * replyData,
        long                 nIndex,
        tsp00_Path         & szFileDir,
        tsp00_Pathc        & szFileName,
        tsp00_Path         & szBaseDir,
        char              *& pCurrent,
        int                  replyLenMax)
{
  FUNCTION_DBG_MCN00_1(__FILE__"::cn40_FileGetListDir");

  tcn00_Error         nFuncReturn  = OK_CN00;
  void              * hDirectory  = NULL;
  tsp00_Path          szRealName;
  tsp00_Pathc         szFullReal;
  tsp05_RteFileInfo   rteFileInfo;
  tsp05_RteFileError  rteFileErr;
  tsp00_Pathc         szToken;
  char              * pFirst = pCurrent;
  int                 nLength;
  int                 replyLen;

  sqlfopendirc (&szFileDir, &hDirectory, &szRealName, &rteFileErr);

  if (rteFileErr.sp5fe_result == vf_ok) {
    while ((rteFileErr.sp5fe_result == vf_ok) && (nFuncReturn == OK_CN00)) {

      if ((strcmp(szRealName, ".") != 0) && (strcmp(szRealName, "..") != 0)) {

        SAPDB_strcpy(szFullReal, szFileDir);
        strcat(szFullReal, szRealName);
        if (cn42_FileMatch(szFileName, szFullReal, szToken)) {
          sqlfinfoc (szFullReal, &rteFileInfo, &rteFileErr );
        
          if (sFGetFiles[nIndex].nType == FGET_TYP_DIRECTORY) {
            size_t nBaseLength;
            nBaseLength = strlen(szBaseDir);
            nBaseLength += (sFGetFiles[nIndex].szName != NULL) ? strlen(sFGetFiles[nIndex].szName) : 0;
            nBaseLength += (sFGetFiles[nIndex].szExt  != NULL) ? strlen(sFGetFiles[nIndex].szExt) : 0;
            SAPDB_strcpy(szToken, &szFullReal[nBaseLength]);

          } // end if

          if (rteFileInfo.sp5fi_exists) {
            // check buffer size
            nLength = (int) (strlen(sFGetFiles[nIndex].szType) +
                             strlen(FGET_TOKENDEL) +
                             strlen(szToken) +
                             (6 * strlen(VALUE_SEPSTRING_CN00)) +
                             strlen(cn40_FileType(rteFileInfo, sFGetFiles[nIndex].nType)) +
                             20 + // rteFileInfo.sp5fi_size
                             sizeof (rteFileInfo.sp5fi_date_modified) +
                             sizeof (rteFileInfo.sp5fi_time_modified) +
                             strlen(sFGetFiles[nIndex].szComment) +
                             strlen(szFullReal  + _tcslen(szFileDir)) +
                             strlen(LINE_SEPSTRING_CN00) );
            if ((replyLenMax - (pCurrent - pFirst)) < nLength) {
              teo200_EventList aEvent(FUNCTION_NAME_MCN00_1, ERR_TOOMANYFILES_CN00_1);
              nFuncReturn = cn90AnswerEvent(replyData, &replyLen, aEvent);
              break;
            } else {
              _stprintf (pCurrent, "%s%s%s%s%s%s%ld%s%.*s%s%.*s%s%s%s%s%s",
                                   (char   *) sFGetFiles[nIndex].szType,
                                   (char   *) FGET_TOKENDEL,
                                   (char   *) szToken,
                                   VALUE_SEPSTRING_CN00,
                                   (char   *) cn40_FileType(rteFileInfo, sFGetFiles[nIndex].nType),
                                   VALUE_SEPSTRING_CN00,
                                   (long) rteFileInfo.sp5fi_size,
                                   VALUE_SEPSTRING_CN00,
                                   sizeof (rteFileInfo.sp5fi_date_modified), (char   *) rteFileInfo.sp5fi_date_modified,
                                   VALUE_SEPSTRING_CN00,
                                   sizeof (rteFileInfo.sp5fi_time_modified), (char   *) rteFileInfo.sp5fi_time_modified,
                                   VALUE_SEPSTRING_CN00,
                                   (char   *) sFGetFiles[nIndex].szComment,
                                   VALUE_SEPSTRING_CN00,
                                   (char   *) szFullReal  + strlen(szFileDir),
                                   LINE_SEPSTRING_CN00);
              pCurrent = pCurrent + strlen(pCurrent);
            } // end if
          } // end if
        } // end if

      } // end if

      sqlfreaddirc(hDirectory, &szRealName, &rteFileErr);
    } /* end while */

    sqlfclosedirc (hDirectory, &rteFileErr);
  } // end if

  return nFuncReturn;
} // end cn40_FileGetListDir

/*
  -----------------------------------------------------------------------------
  private function cn40_FileType
  -----------------------------------------------------------------------------
*/
static const char * cn40_FileType
      ( const tsp05_RteFileInfo  & rteFileInfo,
        long                       nType )
{
  const char * pReturn = FGET_TYPT_UNKNOWN;

  if (rteFileInfo.sp5fi_media_kind == vf_t_directory) {
    pReturn = FGET_TYPT_DIRECTORY;
  } else {
    switch (nType) {
      case FGET_TYP_ASCII:
        pReturn = FGET_TYPT_ASCII;
        break;
      case FGET_TYP_BINARY:
        pReturn = FGET_TYPT_BINARY;
        break;
      case FGET_TYP_DIRECTORY:
        pReturn = FGET_TYPT_UNKNOWN;
        break;
      default:
        pReturn = FGET_TYPT_UNKNOWN;
        break;

    } // end switch
  } // end if

  return pReturn;
} // end cn40_FileType
