• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/Environment.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <stdio.h>
00018 
00019 #if defined(_WIN32) || defined(_WIN64)
00020 #include <spl/configwin32.h>
00021 #include <spl/cleanwindows.h>
00022 #else
00023 #include <spl/autoconf/config.h>
00024 #endif
00025 
00026 #include <spl/types.h>
00027 #include <spl/Debug.h>
00028 
00029 #ifdef HAVE_SYS_TYPES_H
00030 #include <sys/types.h>
00031 #endif
00032 #ifdef HAVE_PWD_H
00033 #include <pwd.h>
00034 #endif
00035 #ifdef HAVE_SYS_UTSNAME_H
00036 #include <sys/utsname.h>
00037 #endif
00038 #ifdef HAVE_ERRNO_H
00039 #include <errno.h>
00040 #endif
00041 #ifdef HAVE_FCNTL_H
00042 #include <fcntl.h>
00043 #endif
00044 #ifdef HAVE_IO_H
00045 #include <io.h>
00046 #endif
00047 #ifdef HAVE_DIRECT_H
00048 #include <direct.h>
00049 #endif
00050 #ifdef HAVE_DIRENT_H
00051 #include <dirent.h>
00052 #endif
00053 #ifdef HAVE_SYS_STAT_H
00054 #include <sys/stat.h>
00055 #endif
00056 #ifdef HAVE_UNISTD_H
00057 #include <unistd.h>
00058 #endif
00059 #ifdef HAVE_STRING_H
00060 #include <string.h>
00061 #endif
00062 #ifdef HAVE_SYS_VFS_H
00063 #include <sys/vfs.h>
00064 #endif
00065 
00066 #include <spl/Char.h>
00067 #include <spl/io/Directory.h>
00068 #include <spl/Environment.h>
00069 #include <spl/io/File.h>
00070 #include <spl/Int32.h>
00071 #include <spl/text/Regex.h>
00072 
00073 String Environment::NewLine()
00074 {
00075 #ifdef _WINDOWS
00076         return "\r\n";
00077 #elif defined(_MACOS)
00078         return "\r";
00079 #else
00080         return "\n";
00081 #endif
00082 }
00083 
00084 String Environment::ProcessName()
00085 {
00086 #ifdef _WINDOWS
00087         char  path[512] = { 0 };
00088 
00089         if (!GetModuleFileName(NULL, path, sizeof(path)) || !path[0])
00090         {
00091                 return "unknown";
00092         }
00093         String fullName(path);
00094         return *fullName.Substring(fullName.LastIndexOf('\\')+1);
00095 #else
00096         pid_t pid = getpid();
00097         StringPtr spid(Int32::ToString((int)pid));
00098         String path = "/proc/" + *spid + "/execname";
00099         if (!File::Exists(path))
00100         {
00101                 return "unknown";
00102         }
00103         TextReaderPtr reader = File::ReadText(path);
00104         StringPtr execname = reader->ReadLine();
00105         reader->Close();
00106         return *execname->Substring(execname->LastIndexOf('/')+1);
00107 #endif
00108 }
00109 
00110 String Environment::GetVariable(const String& name)
00111 {
00112 #ifdef _WINDOWS
00113         DWORD len = ::GetEnvironmentVariable(name.GetChars(), NULL, 0);
00114         if(len == 0)
00115         {
00116                 return String();
00117         }
00118 
00119         char *buf = new char[len];
00120 
00121         len = ::GetEnvironmentVariable(name.GetChars(), buf, len);
00122 
00123         String val(buf);
00124         delete [] buf;
00125         return val;
00126 
00127 #else
00128 
00129         String val = ::getenv(name.GetChars());
00130         return(val);
00131 
00132 #endif
00133 }
00134 
00135 void Environment::SetVariable(const String& name, const String& value)
00136 {
00137         if(name.IndexOf('=') > -1)
00138         {
00139                 return;
00140         }
00141 
00142 #ifdef _WINDOWS
00143 
00144         ::SetEnvironmentVariable(name.GetChars(), value.GetChars());
00145 
00146 #else
00147 
00148         ::setenv(name.GetChars(), value.GetChars(), 1);
00149 
00150 #endif
00151 }
00152 
00153 String Environment::UserName()
00154 {
00155 #ifdef _WINDOWS
00156     char ubuf[256];
00157 
00158     DWORD size = (DWORD)sizeof(ubuf);
00159     if(::GetUserName(ubuf, &size) != TRUE)
00160         {
00161                 throw new Exception("GetUserName error");
00162         }
00163         return String(ubuf);
00164 #else
00165         passwd *pw = getpwuid(geteuid());
00166         if(! pw)
00167         {
00168                 throw new Exception("getpwuid error");
00169         }
00170         return String(pw->pw_name);
00171 #endif
00172 }
00173 
00174 Vector<StringPtr> Environment::GetLogicalDrives(bool localOnly)
00175 {
00176         Vector<StringPtr> drives;
00177 
00178 #ifdef _WINDOWS
00179 
00180         DWORD mask = ::GetLogicalDrives();
00181 
00182         for(int i = 0; i < 26; i++)
00183         {
00184                 if(mask & 0x01)
00185                 {
00186                         char path[4];
00187 
00188                         sprintf(path, "%c:\\", 'A' + i);
00189 
00190                         if(! localOnly || (::GetDriveType(path) == DRIVE_FIXED))
00191                         {
00192                                 drives.Add( StringPtr(new String((const char *)path)) );
00193                         }
00194                 }
00195 
00196                 mask >>= 1;
00197         }
00198 
00199 #else
00200 
00201         drives.Add(StringPtr(new String("/")));
00202 
00203 #endif
00204 
00205         return drives;
00206 }
00207 
00208 String Environment::HostName()
00209 {
00210 #ifdef _WINDOWS
00211         char hbuf[MAX_COMPUTERNAME_LENGTH + 1];
00212 
00213         DWORD size = (DWORD)sizeof(hbuf);
00214         if(::GetComputerName(hbuf, &size) != TRUE)
00215         {
00216                 throw new Exception("GetComputerName error");
00217         }
00218         return String(hbuf);
00219 #else
00220     struct utsname uts;
00221     uname(&uts);
00222     return String(uts.nodename);
00223 #endif
00224 }
00225 
00226 String Environment::HostArchitecture()
00227 {
00228 #ifdef _WINDOWS
00229     SYSTEM_INFO sys_info;
00230 
00231     ::GetSystemInfo(&sys_info);
00232 
00233     switch(sys_info.dwProcessorType)
00234     {
00235       case PROCESSOR_INTEL_386:
00236       case PROCESSOR_INTEL_486:
00237       case PROCESSOR_INTEL_PENTIUM:
00238         return String("x86");
00239 
00240       case 2200:
00241         return String("ia64");
00242 
00243 #ifdef PROCESSOR_AMD_X8664
00244       case PROCESSOR_AMD_X8664:
00245         return String("amd8664");
00246 #endif
00247 
00248       default:
00249         return String("unknown");
00250     }
00251 
00252 #else
00253         struct utsname uts;
00254         uname(&uts);
00255         return String(uts.machine);
00256 #endif
00257 }
00258 
00259 String Environment::OSName()
00260 {
00261 #ifdef _WINDOWS
00262         return String("Windows");
00263 #else
00264     struct utsname uts;
00265     uname(&uts);
00266 
00267         return String(uts.sysname);
00268 #endif
00269 }
00270 
00271 String Environment::OSVersion()
00272 {
00273 #ifdef _WINDOWS
00274     OSVERSIONINFO os_info;
00275 
00276         os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00277     ::GetVersionEx(&os_info);
00278 
00279     switch(os_info.dwMajorVersion)
00280     {
00281       case 4:
00282         switch(os_info.dwMinorVersion)
00283         {
00284           case 0:
00285             if(os_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
00286               return String("NT 4.0");
00287             else
00288               return String("95");
00289             break;
00290 
00291           case 10:
00292             return String("98");
00293 
00294           case 90:
00295             return String("ME");
00296 
00297           default:
00298             return String("unknown");
00299         }
00300         break;
00301 
00302       case 5:
00303         switch(os_info.dwMinorVersion)
00304         {
00305           case 0:
00306             return String("2000");
00307 
00308           case 1:
00309             return String("XP");
00310 
00311           case 2:
00312             return String("Server 2003");
00313 
00314           default:
00315             return String("unknown");
00316         }
00317         break;
00318 
00319       case 6:
00320         return String("Vista");
00321 
00322           case 7:
00323                   return String("7");
00324 
00325       default:
00326                         return String("unknown");
00327     }
00328 #else
00329         struct utsname uts;
00330         uname(&uts);
00331         return String(uts.release);
00332 #endif
00333 }
00334 
00335 String Environment::HomeDirectory()
00336 {
00337 #ifdef _WINDOWS
00338         return String(Environment::GetVariable("USERPROFILE"));
00339 #else
00340         passwd *pw = getpwuid(geteuid());
00341         if(! pw)
00342         {
00343                 throw new Exception("getpwuid error");
00344         }
00345         return String(pw->pw_dir);
00346 #endif
00347 }
00348 
00349 String Environment::TempDirectory()
00350 {
00351 #ifdef _WINDOWS
00352     DWORD tmpLen = ::GetTempPath(0, NULL);
00353     char *buf = new char[tmpLen];
00354     ::GetTempPath(tmpLen, buf);
00355         String path(buf);
00356         delete [] buf;
00357         return path;
00358 #else
00359     const char *tmpEnv = getenv("TMPDIR");
00360         if (NULL != tmpEnv)
00361         {
00362                 return String(tmpEnv);
00363         }
00364         tmpEnv = getenv("TMP");
00365         if (NULL == tmpEnv)
00366         {
00367                 char *tpath = tempnam(NULL, NULL);
00368                 if (NULL != tpath)
00369                 {
00370                         String ret(tpath);
00371                         realfree(tpath);
00372                         return ret;
00373                 }
00374         }
00375         String dir = HomeDirectory() + *Char::ToString(Directory::SeperatorChar()) + "tmp";
00376         if (!Directory::IsDirectory(dir))
00377         {
00378                 Directory::Create(dir);
00379         }
00380         return dir;
00381 #endif
00382 }
00383 
00384 uint64 Environment::DiskFreeSpace()
00385 {
00386 #ifdef _WINDOWS
00387 
00388         ULARGE_INTEGER x, avail;
00389 
00390         if(::GetDiskFreeSpaceEx("\\", &x, &x,   &avail) == FALSE)
00391                 return 0;
00392 
00393         return (uint64)avail.QuadPart;
00394 
00395 #else
00396 
00397         struct statfs buf;
00398         if(::statfs("/", &buf) != 0)
00399                 return 0;
00400 
00401         return (uint64)(buf.f_bavail) * 1024;
00402 
00403 #endif
00404 }
00405 
00406 int Environment::LastError()
00407 {
00408 #ifdef _WINDOWS
00409         return GetLastError();
00410 #else
00411         return errno;
00412 #endif
00413 }
00414 
00415 String Environment::LastErrorMessage()
00416 {
00417 #ifdef _WINDOWS
00418         void *buf = NULL;
00419         ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
00420                                   FORMAT_MESSAGE_FROM_SYSTEM |
00421                                   FORMAT_MESSAGE_IGNORE_INSERTS,
00422                                   NULL,GetLastError(),0,
00423                                   (LPTSTR) &buf,0,NULL);
00424         String ret((char *)buf);
00425         
00426         // Free the buffer
00427         ::LocalFree(buf);
00428 
00429         return ret;
00430 #else
00431         char buf[256];
00432         buf[0] = '\0';
00433 #ifdef HAVE_STRERROR_R
00434         strerror_r(errno, buf, 256);
00435         if ('\0' == buf[0])
00436         {
00437                 return *(String::Format("Error number %d", errno));
00438         }
00439         return String(buf);
00440 #else
00441         return String(strerror(errno));
00442 #endif
00443 #endif
00444 }
00445 
00446 int Environment::ProcessorCount()
00447 {
00448 #ifdef _WINDOWS
00449         SYSTEM_INFO si;
00450         ::GetSystemInfo(&si);
00451         return si.dwNumberOfProcessors;
00452 #else
00453         const char *procCpuInfo = "/proc/cpuinfo";
00454         if (File::Exists(procCpuInfo))
00455         {
00456                 Regex regex("^processor", RegexOptions::MULTILINE);
00457                 StringPtr cpuinfo = File::LoadText(procCpuInfo);
00458                 if (cpuinfo.IsNull())
00459                 {
00460                         return 1;
00461                 }
00462                 RefCountPtr<Array<StringPtr> > matches = regex.Matches(cpuinfo);
00463                 return matches->Count();
00464         }
00465         return 1;
00466 #endif
00467 }
00468