#include "tsystem.h"
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <set>
#undef PLATFORM
#ifdef WIN32
#define PLATFORM WIN32
#include <process.h>
#include <io.h>
#include <stdlib.h>
#include <direct.h>
#include "winsock2.h"
#include "lmcons.h"
#include <sys/utime.h>
#endif
#ifdef LINUX
#define PLATFORM LINUX
#include <grp.h>
#include <utime.h>
#include <sys/param.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/dir.h>
#include <sys/sysinfo.h>
#include <sys/swap.h>
#include <sys/statfs.h>
#include <pwd.h>
#include <mntent.h>
#include <dlfcn.h>
extern "C" {
int gethostname(char *, size_t);
// int L_cuserid;
char *cuserid(char *);
char *tempnam(const char *, const char *);
}
#endif
#ifdef __sgi
#define PLATFORM SGI
#include <sys/param.h>
#include <unistd.h>
#include <grp.h>
#include <sys/dir.h> // dirent.h
#include <sys/utime.h>
#include <sys/swap.h>
#include <sys/statfs.h>
#include <pwd.h>
#include <mntent.h>
#include <dlfcn.h>
#endif
#ifndef PLATFORM
PLATFORM_NOT_SUPPORTED
#endif
using namespace std;
#ifdef WIN32
const int TSystem::MaxPathLen = _MAX_PATH;
const int TSystem::MaxFNameLen = _MAX_FNAME;
const int TSystem::MaxHostNameLen = 64;
const unsigned short TFileStatus::UserReadable = _S_IREAD;
const unsigned short TFileStatus::UserWritable = _S_IWRITE;
const unsigned short TFileStatus::UserExecutable = _S_IEXEC;
const unsigned short TFileStatus::OwnerReadWriteExec =
TFileStatus::UserReadable | TFileStatus::UserWritable |
TFileStatus::UserExecutable;
const unsigned short TFileStatus::OwnerReadable = TFileStatus::UserReadable;
const unsigned short TFileStatus::OwnerWritable = TFileStatus::UserWritable;
const unsigned short TFileStatus::OwnerExecutable = TFileStatus::UserExecutable;
const unsigned short TFileStatus::GroupReadWriteExec =
TFileStatus::OwnerReadWriteExec;
const unsigned short TFileStatus::GroupReadable = TFileStatus::UserReadable;
const unsigned short TFileStatus::GroupWritable = TFileStatus::UserWritable;
const unsigned short TFileStatus::GroupExecutable = TFileStatus::UserExecutable;
const unsigned short TFileStatus::OtherReadWriteExec =
TFileStatus::UserReadable | TFileStatus::UserWritable |
TFileStatus::UserExecutable;
;
const unsigned short TFileStatus::OtherReadable = TFileStatus::UserReadable;
const unsigned short TFileStatus::OtherWritable = TFileStatus::UserWritable;
const unsigned short TFileStatus::OtherExecutable = TFileStatus::UserReadable;
const unsigned short TFileStatus::IfDir = _S_IFDIR;
#define MKDIR _mkdir
#define RMDIR _rmdir
#define TEMPNAM _tempnam
#define ACCESS _access
#define STAT _stat
#define UTIME _utime
#define FTIME _ftime
#else // these are common for IRIX & LINUX
const int TSystem::MaxPathLen = MAXPATHLEN;
const int TSystem::MaxHostNameLen = MAXHOSTNAMELEN;
const unsigned short TFileStatus::OwnerReadWriteExec = S_IRWXU;
const unsigned short TFileStatus::OwnerReadable = S_IRUSR;
const unsigned short TFileStatus::OwnerWritable = S_IWUSR;
const unsigned short TFileStatus::OwnerExecutable = S_IXUSR;
const unsigned short TFileStatus::GroupReadWriteExec = S_IRWXG;
const unsigned short TFileStatus::GroupReadable = S_IRGRP;
const unsigned short TFileStatus::GroupWritable = S_IWGRP;
const unsigned short TFileStatus::GroupExecutable = S_IXGRP;
const unsigned short TFileStatus::OtherReadWriteExec = S_IRWXO;
const unsigned short TFileStatus::OtherReadable = S_IROTH;
const unsigned short TFileStatus::OtherWritable = S_IWOTH;
const unsigned short TFileStatus::OtherExecutable = S_IXOTH;
#define MKDIR mkdir
#define RMDIR rmdir
#define TEMPNAM tempnam
#define ACCESS access
#define STAT stat
#define UTIME utime
#define FTIME ftime
#ifdef __sgi
const int TSystem::MaxFNameLen = MAXNAMELEN;
const unsigned short TFileStatus::UserReadable = S_IREAD;
const unsigned short TFileStatus::UserWritable = S_IWRITE;
const unsigned short TFileStatus::UserExecutable = S_IEXEC;
const unsigned short TFileStatus::IfDir = S_IFDIR;
#else
const int TSystem::MaxFNameLen = 1024;
const unsigned short TFileStatus::UserReadable = __S_IREAD;
const unsigned short TFileStatus::UserWritable = __S_IWRITE;
const unsigned short TFileStatus::UserExecutable = __S_IEXEC;
const unsigned short TFileStatus::IfDir = __S_IFDIR;
#endif
#endif
//-----------------------------------------------------------------------------------
ostream &operator<<(ostream &out, const TSystemException &e) {
return out << "TSystem Exception : " << e.getMessage() << endl;
}
//-----------------------------------------------------------------------------------
// conversion functions
namespace {
//---------------------------------------------------------
void makeTm(const TTime &t, tm *p) {
::memset(p, 0, sizeof(tm));
p->tm_year = t.getYear() - 1900;
p->tm_mon = t.getMonth() - 1; //[0,11]
p->tm_mday = t.getDay();
p->tm_hour = t.getHour();
p->tm_min = t.getMinutes();
p->tm_sec = t.getSeconds();
p->tm_isdst = -1;
}
//---------------------------------------------------------
TTime makeTTime(const tm &p, int msec = 0) {
return TTime(p.tm_year + 1900, p.tm_mon + 1, p.tm_mday, p.tm_hour, p.tm_min,
p.tm_sec, msec);
}
//---------------------------------------------------------
time_t makeTimeT(const TTime &t) {
tm x;
makeTm(t, &x);
time_t tt = mktime(&x);
return tt;
}
} // namespace
//-----------------------------------------------------------------------------------
TDeltaTime::TDeltaTime(long sec, long msec) {
// assert((sec && msec>=0) ||(sec==0 ));
assert(!((sec < 0 && msec > 0) || (sec > 0 && msec < 0)));
/*
0 0 ok
0 1 ok
1 0 ok
1 1 ok
0 -1 ok
-1 0 ok
-1 -1 ok
-1 1 NO
1 -1 NO
*/
m_dsec = sec + msec / 1000;
m_dmsec = msec % 1000;
}
//------------------------------------------------------------
TDeltaTime TDeltaTime::operator+(const TDeltaTime &tdt) {
long sumSec = m_dsec + tdt.m_dsec;
long sumMsec = m_dmsec + tdt.m_dmsec;
if (sumSec > 0 && sumMsec < 0) return TDeltaTime(sumSec - 1, sumMsec + 1000);
if (sumSec < 0 && sumMsec > 0) return TDeltaTime(sumSec + 1, sumMsec - 1000);
return TDeltaTime(sumSec, sumMsec);
}
//------------------------------------------------------------
TDeltaTime TDeltaTime::operator-(const TDeltaTime &tdt) {
long diffSec = m_dsec - tdt.m_dsec;
long diffMsec = m_dmsec - tdt.m_dmsec;
if (diffSec < 0 && diffMsec > 0)
return TDeltaTime(diffSec + 1, diffMsec - 1000);
if (diffSec > 0 && diffMsec < 0)
return TDeltaTime(diffSec - 1, diffMsec + 1000);
return TDeltaTime(diffSec, diffMsec);
}
//------------------------------------------------------------
ostream &operator<<(ostream &out, const TDeltaTime &dt) {
return out << dt.getSeconds() << "." << dt.getMilliSeconds();
}
//-----------------------------------------------------------------------------------
// correggere gli assert => invalid (esiste il metodo bool isValid()const;
// operazioni con
// un TTIme invalid danno un risultato invalid
//
//
TTime::TTime(int yyyy, int mm, int dd, int hh, int min, int sec, int msec) {
if (yyyy < 10)
yyyy += 2000;
else if (yyyy < 99)
yyyy += 1900;
assert(1970 <= yyyy && yyyy <= 2038);
m_y = yyyy;
assert(1 <= mm && mm <= 12);
m_m = mm;
int table[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int ddlimit = mm == 2 ? (28 + (isLeap() ? 1 : 0)) : table[mm - 1];
assert(1 <= dd && dd <= ddlimit);
m_d = dd;
assert(0 <= hh && hh <= 23);
m_h = hh;
assert(0 <= min && min <= 59);
m_min = min;
assert(0 <= sec && sec <= 59);
m_sec = sec;
assert(0 <= msec && msec <= 999);
m_msec = msec;
}
//-----------------------------------------------------------------------------------
TTime::TTime(const TTime &t)
: m_y(t.m_y)
, m_m(t.m_m)
, m_d(t.m_d)
, m_h(t.m_h)
, m_min(t.m_min)
, m_sec(t.m_sec)
, m_msec(t.m_msec) {}
//-----------------------------------------------------------------------------------
bool TTime::operator==(const TTime &time) const {
return (m_y == time.m_y) && (m_m == time.m_m) && (m_d == time.m_d) &&
(m_h == time.m_h) && (m_min == time.m_min) && (m_sec == time.m_sec) &&
(m_msec == time.m_msec);
}
//-----------------------------------------------------------------------------------
bool TTime::operator>(const TTime &time) const {
return (m_y > time.m_y) || (m_y == time.m_y && m_m > time.m_m) ||
(m_y == time.m_y && m_m == time.m_m && m_d > time.m_d) ||
(m_y == time.m_y && m_m == time.m_m && m_d == time.m_d &&
m_h > time.m_h) ||
(m_y == time.m_y && m_m == time.m_m && m_d == time.m_d &&
m_h == time.m_h && m_min > time.m_min) ||
(m_y == time.m_y && m_m == time.m_m && m_d == time.m_d &&
m_h == time.m_h && m_min == time.m_min && m_sec > time.m_sec) ||
(m_y == time.m_y && m_m == time.m_m && m_d == time.m_d &&
m_h == time.m_h && m_min == time.m_min && m_sec == time.m_sec &&
m_msec > time.m_msec);
}
//-----------------------------------------------------------------------------------
TDeltaTime TTime::operator-(const TTime &t) const {
time_t t2 = makeTimeT(*this);
assert(t2 != -1);
time_t t1 = makeTimeT(t);
assert(t1 != -1);
double d = difftime(t2, t1);
if (m_msec >= t.m_msec) {
if (d <= -1)
return TDeltaTime((long)(d + 1), -(long)(1000 - (m_msec - t.m_msec)));
else
return TDeltaTime((long)d, (long)(m_msec - t.m_msec));
} else {
if (d <= 0)
return TDeltaTime((long)(d), (long)(m_msec - t.m_msec));
else
return TDeltaTime((long)(d - 1), (long)(1000 + m_msec - t.m_msec));
}
}
//-----------------------------------------------------------------------------------
TTime TTime::operator+(const TDeltaTime &tdt) const {
tm x;
makeTm(*this, &x);
int ms = m_msec + tdt.getMilliSeconds();
if (ms < 0) {
ms += 1000;
x.tm_sec += tdt.getSeconds() - 1;
} else
x.tm_sec += tdt.getSeconds() + ms / 1000;
mktime(&x);
return makeTTime(x, ms % 1000);
}
//-----------------------------------------------------------------------------------
TTime TTime::operator-(const TDeltaTime &tdt) const {
tm x;
makeTm(*this, &x);
int ms = m_msec - tdt.getMilliSeconds();
if (ms < 0) {
ms += 1000;
x.tm_sec -= tdt.getSeconds() + 1;
} else
x.tm_sec -= tdt.getSeconds() + ms / 1000;
mktime(&x);
return makeTTime(x, ms % 1000);
}
//-----------------------------------------------------------------------------------
string TTime::getFormattedString(char *fmt) const {
tm x;
makeTm(*this, &x);
char strDest[256];
if (!fmt)
// fmt="%b %d %Y %X";
return getDate() + " " + getTime();
strftime(strDest, 256, fmt, &x);
return string(strDest);
}
//-----------------------------------------------------------------------------------
string TTime::getDate() const { return getFormattedString("%b %d %Y"); }
//-----------------------------------------------------------------------------------
string TTime::getTime() const { // hh:mm:ss
stringstream buff_s;
buff_s << "." << m_msec << '\0';
return getFormattedString("%X") + buff_s.str();
}
//-----------------------------------------------------------------------------------
TTime TTime::floor() const {
return TTime(m_y, m_m, m_d, m_h, m_min, m_sec, 0);
}
//-----------------------------------------------------------------------------------
TTime TTime::ceil() const {
if (m_msec == 0)
return *this;
else
return *this + TDeltaTime(0, 1000 - m_msec);
}
//===================================================================================
TFileStatus::TFileStatus(const TFilePath &path) {
int acc = ACCESS(path.getFullPath().c_str(), 00); // 00 == solo esistenza
m_exist = acc != -1;
// gestire eccezioni controllando il valore di ritorno di access
// controllare il valore di errno
// int ret=
STAT(path.getFullPath().c_str(),
&m_fStatus); // returns 0 if the file-status information is obtained
/* if(ret!=0) ::memset(&m_fStatus,0,sizeof(m_fStatus)):*/
}
//-----------------------------------------------------------------------------------
string TFileStatus::getGroup() const {
#ifndef WIN32
struct group *grp = getgrgid(m_fStatus.st_gid);
if (grp) return string(grp->gr_name);
#endif
stringstream buff;
buff << m_fStatus.st_gid;
return buff.str();
}
//-----------------------------------------------------------------------------------
string TFileStatus::getUser() const {
#ifndef WIN32
struct passwd *pw = getpwuid(m_fStatus.st_uid);
if (pw) return string(pw->pw_name);
#endif
stringstream buff;
buff << m_fStatus.st_uid;
return buff.str();
}
//-----------------------------------------------------------------------------------
long TFileStatus::getSize() const { return (long)m_fStatus.st_size; }
//-----------------------------------------------------------------------------------
TTime TFileStatus::getLastAccessTime() const {
struct tm *t = localtime(&(m_fStatus.st_atime));
return TTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
t->tm_min, t->tm_sec);
}
//-----------------------------------------------------------------------------------
TTime TFileStatus::getLastModificationTime() const {
struct tm *t = localtime(&(m_fStatus.st_mtime));
return TTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
t->tm_min, t->tm_sec);
}
//-----------------------------------------------------------------------------------
TTime TFileStatus::getCreationTime() const {
struct tm *t = localtime(&(m_fStatus.st_ctime));
return TTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,
t->tm_min, t->tm_sec);
}
//-----------------------------------------------------------------------------------
unsigned long TFileStatus::getPermissions() const { return m_fStatus.st_mode; }
//-----------------------------------------------------------------------------------
bool TFileStatus::isDirectory() const {
return doesExist() && (getPermissions() & TFileStatus::IfDir) != 0;
}
//-----------------------------------------------------------------------------------
string TSystem::getHostName() {
char hostName[MaxHostNameLen];
#ifdef WIN32
WSADATA wdata;
int err;
err = WSAStartup(MAKEWORD(1, 1), &wdata);
if (!err) strcpy(hostName, "localhost"); // la rete non e' partita ?!?
#endif
gethostname((char *)&hostName, MaxHostNameLen);
#ifdef WIN32
if (err) WSACleanup();
#endif
return hostName;
}
//------------------------------------------------------------
string TSystem::getUserName() {
#ifdef WIN32
#ifndef UNLEN
#define UNLEN (256)
#endif
const long bufSize = UNLEN;
#else
const long bufSize = L_cuserid;
#endif
char userName[bufSize + 1];
#ifdef WIN32
GetUserName((char *)&userName, (unsigned long *)(&bufSize));
#else
cuserid(userName);
if (userName[0] == 0x00) strcpy(userName, "User Unknown");
#endif
return string(userName);
}
//------------------------------------------------------------
string TSystem::getGroupName() {
#ifdef WIN32
return string();
#else
struct group *currentGroup;
currentGroup = getgrgid(getgid());
if (currentGroup)
return string(currentGroup->gr_name);
else
return string();
#endif
}
//------------------------------------------------------------
int TSystem::getProcessId() { return getpid(); }
//------------------------------------------------------------
TFilePath TSystem::getHomeDirectory() {
#ifndef WIN32
struct passwd *pwd = getpwnam(getUserName().c_str());
if (!pwd) {
return TFilePath();
}
return TFilePath(pwd->pw_dir);
#else
char *s = getenv("USERPROFILE");
if (!s)
return TFilePath();
else
return TFilePath(s);
#endif
}
//------------------------------------------------------------
TFilePath TSystem::getTempDir() {
#ifdef WIN32
// gestire eccezioni se dw==0
DWORD dw = GetTempPath(0, 0); // non include il terminatore
char *path = new char[dw + 1];
GetTempPath(dw, path);
TFilePath tempDir(path);
delete[] path;
return tempDir;
#else
return TFilePath(tmpnam(0)).getParentDir();
#endif
}
//------------------------------------------------------------
TFilePath TSystem::getTestDir() {
#ifdef WIN32
return TFilePath("\\\\sirio\\toonz5.0\\TNZCORE_TEST");
#else
return TFilePath("/ULTRA/toonz5.0/TNZCORE_TEST");
#endif
}
//------------------------------------------------------------
string TSystem::getSystemValue(const TFilePath &name) {
#ifdef WIN32
string keyName = name.getParentDir().getFullPath();
string varName = name.getName();
HKEY hkey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName.c_str(), 0, KEY_READ, &hkey) !=
ERROR_SUCCESS) {
/*key not defined*/
return "";
}
unsigned char buffer[1024];
unsigned long bufferSize = sizeof(buffer);
string value;
if (RegQueryValueEx(hkey, varName.c_str(), NULL, NULL, buffer, &bufferSize) ==
ERROR_SUCCESS)
value = string((char *)buffer);
RegCloseKey(hkey);
return value;
#else
char *s = getenv(name.getFullPath().c_str());
return string(s ? s : "");
#endif
}
//------------------------------------------------------------
TFilePath TSystem::getBinDir() {
#ifdef WIN32
char buf[MaxPathLen];
GetModuleFileName(0, buf, MaxPathLen);
return TFilePath(buf).getParentDir();
#else
string binroot = TSystem::getSystemValue("BINROOT");
if (binroot == "") {
assert(!"BINROOT variable undefined");
}
return TFilePath(binroot) + "bin";
#endif
}
//------------------------------------------------------------
TFilePath TSystem::getUniqueFile(string field) {
char *tempName = TEMPNAM(getTempDir().getFullPath().c_str(), field.c_str());
if (tempName == 0)
throw TSystemException(TFilePath(getTempDir().getFullPath() + field), 1);
TFilePath outPath(tempName);
free(tempName);
return outPath;
}
//------------------------------------------------------------
const TDeltaTime TDeltaTime::second = TDeltaTime(1, 0);
const TDeltaTime TDeltaTime::minute = 60 * TDeltaTime::second;
const TDeltaTime TDeltaTime::hour = 60 * TDeltaTime::minute;
const TDeltaTime TDeltaTime::day = 24 * TDeltaTime::hour;
//------------------------------------------------------------
TTime TSystem::getCurrentTime() {
#ifdef WIN32
struct _timeb curTime;
#else
struct timeb curTime;
#endif
FTIME(&curTime);
struct tm *localTime = localtime(&(curTime.time));
return TTime(localTime->tm_year + 1900, localTime->tm_mon + 1,
localTime->tm_mday, localTime->tm_hour, localTime->tm_min,
localTime->tm_sec, curTime.millitm);
}
//------------------------------------------------------------
// gestire exception
void TSystem::mkDir(const TFilePath &path) {
if (path == "") {
throw TSystemException("mkdir: Empty argument");
}
if (TFileStatus(path).doesExist() || path.isRoot()) return;
while (!TFileStatus(path.getParentDir()).doesExist() &&
!path.getParentDir().isRoot()) {
mkDir(path.getParentDir());
}
#ifdef WIN32
int ret = MKDIR(path.getFullPath().c_str()); // ret e' EEXIST o ENOENT
#else
umask(0);
mode_t attr = TFileStatus::UserReadable | TFileStatus::UserWritable |
TFileStatus::UserExecutable | TFileStatus::OwnerReadWriteExec |
TFileStatus::GroupReadWriteExec |
TFileStatus::OtherReadWriteExec;
int ret = MKDIR(path.getFullPath().c_str(), attr); // ret e` EEXIST o ENOENT
#endif
if (ret == -1) throw TSystemException(path, errno);
}
//------------------------------------------------------------
// gestire exception
void TSystem::rmDir(const TFilePath &path) {
// if (!TFileStatus(path).doesExist())
// return;
int ret = RMDIR(path.getFullPath().c_str());
if (ret == -1) // ret e' ENOTEMPTY o ENOENT
throw TSystemException(path, errno);
}
//------------------------------------------------------------
void TSystem::rmDirTree(const TFilePath &path) {
TFilePathSet pathSet = readDirectory(path);
for (TFilePathSet::iterator it = pathSet.begin(); it != pathSet.end(); it++) {
TFilePath path = *it;
if (TFileStatus(path).isDirectory())
rmDirTree(path);
else
deleteFile(path);
}
rmDir(path);
}
//------------------------------------------------------------
void TSystem::copyDir(const TFilePath &dst, const TFilePath &src) {
if (!TFileStatus(dst).doesExist()) mkDir(dst);
TFilePathSet pathSet = readDirectory(src);
for (TFilePathSet::iterator it = pathSet.begin(); it != pathSet.end(); it++) {
TFilePath path = *it;
if (TFileStatus(path).isDirectory())
copyDir(path.withParentDir(dst), path);
else
copyFile(path.withParentDir(dst), path);
}
}
//------------------------------------------------------------
void TSystem::touchFile(const TFilePath &path) {
string filename = path.getFullPath();
if (TFileStatus(path).doesExist()) {
if (0 != UTIME(filename.c_str(), 0)) throw TSystemException(path, errno);
} else {
std::ofstream file(filename.c_str());
if (!file) {
throw TSystemException(path, errno);
}
file.close(); // altrimenti il compilatore da' un warning:
// variabile non utilizzata
}
}
//------------------------------------------------------------
#ifdef WIN32
namespace {
//------------------------------------------------------------
string getFormattedMessage(DWORD lastError) {
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, lastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf, 0, NULL);
return (char *)lpMsgBuf;
}
//------------------------------------------------------------
} // namespace
#endif
//------------------------------------------------------------
void TSystem::copyFile(const TFilePath &dst, const TFilePath &src) {
assert(dst != src);
#ifdef WIN32
// o e' meglio usare CopyFileEx??
BOOL res = CopyFile(
src.getFullPath().c_str(), // pointer to name of an existing file
dst.getFullPath().c_str(), // pointer to filename to copy to
TRUE); // flag for operation if file exists
if (res == 0) {
throw TSystemException(src, getFormattedMessage(GetLastError()));
}
#else
std::ifstream fpin(src.getFullPath().c_str(), ios::in);
std::ofstream fpout(dst.getFullPath().c_str(), ios::out);
if (!fpin || !fpout) throw TSystemException(src, "unable to copy file");
int c = fpin.get();
while (!fpin.eof()) {
fpout.put(c);
c = fpin.get();
}
#endif
}
//------------------------------------------------------------
void TSystem::renameFile(const TFilePath &dst, const TFilePath &src) {
int ret = rename(src.getFullPath().c_str(), dst.getFullPath().c_str());
if (ret != 0) throw TSystemException(dst, errno);
}
//------------------------------------------------------------
// gestire gli errori con GetLastError?
void TSystem::deleteFile(const TFilePath &dst) {
#ifdef WIN32
BOOL res = DeleteFile(
dst.getFullPath().c_str()); // pointer to name of file to delete
// se fallisce perche' un file e' aperto chiudiamo prima il file?
// To close an open file, use the CloseHandle function.
if (res == 0)
throw TSystemException(dst, getFormattedMessage(GetLastError()));
#else
int ret = remove(dst.getFullPath().c_str());
if (ret != 0) throw TSystemException(dst, errno);
#endif
}
//------------------------------------------------------------
void TSystem::moveFileToRecycleBin(const TFilePath &fp) {
#ifdef WIN32
//
// from http://msdn.microsoft.com/msdnmag/issues/01/04/c/default.aspx
//
// Copy pathname to double-NULL-terminated string.
//
char buf[_MAX_PATH + 1]; // allow one more character
strcpy(buf, fp.getFullPath().c_str()); // copy caller's path name
buf[strlen(buf) + 1] = 0; // need two NULLs at end
SHFILEOPSTRUCT data;
memset(&data, 0, sizeof(SHFILEOPSTRUCT));
data.fFlags |= FOF_SILENT; // don't report progress
data.fFlags |= FOF_NOERRORUI; // don't report errors
data.fFlags |= FOF_NOCONFIRMATION; // don't confirm delete
data.wFunc = FO_DELETE; // REQUIRED: delete operation
data.pFrom = buf; // REQUIRED: which file(s)
data.pTo = NULL; // MUST be NULL
data.fFlags |= FOF_ALLOWUNDO; // ..send to Recycle Bin
SHFileOperation(&data); // do it!
#else
assert(!"Not implemented yet");
#endif
}
//------------------------------------------------------------
void TSystem::readDirectory(TFilePathSet &dst, const TFilePath &path) {
if (!TFileStatus(path).isDirectory()) {
throw TSystemException(path, " is not a directory");
}
#ifdef WIN32
WIN32_FIND_DATA findFileData;
string search = (path + "*").getFullPath();
HANDLE h = FindFirstFile(search.c_str(), &findFileData);
if (h == INVALID_HANDLE_VALUE)
throw TSystemException(path, getFormattedMessage(GetLastError()));
do {
string filename(findFileData.cFileName);
if (filename == "." || filename == "..") continue;
TFilePath son = path + filename;
dst.push_back(son);
} while (FindNextFile(h, &findFileData));
FindClose(h);
#else
DIR *dirp;
struct direct *directp;
dirp = opendir(path.getFullPath().c_str());
if (dirp == 0) throw TSystemException(path, errno);
while (directp = readdir(dirp)) {
string filename(directp->d_name);
if (filename == "." || filename == "..") continue;
TFilePath son = path + filename;
dst.push_back(son);
}
closedir(dirp);
#endif
}
//------------------------------------------------------------
void TSystem::readDirectory(TFilePathSet &dst, const TFilePathSet &pathSet) {
for (TFilePathSet::const_iterator it = pathSet.begin(); it != pathSet.end();
it++)
readDirectory(dst, *it);
}
//------------------------------------------------------------
TFilePathSet TSystem::readDirectory(const TFilePath &path) {
TFilePathSet filePathSet;
readDirectory(filePathSet, path);
return filePathSet;
}
//------------------------------------------------------------
TFilePathSet TSystem::readDirectory(const TFilePathSet &pathSet) {
TFilePathSet dst;
readDirectory(dst, pathSet);
return dst;
}
//------------------------------------------------------------
void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePath &path) {
if (!TFileStatus(path).isDirectory()) {
throw TSystemException(path, " is not a directory");
}
#ifdef WIN32
WIN32_FIND_DATA findFileData;
string search = (path + "*").getFullPath();
HANDLE h = FindFirstFile(search.c_str(), &findFileData);
if (h == INVALID_HANDLE_VALUE) return;
do {
string filename(findFileData.cFileName);
if (filename == "." || filename == "..") continue;
TFilePath son = path + findFileData.cFileName;
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
readDirectoryTree(dst, son);
else
dst.push_back(son);
} while (FindNextFile(h, &findFileData));
FindClose(h);
#else
DIR *dirp;
struct direct *directp;
dirp = opendir(path.getFullPath().c_str());
if (dirp == 0) throw TSystemException(path, errno);
while (directp = readdir(dirp)) {
string filename(directp->d_name);
if (filename == "." || filename == "..") continue;
TFilePath son = path + filename;
if (TFileStatus(son).isDirectory())
readDirectoryTree(dst, son);
else
dst.push_back(son);
}
closedir(dirp);
#endif
}
//------------------------------------------------------------
void TSystem::readDirectoryTree(TFilePathSet &dst,
const TFilePathSet &pathSet) {
for (TFilePathSet::const_iterator it = pathSet.begin(); it != pathSet.end();
it++)
readDirectoryTree(dst, *it);
}
//------------------------------------------------------------
TFilePathSet TSystem::readDirectoryTree(const TFilePath &path) {
TFilePathSet dst;
readDirectoryTree(dst, path);
return dst;
}
//------------------------------------------------------------
TFilePathSet TSystem::readDirectoryTree(const TFilePathSet &pathSet) {
TFilePathSet dst;
readDirectoryTree(dst, pathSet);
return dst;
}
//------------------------------------------------------------
TFilePathSet TSystem::packLevelNames(const TFilePathSet &fps) {
std::set<TFilePath> tmpSet;
TFilePathSet::const_iterator cit;
for (cit = fps.begin(); cit != fps.end(); ++cit)
tmpSet.insert(cit->getParentDir() + cit->getLevelName());
TFilePathSet fps2;
for (std::set<TFilePath>::const_iterator c_sit = tmpSet.begin();
c_sit != tmpSet.end(); ++c_sit) {
fps2.push_back(*c_sit);
}
return fps2;
}
//------------------------------------------------------------
TFilePathSet TSystem::getDisks() {
TFilePathSet filePathSet;
#ifdef WIN32
DWORD size = GetLogicalDriveStrings(0, NULL);
char *buffer = new char[size + 1];
char *ptr = buffer;
DWORD rc = GetLogicalDriveStrings(size, buffer);
if (rc == 0) throw TSystemException("", getFormattedMessage(GetLastError()));
while (*ptr) {
filePathSet.push_back(ptr);
while (*ptr) ptr++;
ptr++;
}
delete[] buffer;
return filePathSet;
#else
FILE *f = setmntent("/etc/fstab", "r");
if (f) {
while (struct mntent *m = getmntent(f)) {
// cout << "machine "<< m->mnt_fsname << " dir " <<m->mnt_dir << " type "
// << m->mnt_type << endl;
filePathSet.push_back(m->mnt_dir);
}
endmntent(f);
}
return filePathSet;
#endif
}
//------------------------------------------------------------
ULONG TSystem::getDiskSize(const TFilePath &diskName) {
ULONG size = 0;
if (!diskName.isAbsolute()) {
assert(0);
return 0;
}
#ifndef WIN32
struct statfs buf;
#ifdef __sgi
statfs(diskName.getFullPath().c_str(), &buf, sizeof(struct statfs), 0);
#else
statfs(diskName.getFullPath().c_str(), &buf);
#endif
size = (ULONG)((buf.f_blocks * buf.f_bsize) >> 10);
#else
DWORD sectorsPerCluster; // sectors per cluster
DWORD bytesPerSector; // bytes per sector
DWORD numberOfFreeClusters; // free clusters
DWORD totalNumberOfClusters;
BOOL rc = GetDiskFreeSpace(diskName.getFullPath().c_str(), // root path
§orsPerCluster, // sectors per cluster
&bytesPerSector, // bytes per sector
&numberOfFreeClusters, // free clusters
&totalNumberOfClusters // total clusters
);
if (!rc)
throw TSystemException(diskName, getFormattedMessage(GetLastError()));
else
size = (totalNumberOfClusters * sectorsPerCluster * bytesPerSector) >> 10;
#endif
return size;
}
//------------------------------------------------------------
ULONG TSystem::getFreeDiskSize(const TFilePath &diskName) {
ULONG size = 0;
if (!diskName.isAbsolute()) {
assert(0);
return 0;
}
#ifndef WIN32
struct statfs buf;
#ifdef __sgi
statfs(diskName.getFullPath().c_str(), &buf, sizeof(struct statfs), 0);
#else
statfs(diskName.getFullPath().c_str(), &buf);
#endif
size = (ULONG)(buf.f_bfree * buf.f_bsize) >> 10;
#else
DWORD sectorsPerCluster; // sectors per cluster
DWORD bytesPerSector; // bytes per sector
DWORD numberOfFreeClusters; // free clusters
DWORD totalNumberOfClusters;
BOOL rc = GetDiskFreeSpace(diskName.getFullPath().c_str(), // root path
§orsPerCluster, // sectors per cluster
&bytesPerSector, // bytes per sector
&numberOfFreeClusters, // free clusters
&totalNumberOfClusters // total clusters
);
if (!rc) // eccezione... getLastError etc...
throw TSystemException(diskName, getFormattedMessage(GetLastError()));
else
size = (numberOfFreeClusters * sectorsPerCluster * bytesPerSector) >> 10;
#endif
return size;
}
//------------------------------------------------------------
ULONG TSystem::getFreeMemorySize() {
ULONG totalFree = 0;
#ifdef WIN32
ULONG virtualFree = 0;
ULONG physicalFree = 0;
MEMORYSTATUS buff;
GlobalMemoryStatus(&buff);
physicalFree = buff.dwAvailPhys;
virtualFree = buff.dwAvailVirtual;
totalFree = (physicalFree + virtualFree) >> 10;
#else
#ifdef __sgi
// check for virtual memory
int numberOfResources =
swapctl(SC_GETNSWP, 0); /* get number of swapping resources configued */
if (numberOfResources == 0) return 0;
// avrei voluto fare: struct swaptable *table = new struct swaptable[...]
struct swaptable *table = (struct swaptable *)calloc(
1, sizeof(struct swapent) * numberOfResources + sizeof(int));
table->swt_n = numberOfResources;
swapctl(SC_LIST, table); /* list all the swapping resources */
ULONG virtualFree = 0;
ULONG physicalFree = 0;
for (int i = 0; i < table->swt_n; i++) {
virtualFree += table->swt_ent[i].ste_free;
}
free(table);
totalFree = virtualFree << 4 + physicalFree;
#else
#ifdef LINUX
struct sysinfo *sysInfo = (struct sysinfo *)calloc(1, sizeof(struct sysinfo));
if (!sysinfo(sysInfo)) {
totalFree = sysInfo->freeram + sysInfo->freeswap;
} else {
assert(!"sysinfo function failed");
}
free(sysInfo);
#else
@ @ @ERROR : PLATFORM NOT SUPPORTED
#endif
#endif //__sgi
#endif // WIN32
#ifndef WIN32
#else
#endif
return totalFree;
}
//------------------------------------------------------------
ostream &operator<<(ostream &out, const TTime &t) {
return out << t.getDate() << " " << t.getTime();
}
//------------------------------------------------------------
#ifdef __sgi
extern "C" long sginap(long ticks);
#else
#ifdef LINUX
extern "C" int usleep(unsigned int);
#endif
#endif
void TSystem::sleep(const TDeltaTime &delay) {
int ms = delay.getSeconds() * 1000;
assert(ms >= delay.getSeconds());
ms += delay.getMilliSeconds();
#ifdef WIN32
Sleep(ms);
#else
#ifdef __sgi
sginap(ms * CLK_TCK / 1000);
#else
#ifdef LINUX
ms *= 1000;
usleep(ms);
#endif
#endif
#endif
}
//--------------------------------------------------------------
TSystemException::TSystemException(const TFilePath &fname, int err)
: m_fname(fname.getFullPath())
, m_err(err)
, m_msg("")
{}
//--------------------------------------------------------------
TSystemException::TSystemException(const TFilePath &fname, const string &msg)
: m_fname(fname.getFullPath()), m_err(-1), m_msg(msg) {}
//--------------------------------------------------------------
TSystemException::TSystemException(const string &msg)
: m_fname(""), m_err(-1), m_msg(msg) {}
//--------------------------------------------------------------
string TSystemException::getMessage() const {
string msg = m_fname;
switch (m_err) {
case -1:
// nothing
msg += ": ";
msg += m_msg;
CASE EEXIST : msg +=
": Directory was not created because filename is the name of "
"an existing file, directory, or device";
CASE ENOENT : msg +=
": Path was not found, or the named file does not exist or "
"is a null pathname.";
CASE ENOTEMPTY : msg +=
": Given path is not a directory; directory is not empty; "
"or directory is either current working directory or root "
"directory";
CASE EACCES : msg +=
": Search permission is denied by a component of the path "
"prefix, or write permission on the file named by path is "
"denied, or times is NULL, and write access is denied";
CASE EFAULT : msg +=
": Times is not NULL and, or points outside the process's "
"allocated address space.";
CASE EINTR : msg += ": A signal was caught during the utime system call.";
CASE ENAMETOOLONG : msg +=
": The length of the path argument exceeds {PATH_MAX}, "
"or the length of a path component exceeds {NAME_MAX} "
"while _POSIX_NO_TRUNC is in effect.";
CASE ENOTDIR : msg +=
": A component of the path prefix is not a directory.";
CASE EPERM : msg +=
": The calling process does not have the super-user "
"privilege, the effective user ID is not the owner of the "
"file, and times is not NULL, or the file system containing "
"the file is mounted read-only";
CASE EROFS : msg +=
": The current file system level range does not envelop the "
"level of the file named by path, and the calling process "
"does not have the super-user privilege.";
CASE ENOSYS : msg +=
": When the named file cannot have its time reset. The file "
"is on a file system that doesn't have this operation.";
CASE EMFILE
: msg += ": The maximum number of file descriptors are currently open.";
CASE ENFILE : msg += ": The system file table is full.";
CASE EBADF : msg +=
": The file descriptor determined by the DIR stream is no "
"longer valid. This result occurs if the DIR stream has been "
"closed.";
CASE EINVAL
: msg +=
": 64-bit and non-64-bit calls were mixed in a sequence of calls.";
DEFAULT:
msg += ": Unknown error";
#ifndef WIN32
CASE ELOOP
: msg +=
": Too many symbolic links were encountered in translating path.";
CASE EMULTIHOP : msg +=
": Components of path require hopping to multiple remote "
"machines and the file system does not allow it.";
CASE ENOLINK : msg +=
": Path points to a remote machine and the link to that "
"machine is no longer active.";
#ifndef LINUX
CASE EDIRCORRUPTED : msg += ": The directory is corrupted on disk.";
#endif
CASE EOVERFLOW : msg +=
": One of the inode number values or offset values did "
"not fit in 32 bits, and the 64-bit interfaces were not "
"used.";
#endif
}
return msg;
}
//--------------------------------------------------------------
static const char *TnzLibMainProcName = "TLibMain";
static std::map<string, const TPluginInfo *> PluginTable;
static std::set<TnzLibMainProcType *> PluginMainTable;
//--------------------------------------------------------------
namespace {
#ifdef WIN32
static std::vector<HINSTANCE> PluginInstanceTable;
#else
static std::vector<void *> PluginInstanceTable;
#endif
extern "C" void unloadPlugins() {
#ifdef WIN32
for (std::vector<HINSTANCE>::iterator it = PluginInstanceTable.begin();
it != PluginInstanceTable.end(); ++it)
FreeLibrary(*it);
#else
for (std::vector<void *>::iterator it = PluginInstanceTable.begin();
it != PluginInstanceTable.end(); ++it)
dlclose(*it);
#endif
PluginInstanceTable.clear();
}
}
//--------------------------------------------------------------
void TSystem::unLoadPlugins() { unloadPlugins(); }
//--------------------------------------------------------------
void TSystem::loadPlugins(const TFilePath &dir) {
static bool cbReg = false;
if (!cbReg) {
cbReg = true;
atexit(unloadPlugins);
}
#ifdef WIN32
string extension = "dll";
#else
string extension = "so";
#endif
TFilePathSet dirContent = TSystem::readDirectory(dir);
if (dirContent.empty()) return;
for (TFilePathSet::iterator it = dirContent.begin(); it != dirContent.end();
it++) {
TFilePath fp = *it;
if (fp.getType() != extension) continue;
// cout << "Loading..." << fp << endl;
#ifdef WIN32
HINSTANCE handle = LoadLibrary(fp.getFullPath().c_str());
#else
void *handle = dlopen(fp.getFullPath().c_str(), RTLD_LAZY);
#endif
if (!handle) {
// non riesce a caricare la libreria;
#ifdef WIN32
DWORD err = GetLastError();
string s;
s = "*Error* unable to load " + fp.getFullPath() + ": " +
getFormattedMessage(err) + '\0';
TSystem::outputDebug(s);
#else
cout << "*ERROR* couldn't load " << fp << ":";
cout << dlerror() << endl;
#endif
} else {
PluginInstanceTable.push_back(handle);
// cout << "loaded" << endl;
#ifdef WIN32
TnzLibMainProcType *tnzLibMain =
(TnzLibMainProcType *)GetProcAddress(handle, TnzLibMainProcName);
#else
TnzLibMainProcType *tnzLibMain =
(TnzLibMainProcType *)dlsym(handle, TnzLibMainProcName);
#endif
if (!tnzLibMain) {
// La libreria non esporta TLibMain;
// per ora niente messaggi di errore
// cout<< "Unable to load TLibMain" << endl;
/*
#ifdef WIN32
FreeLibrary(handle);
#else
dlclose(handle);
#endif
*/
} else {
std::set<TnzLibMainProcType *>::iterator it;
it = PluginMainTable.find(tnzLibMain);
if (it == PluginMainTable.end()) {
PluginMainTable.insert(tnzLibMain);
const TPluginInfo *info = tnzLibMain();
if (info) {
PluginTable[info->getName()] = info;
}
}
} // if(tnzLibMain)
} // if(handle)
} // for
}
//--------------------------------------------------------------
void TSystem::loadStandardPlugins() {
static bool alreadyDone = false;
if (alreadyDone) return;
alreadyDone = true;
TFilePath pluginsDir = TSystem::getBinDir() + "plugins";
// cout << "loading standard plugins ... " << pluginsDir << endl;
try {
TSystem::loadPlugins(pluginsDir + "io");
} catch (const TException &e) {
#ifdef WIN32
MessageBox(0, e.getMessage().c_str(), "Error loading plugin", MB_OK);
#else
cout << e.getMessage() << endl;
#endif
}
try {
TSystem::loadPlugins(pluginsDir + "fx");
} catch (const TException &e) {
#ifdef WIN32
MessageBox(0, e.getMessage().c_str(), "Error loading plugin", MB_OK);
#else
cout << e.getMessage() << endl;
#endif
}
// cout << "done ... " << endl;
}
//--------------------------------------------------------------
const TPluginInfo *TSystem::getLoadedPluginInfo(string name) {
std::map<string, const TPluginInfo *>::iterator it;
it = PluginTable.find(name);
if (it == PluginTable.end())
return 0;
else
return it->second;
}
//--------------------------------------------------------------
void TSystem::showDocument(const TFilePath &path) {
#ifdef WIN32
int ret = (int)ShellExecute(0, "open", path.getFullPath().c_str(), 0, 0,
SW_SHOWNORMAL);
if (ret <= 32) {
throw TException(path.getFullPath() + " : can't open");
}
#else
string cmd = "mediaplayer ";
cmd = cmd + path.getFullPath();
system(cmd.c_str());
#endif
}
//--------------------------------------------------------------
int TSystem::getProcessorCount() {
#ifdef WIN32
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwNumberOfProcessors;
#else
#ifdef __sgi
return sysconf(_SC_NPROC_CONF);
#else
return sysconf(_SC_NPROCESSORS_CONF);
#endif
#endif
}
//--------------------------------------------------------------
void TSystem::outputDebug(string s) {
#ifdef WIN32
OutputDebugString(s.c_str());
#else
cerr << s << endl;
#endif
}