| |
| |
| #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); |
| |
| 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 |
| using std::ifstream; |
| using std::ofstream; |
| using std::filebuf; |
| #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; |
| } |
| |
| |
| |
| 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; |
| 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; |
| } |
| |
| } |
| |
| |
| |
| TDeltaTime::TDeltaTime(long sec, long msec) |
| { |
| |
| assert(!((sec < 0 && msec > 0) || (sec > 0 && msec < 0))); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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(); |
| } |
| |
| |
| |
| |
| |
| |
| |
| 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) |
| |
| return getDate() + " " + getTime(); |
| strftime(strDest, 256, fmt, &x); |
| return string(strDest); |
| } |
| |
| |
| |
| string TTime::getDate() const |
| { |
| return getFormattedString("%b %d %Y"); |
| } |
| |
| |
| |
| string TTime::getTime() const |
| { |
| char buffer[10]; |
| ostrstream buff_s(buffer, sizeof(buffer)); |
| buff_s << "." << m_msec << '\0'; |
| return getFormattedString("%X") + buffer; |
| } |
| |
| |
| |
| 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); |
| m_exist = acc != -1; |
| |
| |
| |
| STAT(path.getFullPath().c_str(), &m_fStatus); |
| |
| } |
| |
| |
| |
| string TFileStatus::getGroup() const |
| { |
| #ifndef WIN32 |
| struct group *grp = getgrgid(m_fStatus.st_gid); |
| if (grp) |
| return string(grp->gr_name); |
| #endif |
| char buffer[1024]; |
| ostrstream buff(buffer, sizeof(buffer)); |
| buff << m_fStatus.st_gid; |
| return string(buffer, buff.pcount()); |
| } |
| |
| |
| |
| string TFileStatus::getUser() const |
| { |
| #ifndef WIN32 |
| struct passwd *pw = getpwuid(m_fStatus.st_uid); |
| if (pw) |
| return string(pw->pw_name); |
| #endif |
| char buffer[1024]; |
| ostrstream buff(buffer, sizeof(buffer)); |
| buff << m_fStatus.st_uid; |
| return string(buffer, buff.pcount()); |
| } |
| |
| |
| |
| 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"); |
| #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 |
| |
| DWORD dw = GetTempPath(0, 0); |
| 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) { |
| |
| 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); |
| } |
| |
| |
| |
| 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()); |
| #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); |
| #endif |
| if (ret == -1) |
| throw TSystemException(path, errno); |
| } |
| |
| |
| |
| void TSystem::rmDir(const TFilePath &path) |
| { |
| |
| |
| int ret = RMDIR(path.getFullPath().c_str()); |
| if (ret == -1) |
| 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 { |
| ofstream file(filename.c_str()); |
| if (!file) { |
| throw TSystemException(path, errno); |
| } |
| file.close(); |
| |
| } |
| } |
| |
| |
| |
| #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), |
| (LPTSTR)&lpMsgBuf, |
| 0, |
| NULL); |
| return (char *)lpMsgBuf; |
| } |
| |
| |
| |
| } |
| #endif |
| |
| |
| void TSystem::copyFile(const TFilePath &dst, const TFilePath &src) |
| { |
| assert(dst != src); |
| #ifdef WIN32 |
| |
| BOOL res = CopyFile(src.getFullPath().c_str(), |
| dst.getFullPath().c_str(), |
| TRUE); |
| if (res == 0) { |
| throw TSystemException(src, getFormattedMessage(GetLastError())); |
| } |
| #else |
| ifstream fpin(src.getFullPath().c_str(), ios::in); |
| 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); |
| } |
| |
| |
| |
| |
| void TSystem::deleteFile(const TFilePath &dst) |
| { |
| #ifdef WIN32 |
| BOOL res = DeleteFile(dst.getFullPath().c_str()); |
| |
| |
| 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 |
| |
| |
| |
| |
| |
| |
| char buf[_MAX_PATH + 1]; |
| strcpy(buf, fp.getFullPath().c_str()); |
| buf[strlen(buf) + 1] = 0; |
| |
| SHFILEOPSTRUCT data; |
| memset(&data, 0, sizeof(SHFILEOPSTRUCT)); |
| data.fFlags |= FOF_SILENT; |
| data.fFlags |= FOF_NOERRORUI; |
| data.fFlags |= FOF_NOCONFIRMATION; |
| |
| data.wFunc = FO_DELETE; |
| data.pFrom = buf; |
| data.pTo = NULL; |
| data.fFlags |= FOF_ALLOWUNDO; |
| SHFileOperation(&data); |
| #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)) { |
| |
| 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; |
| DWORD bytesPerSector; |
| DWORD numberOfFreeClusters; |
| DWORD totalNumberOfClusters; |
| |
| BOOL rc = GetDiskFreeSpace(diskName.getFullPath().c_str(), |
| §orsPerCluster, |
| &bytesPerSector, |
| &numberOfFreeClusters, |
| &totalNumberOfClusters |
| ); |
| |
| 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; |
| DWORD bytesPerSector; |
| DWORD numberOfFreeClusters; |
| DWORD totalNumberOfClusters; |
| |
| BOOL rc = GetDiskFreeSpace(diskName.getFullPath().c_str(), |
| §orsPerCluster, |
| &bytesPerSector, |
| &numberOfFreeClusters, |
| &totalNumberOfClusters |
| ); |
| |
| if (!rc) |
| 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 |
| |
| int numberOfResources = swapctl(SC_GETNSWP, 0); |
| |
| if (numberOfResources == 0) |
| return 0; |
| |
| |
| struct swaptable *table = (struct swaptable *)calloc(1, sizeof(struct swapent) * numberOfResources + sizeof(int)); |
| |
| table->swt_n = numberOfResources; |
| swapctl(SC_LIST, table); |
| |
| 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: |
| |
| 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; |
| |
| |
| #ifdef WIN32 |
| HINSTANCE handle = LoadLibrary(fp.getFullPath().c_str()); |
| #else |
| void *handle = dlopen(fp.getFullPath().c_str(), RTLD_LAZY); |
| #endif |
| |
| if (!handle) { |
| |
| #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); |
| |
| #ifdef WIN32 |
| TnzLibMainProcType *tnzLibMain = |
| (TnzLibMainProcType *)GetProcAddress(handle, TnzLibMainProcName); |
| #else |
| TnzLibMainProcType *tnzLibMain = |
| (TnzLibMainProcType *)dlsym(handle, TnzLibMainProcName); |
| #endif |
| if (!tnzLibMain) { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } 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; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| void TSystem::loadStandardPlugins() |
| { |
| static bool alreadyDone = false; |
| if (alreadyDone) |
| return; |
| alreadyDone = true; |
| TFilePath pluginsDir = TSystem::getBinDir() + "plugins"; |
| |
| |
| |
| 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 |
| } |
| |
| |
| } |
| |
| |
| |
| 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 |
| } |
| |