diff options
Diffstat (limited to 'indra/llcommon/llsys.cpp')
-rw-r--r-- | indra/llcommon/llsys.cpp | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp new file mode 100644 index 0000000000..65fa4a5c9c --- /dev/null +++ b/indra/llcommon/llsys.cpp @@ -0,0 +1,534 @@ +/** + * @file llsys.cpp + * @brief Impelementation of the basic system query functions. + * + * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#include "linden_common.h" + +#include <iostream> +#include <zlib/zlib.h> +#include "processor.h" + +#if LL_DARWIN +#include <sys/sysctl.h> +#include <sys/utsname.h> +#elif LL_LINUX +#include <sys/utsname.h> +const char MEMINFO_FILE[] = "/proc/meminfo"; +const char CPUINFO_FILE[] = "/proc/cpuinfo"; +#endif + + +static const S32 CPUINFO_BUFFER_SIZE = 16383; +LLCPUInfo gSysCPU; + +LLOSInfo::LLOSInfo() : + mMajorVer(0), mMinorVer(0), mBuild(0), + mOSString("") +{ + +#if LL_WINDOWS + OSVERSIONINFOEX osvi; + BOOL bOsVersionInfoEx; + + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi))) + { + // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if(!GetVersionEx( (OSVERSIONINFO *) &osvi)) + return; + } + mMajorVer = osvi.dwMajorVersion; + mMinorVer = osvi.dwMinorVersion; + mBuild = osvi.dwBuildNumber; + + switch(osvi.dwPlatformId) + { + case VER_PLATFORM_WIN32_NT: + { + // Test for the product. + if(osvi.dwMajorVersion <= 4) + { + mOSString = "Microsoft Windows NT "; + } + else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) + { + mOSString = "Microsoft Windows 2000 "; + } + else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1) + { + mOSString = "Microsoft Windows XP "; + } + else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if(osvi.wProductType == VER_NT_WORKSTATION) + mOSString = "Microsoft Windows XP x64 Edition "; + else mOSString = "Microsoft Windows Server 2003 "; + } + else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) + { + if(osvi.wProductType == VER_NT_WORKSTATION) + mOSString = "Microsoft Windows Vista "; + else mOSString = "Microsoft Windows Vista Server "; + } + else // Use the registry on early versions of Windows NT. + { + HKEY hKey; + WCHAR szProductType[80]; + DWORD dwBufLen; + RegOpenKeyEx( HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions", + 0, KEY_QUERY_VALUE, &hKey ); + RegQueryValueEx( hKey, L"ProductType", NULL, NULL, + (LPBYTE) szProductType, &dwBufLen); + RegCloseKey( hKey ); + if ( lstrcmpi( L"WINNT", szProductType) == 0 ) + { + mOSString += "Professional "; + } + else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 ) + { + mOSString += "Server "; + } + else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 ) + { + mOSString += "Advanced Server "; + } + } + + std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion); + // Display version, service pack (if any), and build number. + char tmp[MAX_STRING]; /* Flawfinder: ignore */ + if(osvi.dwMajorVersion <= 4) + { + snprintf( + tmp, + sizeof(tmp), + "version %d.%d %s (Build %d)", + osvi.dwMajorVersion, + osvi.dwMinorVersion, + csdversion.c_str(), + (osvi.dwBuildNumber & 0xffff)); /* Flawfinder: ignore */ + } + else + { + snprintf( + tmp, + sizeof(tmp), + "%s (Build %d)", + csdversion.c_str(), + (osvi.dwBuildNumber & 0xffff)); /*Flawfinder: ignore*/ + } + mOSString += tmp; + } + break; + + case VER_PLATFORM_WIN32_WINDOWS: + // Test for the Windows 95 product family. + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + { + mOSString = "Microsoft Windows 95 "; + if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' ) + { + mOSString += "OSR2 "; + } + } + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + mOSString = "Microsoft Windows 98 "; + if ( osvi.szCSDVersion[1] == 'A' ) + { + mOSString += "SE "; + } + } + if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + { + mOSString = "Microsoft Windows Millennium Edition "; + } + break; + } +#else + struct utsname un; + if(0==uname(&un)) + { + mOSString.append(un.sysname); + mOSString.append(" "); + mOSString.append(un.release); + mOSString.append(" "); + mOSString.append(un.version); + mOSString.append(" "); + mOSString.append(un.machine); + } + else + { + mOSString.append("Unable to collect OS info"); + } +#endif + +} + +#ifndef LL_WINDOWS +// static +S32 LLOSInfo::getMaxOpenFiles() +{ + const S32 OPEN_MAX_GUESS = 256; + +#ifdef OPEN_MAX + static S32 open_max = OPEN_MAX; +#else + static S32 open_max = 0; +#endif + + if (0 == open_max) + { + // First time through. + errno = 0; + if ( (open_max = sysconf(_SC_OPEN_MAX)) < 0) + { + if (0 == errno) + { + // Indeterminate. + open_max = OPEN_MAX_GUESS; + } + else + { + llerrs << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << llendl; + } + } + } + return open_max; +} +#endif + +void LLOSInfo::stream(std::ostream& s) const +{ + s << mOSString; +} + +const std::string& LLOSInfo::getOSString() const +{ + return mOSString; +} + +const S32 STATUS_SIZE = 8192; + +//static +U32 LLOSInfo::getProcessVirtualSizeKB() +{ + U32 virtual_size = 0; +#if LL_WINDOWS +#endif +#if LL_LINUX + FILE *status_filep = LLFile::fopen("/proc/self/status", "r"); + S32 numRead = 0; + char buff[STATUS_SIZE]; /* Flawfinder: ignore */ + bzero(buff, STATUS_SIZE); + + rewind(status_filep); + fread(buff, 1, STATUS_SIZE-2, status_filep); + + // All these guys return numbers in KB + char *memp = strstr(buff, "VmSize:"); + if (memp) + { + numRead += sscanf(memp, "%*s %u", &virtual_size); + } + fclose(status_filep); +#endif + return virtual_size; +} + +//static +U32 LLOSInfo::getProcessResidentSizeKB() +{ + U32 resident_size = 0; +#if LL_WINDOWS +#endif +#if LL_LINUX + FILE *status_filep = LLFile::fopen("/proc/self/status", "r"); + if (status_filep != NULL) + { + S32 numRead = 0; + char buff[STATUS_SIZE]; /* Flawfinder: ignore */ + bzero(buff, STATUS_SIZE); + + rewind(status_filep); + fread(buff, 1, STATUS_SIZE-2, status_filep); + + // All these guys return numbers in KB + char *memp = strstr(buff, "VmRSS:"); + if (memp) + { + numRead += sscanf(memp, "%*s %u", &resident_size); + } + fclose(status_filep); + } +#endif + return resident_size; +} + +LLCPUInfo::LLCPUInfo() +{ + CProcessor proc; + const ProcessorInfo* info = proc.GetCPUInfo(); + mHasSSE = (info->_Ext.SSE_StreamingSIMD_Extensions != 0); + mHasSSE2 = (info->_Ext.SSE2_StreamingSIMD2_Extensions != 0); + mCPUMhz = (S32)(proc.GetCPUFrequency(50)/1000000.0); + mFamily.assign( info->strFamily ); +} + +std::string LLCPUInfo::getCPUString() const +{ + std::string cpu_string; + +#if LL_WINDOWS || LL_DARWIN + // gather machine information. + char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */ + CProcessor proc; + if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE)) + { + cpu_string.append(proc_buf); + } +#else + cpu_string.append("Can't get CPU information"); +#endif + + return cpu_string; +} + +std::string LLCPUInfo::getCPUStringTerse() const +{ + std::string cpu_string; + +#if LL_WINDOWS || LL_DARWIN + CProcessor proc; + const ProcessorInfo *info = proc.GetCPUInfo(); + + cpu_string.append(info->strBrandID); + + F64 freq = (F64)(S64)proc.GetCPUFrequency(50) / 1000000.f; + + // cpu speed is often way wrong, do a sanity check + if (freq < 10000.f && freq > 200.f ) + { + char tmp[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(tmp, sizeof(tmp), " (%.0f Mhz)", freq); /* Flawfinder: ignore */ + + cpu_string.append(tmp); + } +#else + cpu_string.append("Can't get terse CPU information"); +#endif + + return cpu_string; +} + +void LLCPUInfo::stream(std::ostream& s) const +{ +#if LL_WINDOWS || LL_DARWIN + // gather machine information. + char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */ + CProcessor proc; + if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE)) + { + s << proc_buf; + } + else + { + s << "Unable to collect processor info"; + } +#else + // *FIX: This works on linux. What will it do on other systems? + FILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "r"); /* Flawfinder: ignore */ + if(cpuinfo) + { + char line[MAX_STRING]; /* Flawfinder: ignore */ + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo)) + { + line[strlen(line)-1] = ' '; /*Flawfinder: ignore*/ + s << line; + } + fclose(cpuinfo); + } + else + { + s << "Unable to collect memory information"; + } +#endif +} + +LLMemoryInfo::LLMemoryInfo() +{ +} + +#if LL_LINUX +#include <unistd.h> +#include <sys/sysinfo.h> +#endif + +U32 LLMemoryInfo::getPhysicalMemory() const +{ +#if LL_WINDOWS + MEMORYSTATUS state; + state.dwLength = sizeof(state); + GlobalMemoryStatus(&state); + + return (U32)state.dwTotalPhys; + +#elif LL_DARWIN + // This might work on Linux as well. Someone check... + unsigned int phys = 0; + int mib[2] = { CTL_HW, HW_PHYSMEM }; + + size_t len = sizeof(phys); + sysctl(mib, 2, &phys, &len, NULL, 0); + + return phys; +#elif LL_LINUX + + return getpagesize() * get_phys_pages(); + +#else + return 0; + +#endif +} + +void LLMemoryInfo::stream(std::ostream& s) const +{ +#if LL_WINDOWS + MEMORYSTATUS state; + state.dwLength = sizeof(state); + GlobalMemoryStatus(&state); + + s << "Percent Memory use: " << (U32)state.dwMemoryLoad << '%' << std::endl; + s << "Total Physical Kb: " << (U32)state.dwTotalPhys/1024 << std::endl; + s << "Avail Physical Kb: " << (U32)state.dwAvailPhys/1024 << std::endl; + s << "Total page Kb: " << (U32)state.dwTotalPageFile/1024 << std::endl; + s << "Avail page Kb: " << (U32)state.dwAvailPageFile/1024 << std::endl; + s << "Total Virtual Kb: " << (U32)state.dwTotalVirtual/1024 << std::endl; + s << "Avail Virtual Kb: " << (U32)state.dwAvailVirtual/1024 << std::endl; +#elif LL_DARWIN + U64 phys = 0; + + size_t len = sizeof(phys); + + if(sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0) + { + s << "Total Physical Kb: " << phys/1024 << std::endl; + } + else + { + s << "Unable to collect memory information"; + } + +#else + // *FIX: This works on linux. What will it do on other systems? + FILE* meminfo = LLFile::fopen(MEMINFO_FILE,"r"); /* Flawfinder: ignore */ + if(meminfo) + { + char line[MAX_STRING]; /* Flawfinder: ignore */ + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, meminfo)) + { + line[strlen(line)-1] = ' '; /*Flawfinder: ignore*/ + s << line; + } + fclose(meminfo); + } + else + { + s << "Unable to collect memory information"; + } +#endif +} + +std::ostream& operator<<(std::ostream& s, const LLOSInfo& info) +{ + info.stream(s); + return s; +} + +std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info) +{ + info.stream(s); + return s; +} + +std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info) +{ + info.stream(s); + return s; +} + +BOOL gunzip_file(const char *srcfile, const char *dstfile) +{ + char tmpfile[LL_MAX_PATH]; /* Flawfinder: ignore */ + const S32 UNCOMPRESS_BUFFER_SIZE = 32768; + BOOL retval = FALSE; + gzFile src = NULL; + U8 buffer[UNCOMPRESS_BUFFER_SIZE]; + FILE *dst = NULL; + S32 bytes = 0; + (void *) strcpy(tmpfile, dstfile); /* Flawfinder: ignore */ + (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1); /* Flawfinder: ignore */ + src = gzopen(srcfile, "rb"); + if (! src) goto err; + dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */ + if (! dst) goto err; + do + { + bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE); + fwrite(buffer, sizeof(U8), bytes, dst); + } while(gzeof(src) == 0); + fclose(dst); + dst = NULL; + if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */ + retval = TRUE; +err: + if (src != NULL) gzclose(src); + if (dst != NULL) fclose(dst); + return retval; +} + +BOOL gzip_file(const char *srcfile, const char *dstfile) +{ + const S32 COMPRESS_BUFFER_SIZE = 32768; + char tmpfile[LL_MAX_PATH]; /* Flawfinder: ignore */ + BOOL retval = FALSE; + U8 buffer[COMPRESS_BUFFER_SIZE]; + gzFile dst = NULL; + FILE *src = NULL; + S32 bytes = 0; + (void *) strcpy(tmpfile, dstfile); /* Flawfinder: ignore */ + (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1); /* Flawfinder: ignore */ + dst = gzopen(tmpfile, "wb"); /* Flawfinder: ignore */ + if (! dst) goto err; + src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */ + if (! src) goto err; + + do + { + bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE,src); + gzwrite(dst, buffer, bytes); + } while(feof(src) == 0); + gzclose(dst); + dst = NULL; +#if LL_WINDOWS + // Rename in windows needs the dstfile to not exist. + LLFile::remove(dstfile); +#endif + if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */ + retval = TRUE; + err: + if (src != NULL) fclose(src); + if (dst != NULL) gzclose(dst); + return retval; +} |