Hi Everybody,
I am encountering an interesting behaviour with Ant's <ftp> task that I
cannot explain and wonder if anybody else has come across this.
I am transferring a bug of *.h and *.cpp files from Windows to unix in
text-file format (this correctly takes care of converting dos-format
line-endings into unix format; <ftp binary="no">).
Also if a file is already in unix format, it leaves the file untouched
(as expected).
However, I have this one file (please find attached file: xutil.cpp) on
which the <ftp> hangs !?!
The file is in unix-format. If I manually convert file to dos-format,
then <ftp> does not hang and properly transfers file to linux machine
while also converting it to unix-format. However, I dont understand why
it hangs when the file is in unix-format already ?
Any ideas ?
-sharad
--
=================================================
Sharad Jain
Gamma Technologies, Inc.
601 Oakmont Lane, Suite 220
Westmont, IL 60559
Tel: (630)-325-5848
Fax: (630)-325-5849
Email: [EMAIL PROTECTED]
Web: http://www.gtisoft.com
=================================================
// xutil.cpp: implementation of the xutil class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gttools.h"
#include "xutil.h"
#ifdef _UNIX
#include <pwd.h>
#if defined(linux)
#include <sys/sysinfo.h>
#elif defined(hp700mt)
#include <sys/mp.h>
#endif
#else
#include "Lmcons.h"
#endif
#ifdef _DEBUG
#undef XASSERT_FILE
static char XASSERT_FILE[] = __FILE__;
#endif
const char* DB_FILE_NAME = "db.cfg";
const char* DB_PATH_KEY = "dbpath";
const char* DB_DIR = "db";
const char* DB_DEFAULT = "default~";
const char* DB_BIN_VERSION = "v41";
const char* USER_PREF = "dbparam.xml";
// GTIHOME: the home directory string
// Description:
// The string that is the environment variable for the home directory.
// Remarks:
// The GTIHOME string is the string that is the environment varaible used to
// determine what the home directory should be.
GTTOOLS_API const char* GTIHOME = "GTIHOME";
// GTIVERSION: the version directory string
// Description:
// The string that is the current version.
// Remarks:
// The GTIVERSION string is the string that is the current latest version.
GTTOOLS_API int GTIVERSION = 0x06020000;
#ifdef _UNIX
GTTOOLS_API const char* GTILINE = "\n";
#else
// GTILINE: the line ending string
// Description:
// The string that is the end of a line.
GTTOOLS_API const char* GTILINE = "\r\n";
#endif
// XGetEnvironmentVariable: retrieves a specified environment variable
// Description:
// Retrieves a requested environment variable
// Return Value:
// Returns true if the variable exists, otherwise false
// Parameters:
// lpszVar - the desired environment variable's value to retrieve
// strVal - the XString object that will hold the value of the environment
// variable upon successful completion
// Remarks:
// strVal will only hold a valid value if this function returns true,
// strVal's value is undefined if this function returns false
bool XGetEnvironmentVariable(const char* lpszVar, XString& strVal)
{
// sanity check first
if (lpszVar == NULL)
return false;
// now grab the environment variable
const char* lpsz = getenv(lpszVar);
// if we have NULL then the enviornment variable wasn't found
if (lpsz == NULL)
return false;
// set the string equal to the value and return
strVal = lpsz;
return true;
}
// XSetEnvironmentVariable: sets the value of an environment variable
// Description:
// Sets the value of an environment variable
// Return Value:
// Returns true if the variable was successfully set, otherwise false
// Parameters:
// lpszVar - the environment variable to set
// lpszVal - the new value of the environment varaible
// Remarks:
// lpszVal can be NULL, this will effectively remove the environment
// variable
bool XSetEnvironmentVariable(const char* lpszVar, const char* lpszVal)
{
// static storage here
static XMapStringKey<XString> storage;
// sanity check first
if (lpszVar == NULL)
return false;
if (lpszVal == NULL)
lpszVal = "";
// map is necessary since we are not permitted to deallocate memory for an
// environment variable until after it has been removed from the system.
// Therefore we will keep a map of values and strings here, to reduce
// memory leaks
XString& str = storage[lpszVar];
str.format("%s=%s", lpszVar, lpszVal);
#if defined(rs6000) || defined(linux) || defined(sol2)
bool bRet = putenv(str.getBuffer()) == 0;
str.releaseBuffer();
return bRet;
#else
return putenv(str) == 0;
#endif
}
// XMultDiv: mutlipy and divide an integer
// Description:
// Multiplies two integers storing them into a long and divides by an int.
// Return Value:
// The integer value if successful, or -1 if nDenominator was 0 or an
// overflow occured.
// Parameters:
// nNumber - a number to multiply and divide
// nNumerator - the number to multiply by
// nDenominator - the number to divide by, should not be 0
// Remarks:
// Useful when an integer value might temporarily overflow during a
// multiplication and division operation.
int XMultDiv(int nNumber, int nNumerator, int nDenominator)
{
if (nDenominator == 0)
return -1;
long lValue = (long)(nNumber * nNumerator);
lValue = XRound((double)(lValue / nDenominator));
int nRet = (int)lValue;
return (nRet == lValue) ? nRet : -1;
}
// XGetHostname: retrieves the name of the computer
// Description:
// Determines the name of the computer.
// Return Value:
// true if successful, otherwise false
// Parameters:
// str - holds the name of the computer, unless an error occurred then will
// hold "host error" string
// Remarks:
// Attempts to determine what the name of the computer is.
bool XGetHostname(XString& str)
{
int nError = -1;
#ifdef WIN32
// GetComputerName appears to do the same thing on windows as gethostname
// on UNIX
DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
nError = ::GetComputerName(str.getBuffer(size), &size) == 0;
str.releaseBuffer();
#else
nError = gethostname(str.getBuffer(256), 256);
str.releaseBuffer();
#endif
if (nError != 0)
{
str = "host error";
}
return nError == 0;
}
// XGetLoginName: retrieves the current user's login name
// Description:
// Determines the current user's login name and returns it.
// Return Value:
// true if the function was successful, otherwise false.
// Parameters:
// str - the user's login name if the function was successful
// Remarks:
// Attempts to figure out the user name for the currently logged in user.
// str is undefined if the function fails.
bool XGetLoginName(XString& str)
{
#ifndef _UNIX
DWORD dwSize = UNLEN + 1;
BOOL bResult = ::GetUserName(str.getBuffer(dwSize), &dwSize);
if (bResult)
str.releaseBuffer(dwSize);
else
str.releaseBuffer(0);
return (bResult == TRUE);
#else
// try getlogin
const char* lpsz = getlogin();
if (lpsz)
{
str = lpsz;
return true;
}
// now try getpwuid
struct passwd* entry = getpwuid(getuid());
if (entry && entry->pw_name)
{
str = entry->pw_name;
return true;
}
// don't know what else to do, failure is an option
return false;
#endif
}
// XIsWinNT: tests whether this windows NT
// Description:
// Returns whether the application is running on a Windows NT derived
// operating system.
// Return Value:
// true if Windows NT, otherwise false.
// Parameters:
// n/a
// Remarks:
// Checks an environment variable to see if the program is running on a
// Windows NT derived system (i.e. NT 4.0, Windows 2000, Windows XP...)
// This should only be used when absolutely necessary, since we generally
// want to keep the OS specific stuff to a minimum.
bool XIsWinNT()
{
#ifndef _UNIX
XString str;
if (!XGetEnvironmentVariable("OS", str))
return false;
return (str == "Windows_NT");
#else
return false;
#endif
}
// XGetUserPath: retrieves the user directory location
// Description:
// Retrieves the user directory.
// Return Value:
// n/a
// Parameters:
// path - A reference to a XPath to hold the path.
// Remarks:
// Returns a folder where user data can be placed. Location is operating
// system dependent and is not currently directly user definable.
void XGetUserPath(XPath& path)
{
const char* lpsz = NULL;
#ifndef _UNIX
lpsz = getenv("USERPROFILE");
if (lpsz == NULL || strlen(lpsz) == 0)
{
lpsz = getenv("windir");
}
#endif
if (!lpsz)
{
lpsz = getenv("HOME");
}
path.set(lpsz);
}
//
// Description:
// Substitues the environment variable strings with its value
// i.e if argument is $GTIHOME$\bin it will be substituted with the
c:\gti\bin, if
// GTIHOME equals c:\gti
// Return Value:
// n/a
// Parameters:
// path - A reference to a XString to hold the path, where env. variable need
to be substituted.
// Remarks:
void XSubstituteEnvVar(XString& path)
{
const short NUM_TERMS = 4;
const char TERMNS[] = { '\\', '/', ':', '$' };
int n1, n2 = 0;
int shift = 0;
char term = '\0';
int len = path.getLength();
int actualPos = 0;
while ( actualPos <len)
{
if( (n1 = path.find( "${", actualPos ) ) >= 0 )
{
shift = 2;
term = '}';
}
else if( (n1 = path.find( "$", actualPos ) ) >= 0 )
{
shift = 1;
term = '\0';
}
else if( (n1 = path.find( "%", actualPos ) ) >= 0 )
{
shift = 1;
term = '%';
}
else
{
break;
}
if( term != '\0' )
{
n2 = path.find(term, n1 + shift);
}
else
{
int pos = -1;
bool found = false;
for( int i = 0; i < NUM_TERMS && pos != 0; i++ )
{
pos = path.find(TERMNS[i], n1 + shift);
if( pos >= 0 )
{
if( !found )
{
n2 = pos;
found = true;
}
else
n2 = min( n2, pos );
}
}
if( !found )
{
n2 = path.getLength();
}
else if( path.getAt( n2 ) == '$' )
{
term = '$';
}
else
{
n2--;
}
/*
// When the star is $, we can terminate with $ or with
nothing.
if ( ( n2 = path.find('\\', n1 + shift) ) < 0 )
{
if ( ( n2 = path.find('/', n1 + shift) ) < 0 )
{
if( ( n2 = path.find('$', n1 + shift) )
< 0 )
{
n2 = path.getLength();
}
else
{
term = '$';
}
}
}
else
{
n2--;
}
*/
}
if (n2 < 0)
{
break;
}
n2++;
XString token;
path.mid(n1, n2 - n1, token);
XString env;
if( term != '\0' )
{
token.mid( shift, token.getLength() - 1 - shift, env );
}
else
{
token.mid( shift, token.getLength() - 1, env );
}
XString val;
if (env.getLength() > 0)
{
if (XGetEnvironmentVariable((const char *) env, val))
{
path.replace((const char*) token, (const char*)
val);
}
}
actualPos = actualPos + val.getLength() + 1;
}
return;
}
// XGetDBMode: gets current dbmode and initializes dbpath with the path to the
DB_FILE_NAME file
// Description:
// This function returns DB_GLOBAL_MODE or DB_LOCAL_MODE wich is determined by
location of the
// DB_FILE_NAME file. If it's in the one of the GTIHOME/db/<hostname> or
GTIHOME/db/<default~>
// directory than its global, if it's in the gamma user directory than it's
local. DB_MODE_ERROR
// is returned if DB_FILE_NAME file can not be found
//
int XGetDBMode(XString& databasePath)
{
XString hostname;
XGetHostname(hostname);
//getting the host name
XString gtihome;
XGetEnvironmentVariable(GTIHOME, gtihome);
//getting base db directory
XPath path (gtihome);
path.addFile(DB_DIR);
// fprintf(stderr, "path generated %s\n", (const char*) path);
//checking host first
XPath dbpath(path);
dbpath.addFile(hostname);
dbpath.addFile(DB_FILE_NAME);
// fprintf(stderr, "first check host path %s\n", (const char*) dbpath);
if (dbpath.exists())
{
// fprintf(stderr, "path %s exist\n", (const char*) dbpath);
}
else
{
// fprintf(stderr, "path %s does not exist!!!!\n", (const char*)
dbpath);
dbpath = path;
dbpath.addFile(DB_DEFAULT);
dbpath.addFile(DB_FILE_NAME);
if (!dbpath.exists())
{
// fprintf(stderr, "path %s does not exist!!!! Searcing in
the user local directory\n", (const char*) dbpath);
XString userPath;
XGetGammaUserPath(userPath);
dbpath = (const char*)userPath;
dbpath.addFile(DB_FILE_NAME);
if (!dbpath.exists())
{
databasePath = "";
return DB_LOCAL_MODE;
}
else
{
databasePath = dbpath;
return DB_LOCAL_MODE;
}
}
}
databasePath = dbpath;
return DB_GLOBAL_MODE;
}
// XGetDBPath: retrives database path
// Description:
// Database path retrieval rules.
//
// File name: db.cfg
// Database path string: dbpath = \somepath\somepath\$env_var$,
// where env_var is an environment variable
//
// 0. GTIHOME/db/hostname or GTIHOME/db/default where hostname superseeds the
default one
// 1. (for feature releases) Look up somewhere in GTI_HOME
// 2. Look in the user directory and if file or property in this file not found
there go to step 3.
// 3. Return temp directory
//
// User can edit this file from ui. If user enters empty path file should be
deleted.
// Database should be stopped and applications may need to exit.
//
// Return Value:
// changes value passed as an argument, by substituting env. variables with
its values
// Parameters:
// value - A reference to a XString to hold the path
// convert - whether or not to convert environment variables to its actual
values
void XGetDBPrefPath(XString& value, bool convert)
{
//Changes for VW.
if (isSingleDB())
{
XString str;
XGetDatabaseDbParam( str );
XPath path(str);
path.getParent(value);
return;
}
XString key;
key = DB_PATH_KEY;
if (key.getLength() == 0)
{
//invalid key
return;
}
XString dbpath;
if (XGetDBMode(dbpath) < 0)
{
value = "";
return;
}
// fprintf(stderr, "database folder where db.cnf will be searched is:
%s\n", (const char *) dbpath);
XStreamFile f;
XString line(256);
// Fran: I know that SHARE_DENYNONE is not the best way to go because
another process could make changes, but
// at the same token if this function fails, we will return the wrong
database directory.
if ( strlen(dbpath) > 0 && f.open((const char *) dbpath,
XFile::MODE_READ | XFile::MODE_TEXT| XFile::SHARE_DENYNONE))
{
while (f.readString(line))
{
int len = line.getLength();
if ( !line.startsWith("#") && len >= 1)
{
int n = line.find('=', 0);
if (n > 0)
{
XString left;
line.left(n, left);
left.trimLeft();
left.trimRight();
if (key == left)
{
XString right;
line.right(len - n - 1, right);
right.trimLeft();
right.trimRight();
if (convert)
{
XSubstituteEnvVar(right);
}
value.empty();
value = right;
}
}
}
}
if (value.getLength() == 0) // if value not found for databas
{
f.remove();
XGetDbPath (value);
}
}
else
{
if (key == "dbpath")
{
XGetDbPath (value);
}
}
}
// XWriteDBPrefPath: writes database directory path to a file
// Description:
// Writes database directory path to the file. If file doesn't exist it
// will be created, if value passed is empty, it will delete file
// Return Value:
// n/a
// Parameters:
// value - database path that needs to be written
// Remarks:
void XWriteDBPrefPath(XString& value)
{
XString key = DB_PATH_KEY;
XString cfgpath;
XGetDBMode (cfgpath);
XStreamFile f;
if (f.open((const char*) cfgpath, XFile::MODE_WRITE |
XFile::MODE_TRUNCATE | XFile::MODE_CREATE | XFile::MODE_TEXT
|XFile::SHARE_DENYWRITE))
{
if (value.getLength() == 0)
{
f.remove();
return;
}
XString msg = "#Please don't edit this file by hand use
'gtcollect DBCONF' instead.";
f.writeLine(msg);
XString line = key + "=" + (const char*)value;
line.trimRight();
f.writeLine(line);
f.flush();
f.close();
}
}
// XGetGammaUserPath: retrieves the location where application data should be
placed
// Description:
// Retrieves the user directory where application data can be safely placed.
// Return Value:
// n/a
// Parameters:
// str - A reference to a XString to hold the path.
// Remarks:
// Returns a folder where user data can be placed, the str will end with
// the path separator character '\' or '/' depending on the operating system.
// Location is operating system dependent and is not currently directly user
// definable.
void XGetGammaUserPath(XString& str)
{
XPath path;
XGetUserPath(path);
path.addFile(".gamma");
// the path does not exist, create it...
if (!path.exists())
{
path.makeDirs();
}
str = (const char*)path;
str += XPath::m_chSeparator;
}
void XGetDbPath( XString& str )
{
XGetGammaUserPath( str );
XPath path( str );
path.addFile( "data" );
#ifdef _UNIX
char compName[125];
gethostname( compName, 125 );
path.addFile( compName );
#endif
path.addFile( DB_DATA_VERSION );
str = (const char*)path;
if (str[str.getLength() - 1] != XPath::m_chSeparator)
{
str += XPath::m_chSeparator;
}
}
void XGetJREBinPath( XString &str )
{
XGetGTIPath( str );
XPath path( str );
path.addFile( "jre" );
path.addFile( XGetPlatformName() );
path.addFile( "bin" );
str = (const char *)path;
if (str[str.getLength() - 1] != XPath::m_chSeparator)
{
str += XPath::m_chSeparator;
}
}
void XGetExtPath( XString &str )
{
XGetGTIPath( str );
XPath path( str );
path.addFile( "ext" );
str = (const char *)path;
if (str[str.getLength() - 1] != XPath::m_chSeparator)
{
str += XPath::m_chSeparator;
}
}
void XGetResourcePath(XString &str)
{
XGetVersionPath(str);
XPath path(str);
// add the gtsuite name, case matters for UNIX
path.addFile("resrc");
str = (const char *)path;
}
void XGetVersionPath(XString &str)
{
// this should have been verified earlier
XVERIFY(XGetEnvironmentVariable(GTIHOME, str));
XPath path(str);
// here are some hard-coded paths, hopefully these will never have to be
// changed
XString strVersion;
XGTiseString::getVersionString(GTIVERSION,
XGTiseString::VERSION_IGNORE_INTERNAL, strVersion);
// now add the version directory
str.format("v%s", (const char*)strVersion);
path.addFile(str);
str = (const char *)path;
}
void XGetGTIPath(XString& str )
{
XGetVersionPath(str);
XPath path(str);
// add the gtsuite name, case matters for UNIX
path.addFile("GTsuite");
str = (const char *)path;
}
const char* XGetPlatformName()
{
#if defined(WIN32)
return "win32";
#elif defined(hp11)
return "hp11";
#elif defined(ibm43)
return "ibm43";
#elif defined(ibm51)
return "ibm51";
#elif defined(ibm51_64)
return "ibm51_64";
#elif defined(rhel30_ia64)
return "rhel30_ia64";
#elif defined(linuxrh72)
return "linuxrh72";
#elif defined(linuxss82)
return "linuxss82";
#elif defined(sgi32)
return "sgi32";
#elif defined(sgi64)
return "sgi64";
#elif defined(sun7)
return "sun7";
#elif defined(sun8)
return "sun8";
#elif defined(sun8_64)
return "sun8_64";
#else
// if you get a compiler error here this is because you need to add
// the platform to the list
compiler = error here
#endif
}
//
// returns the shared lib extension.
//
const char* XGetSharedLibExt()
{
#if defined(WIN32)
return "dll";
#elif defined(hp11)
return "sl";
#elif defined(ibm43)
return "so";
#elif defined(ibm51)
return "so";
#elif defined(ibm51_64)
return "so";
#elif defined(rhel30_ia64)
return "so";
#elif defined(linuxrh72)
return "so";
#elif defined(linuxss82)
return "so";
#elif defined(sgi32)
return "so";
#elif defined(sgi64)
return "so";
#elif defined(sun7)
return "so";
#elif defined (sun8)
return "so";
#elif defined(sun8_64)
return "so";
#else
// if you get a compiler error here this is because you need to add
// the platform to the list
compiler = error here
#endif
}
//XGetGTIBinPath: Gets the path to the BIN directory
// Description:
// Retrieves path to the bin directory
// which is on windows %GTIHOME%/<version>/GTSuite/bin
// Parameters: str a string that will contain output of this function (path)
// Return Value:
// Remarks:
void XGetGTIBinPath(XString& str)
{
XGetGTIPath(str);
XPath path(str);
path.addFile("bin");
str = (const char*)path;
if (str[str.getLength() - 1] != XPath::m_chSeparator)
str += XPath::m_chSeparator;
}
void XGetOSName(XString& str)
{
#ifdef _UNIX
str = XGetPlatformName();
#else
if( XIsWinNT() )
str = "NT-based";
else
str = "Win98-based";
#endif
}
// XGetNumProc: grabs the number of CPUs
// Description:
// Determines the number of CPU's on the current machine.
// Return Value:
// true if supported and successful, otherwise false.
// Parameters:
// nNum - the number of CPU's
// Remarks:
// This call is highly platform dependent and the return value should
// be checked on every platform to make sure that the number of CPU's could
// be determined.
bool XGetNumProc(int& nNum)
{
#if defined(WIN32)
SYSTEM_INFO sysinfo;
::GetSystemInfo(&sysinfo);
nNum = sysinfo.dwNumberOfProcessors;
return true;
#elif defined(linux)
nNum = get_nprocs();
return true;
#elif defined(hp700mt)
nNum = mpctl(MPC_GETNUMSPUS, NULL, NULL);
return true;
#else
return false;
#endif
}
#if defined(_UNIX)
// same as for windows
void XGetLastSystemError(XString& str)
{
str.format(XT("System Error: (%d) - %s"), errno, strerror(errno));
}
#else
// XGetLastSystemError: retrieves the last system error
// Description:
// Retrieves an error message based upon the last system error code received.
// Return Value:
// n/a
// Parameters:
// str - a string to the error message
// Remarks:
// The error message returned is based on the whatever error code happens to
// be currently stored in the global error variable.
void XGetLastSystemError(XString& str)
{
DWORD dwErrorID = ::GetLastError();
void* pMsgBuf;
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dwErrorID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&pMsgBuf,
0,
NULL
);
str.format(XT("Windows Error: (%d) - %s"), dwErrorID, (LPXSTR)pMsgBuf);
// Free the buffer.
LocalFree(pMsgBuf);
}
#endif
// XGetArgArray: breaks up a string into an argument array
// Description:
// Treats lpsz as a command-line string and breaks it up in a manner suitable
// as an argument to one of the exec family of functions.
// Return Value:
// 0 if args is large enough to hold all of the arguments, otherwise the size
// necessary to hold of the arguments is returned.
// Parameters:
// lpsz - the command-line string
// args[] - an array of pointers to strings
// length - the size of args
// Remarks:
// lpsz is changed as a result of a call to XCreateArgArray regardless of
// whether args is large enough or not. But lpsz is not changed past the
// point where args is unable to hold the additional arguments. This could
// facilitate a second call to the function with the a larger array
// initialized using the first args array, although it is probably better to
// just call with length 0 once and then follow-up with another call after
// with a large enough array. A terminating character will be placed into
// lpsz in order to break the string into the arguments.
int XCreateArgArray(LPXSTR lpsz, XCHAR* args[], int length)
{
int i = 0;
for (XCHAR* lp = lpsz; lp != NULL; i++)
{
while (xisspace(*lp)) lp++;
if (*lp == XT('"'))
{
if (i < length)
{
args[i] = ++lp;
}
lp = xstrchr(lp, XT('"'));
}
else if (*lp != XT('\0'))
{
if (i < length)
{
args[i] = lp;
}
lp = xstrchr(lp, XT(' '));
}
else
{
break;
}
if (lp != NULL)
{
// only modify the string if the length of the array is long enough
if (i < length)
{
*lp = XT('\0');
}
lp++;
}
}
if (i < length)
{
// need to terminate the argument array
args[i] = NULL;
return 0;
}
// not enough pointers in the array
return i + 1;
}
void XGetDatabaseInstPath( XString& str )
{
XString gtihome;
XGetEnvironmentVariable(GTIHOME, gtihome);
//getting base db directory
XPath path (gtihome);
path.addFile(DB_DIR);
path.addFile(DB_BIN_VERSION);
str = (const char *)path;
}
void XGetDatabaseDbParam( XString& str )
{
if (isSingleDB())
{
XString currDir;
XPath::getCurDir( currDir );
XPath dbParam( currDir );
dbParam.addFile( "datadir" );
dbParam.addFile( "dbparam.xml" );
str = (const char *)dbParam;
return;
}
XString dbpath;
int mode = XGetDBMode(dbpath);
if(mode == DB_LOCAL_MODE )
{
XGetGammaUserPath( str );
}
else
{
XGetDBPrefPath( str, true );
}
XPath dbParamFile( str );
dbParamFile.addFile( USER_PREF );
str = (const char *)dbParamFile;
}
bool isSingleDB()
{
#ifdef _UNIX
XString currDir;
XPath::getCurDir( currDir );
XPath singleDbFile( currDir );
singleDbFile.addFile( "ds.db" );
return singleDbFile.exists() && singleDbFile.canRead();
#else
return false;
#endif
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]