llsys.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "llsys.h"
00035 
00036 #include <iostream>
00037 #ifdef LL_STANDALONE
00038 # include <zlib.h>
00039 #else
00040 # include "zlib/zlib.h"
00041 #endif
00042 
00043 #include "llprocessor.h"
00044 
00045 #if LL_WINDOWS
00046 #       define WIN32_LEAN_AND_MEAN
00047 #       include <winsock2.h>
00048 #       include <windows.h>
00049 #elif LL_DARWIN
00050 #       include <errno.h>
00051 #       include <sys/sysctl.h>
00052 #       include <sys/utsname.h>
00053 #       include <stdint.h>
00054 #elif LL_LINUX
00055 #       include <errno.h>
00056 #       include <sys/utsname.h>
00057 #       include <unistd.h>
00058 #       include <sys/sysinfo.h>
00059 const char MEMINFO_FILE[] = "/proc/meminfo";
00060 const char CPUINFO_FILE[] = "/proc/cpuinfo";
00061 #endif
00062 
00063 
00064 static const S32 CPUINFO_BUFFER_SIZE = 16383;
00065 LLCPUInfo gSysCPU;
00066 
00067 LLOSInfo::LLOSInfo() :
00068         mMajorVer(0), mMinorVer(0), mBuild(0)
00069 {
00070 
00071 #if LL_WINDOWS
00072         OSVERSIONINFOEX osvi;
00073         BOOL bOsVersionInfoEx;
00074 
00075         // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
00076         ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
00077         osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
00078         if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
00079         {
00080                 // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
00081                 osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00082                 if(!GetVersionEx( (OSVERSIONINFO *) &osvi))
00083                         return;
00084         }
00085         mMajorVer = osvi.dwMajorVersion;
00086         mMinorVer = osvi.dwMinorVersion;
00087         mBuild = osvi.dwBuildNumber;
00088 
00089         switch(osvi.dwPlatformId)
00090         {
00091         case VER_PLATFORM_WIN32_NT:
00092                 {
00093                         // Test for the product.
00094                         if(osvi.dwMajorVersion <= 4)
00095                         {
00096                                 mOSStringSimple = "Microsoft Windows NT ";
00097                         }
00098                         else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
00099                         {
00100                                 mOSStringSimple = "Microsoft Windows 2000 ";
00101                         }
00102                         else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1)
00103                         {
00104                                 mOSStringSimple = "Microsoft Windows XP ";
00105                         }
00106                         else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
00107                         {
00108                                  if(osvi.wProductType == VER_NT_WORKSTATION)
00109                                         mOSStringSimple = "Microsoft Windows XP x64 Edition ";
00110                                  else
00111                                          mOSStringSimple = "Microsoft Windows Server 2003 ";
00112                         }
00113                         else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
00114                         {
00115                                  if(osvi.wProductType == VER_NT_WORKSTATION)
00116                                         mOSStringSimple = "Microsoft Windows Vista ";
00117                                  else mOSStringSimple = "Microsoft Windows Vista Server ";
00118                         }
00119                         else   // Use the registry on early versions of Windows NT.
00120                         {
00121                                 HKEY hKey;
00122                                 WCHAR szProductType[80];
00123                                 DWORD dwBufLen;
00124                                 RegOpenKeyEx( HKEY_LOCAL_MACHINE,
00125                                                         L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
00126                                                         0, KEY_QUERY_VALUE, &hKey );
00127                                 RegQueryValueEx( hKey, L"ProductType", NULL, NULL,
00128                                                                 (LPBYTE) szProductType, &dwBufLen);
00129                                 RegCloseKey( hKey );
00130                                 if ( lstrcmpi( L"WINNT", szProductType) == 0 )
00131                                 {
00132                                         mOSStringSimple += "Professional ";
00133                                 }
00134                                 else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 )
00135                                 {
00136                                         mOSStringSimple += "Server ";
00137                                 }
00138                                 else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 )
00139                                 {
00140                                         mOSStringSimple += "Advanced Server ";
00141                                 }
00142                         }
00143 
00144                         std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion);
00145                         // Display version, service pack (if any), and build number.
00146                         char tmp[MAX_STRING];           /* Flawfinder: ignore */
00147                         if(osvi.dwMajorVersion <= 4)
00148                         {
00149                                 snprintf(       /* Flawfinder: ignore */
00150                                         tmp,
00151                                         sizeof(tmp),
00152                                         "version %d.%d %s (Build %d)",
00153                                         osvi.dwMajorVersion,
00154                                         osvi.dwMinorVersion,
00155                                         csdversion.c_str(),
00156                                         (osvi.dwBuildNumber & 0xffff));
00157                         }
00158                         else
00159                         {
00160                                 snprintf(       /* Flawfinder: ignore */
00161                                         tmp,
00162                                         sizeof(tmp),
00163                                         "%s (Build %d)",
00164                                         csdversion.c_str(),
00165                                         (osvi.dwBuildNumber & 0xffff));  
00166                         }
00167                         mOSString = mOSStringSimple + tmp;
00168                 }
00169                 break;
00170 
00171         case VER_PLATFORM_WIN32_WINDOWS:
00172                 // Test for the Windows 95 product family.
00173                 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
00174                 {
00175                         mOSStringSimple = "Microsoft Windows 95 ";
00176                         if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
00177                         {
00178                 mOSStringSimple += "OSR2 ";
00179                         }
00180                 } 
00181                 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
00182                 {
00183                         mOSStringSimple = "Microsoft Windows 98 ";
00184                         if ( osvi.szCSDVersion[1] == 'A' )
00185                         {
00186                 mOSStringSimple += "SE ";
00187                         }
00188                 } 
00189                 if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
00190                 {
00191                         mOSStringSimple = "Microsoft Windows Millennium Edition ";
00192                 }
00193                 mOSString = mOSStringSimple;
00194                 break;
00195         }
00196 #else
00197         struct utsname un;
00198         if(uname(&un) != -1)
00199         {
00200                 mOSStringSimple.append(un.sysname);
00201                 mOSStringSimple.append(" ");
00202                 mOSStringSimple.append(un.release);
00203 
00204                 mOSString = mOSStringSimple;
00205                 mOSString.append(" ");
00206                 mOSString.append(un.version);
00207                 mOSString.append(" ");
00208                 mOSString.append(un.machine);
00209 
00210                 // Simplify 'Simple'
00211                 std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
00212                 if (ostype == "Darwin")
00213                 {
00214                         // Only care about major Darwin versions, truncate at first '.'
00215                         S32 idx1 = mOSStringSimple.find_first_of(".", 0);
00216                         std::string simple = mOSStringSimple.substr(0, idx1);
00217                         if (simple.length() > 0)
00218                                 mOSStringSimple = simple;
00219                 }
00220                 else if (ostype == "Linux")
00221                 {
00222                         // Only care about major and minor Linux versions, truncate at second '.'
00223                         S32 idx1 = mOSStringSimple.find_first_of(".", 0);
00224                         S32 idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
00225                         std::string simple = mOSStringSimple.substr(0, idx2);
00226                         if (simple.length() > 0)
00227                                 mOSStringSimple = simple;
00228                 }
00229         }
00230         else
00231         {
00232                 mOSStringSimple.append("Unable to collect OS info");
00233                 mOSString = mOSStringSimple;
00234         }
00235 #endif
00236 
00237 }
00238 
00239 #ifndef LL_WINDOWS
00240 // static
00241 S32 LLOSInfo::getMaxOpenFiles()
00242 {
00243         const S32 OPEN_MAX_GUESS = 256;
00244 
00245 #ifdef  OPEN_MAX
00246         static S32 open_max = OPEN_MAX;
00247 #else
00248         static S32 open_max = 0;
00249 #endif
00250 
00251         if (0 == open_max)
00252         {
00253                 // First time through.
00254                 errno = 0;
00255                 if ( (open_max = sysconf(_SC_OPEN_MAX)) < 0)
00256                 {
00257                         if (0 == errno)
00258                         {
00259                                 // Indeterminate.
00260                                 open_max = OPEN_MAX_GUESS;
00261                         }
00262                         else
00263                         {
00264                                 llerrs << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << llendl;
00265                         }
00266                 }
00267         }
00268         return open_max;
00269 }
00270 #endif
00271 
00272 void LLOSInfo::stream(std::ostream& s) const
00273 {
00274         s << mOSString;
00275 }
00276 
00277 const std::string& LLOSInfo::getOSString() const
00278 {
00279         return mOSString;
00280 }
00281 
00282 const std::string& LLOSInfo::getOSStringSimple() const
00283 {
00284         return mOSStringSimple;
00285 }
00286 
00287 const S32 STATUS_SIZE = 8192;
00288 
00289 //static
00290 U32 LLOSInfo::getProcessVirtualSizeKB()
00291 {
00292         U32 virtual_size = 0;
00293 #if LL_WINDOWS
00294 #endif
00295 #if LL_LINUX
00296         LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
00297         S32 numRead = 0;                
00298         char buff[STATUS_SIZE];         /* Flawfinder: ignore */
00299 
00300         size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
00301         buff[nbytes] = '\0';
00302 
00303         // All these guys return numbers in KB
00304         char *memp = strstr(buff, "VmSize:");
00305         if (memp)
00306         {
00307                 numRead += sscanf(memp, "%*s %u", &virtual_size);
00308         }
00309         fclose(status_filep);
00310 #elif LL_SOLARIS
00311         char proc_ps[LL_MAX_PATH];
00312         sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
00313         int proc_fd = -1;
00314         if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
00315                 llwarns << "unable to open " << proc_ps << llendl;
00316                 return 0;
00317         }
00318         psinfo_t proc_psinfo;
00319         if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
00320                 llwarns << "Unable to read " << proc_ps << llendl;
00321                 close(proc_fd);
00322                 return 0;
00323         }
00324 
00325         close(proc_fd);
00326 
00327         virtual_size = proc_psinfo.pr_size;
00328 #endif
00329         return virtual_size;
00330 }
00331 
00332 //static
00333 U32 LLOSInfo::getProcessResidentSizeKB()
00334 {
00335         U32 resident_size = 0;
00336 #if LL_WINDOWS
00337 #endif
00338 #if LL_LINUX
00339         LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
00340         if (status_filep != NULL)
00341         {
00342                 S32 numRead = 0;
00343                 char buff[STATUS_SIZE];         /* Flawfinder: ignore */
00344 
00345                 size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep);
00346                 buff[nbytes] = '\0';
00347 
00348                 // All these guys return numbers in KB
00349                 char *memp = strstr(buff, "VmRSS:");
00350                 if (memp)
00351                 {
00352                         numRead += sscanf(memp, "%*s %u", &resident_size);
00353                 }
00354                 fclose(status_filep);
00355         }
00356 #elif LL_SOLARIS
00357         char proc_ps[LL_MAX_PATH];
00358         sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
00359         int proc_fd = -1;
00360         if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
00361                 llwarns << "unable to open " << proc_ps << llendl;
00362                 return 0;
00363         }
00364         psinfo_t proc_psinfo;
00365         if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
00366                 llwarns << "Unable to read " << proc_ps << llendl;
00367                 close(proc_fd);
00368                 return 0;
00369         }
00370 
00371         close(proc_fd);
00372 
00373         resident_size = proc_psinfo.pr_rssize;
00374 #endif
00375         return resident_size;
00376 }
00377 
00378 LLCPUInfo::LLCPUInfo()
00379 {
00380         std::ostringstream out;
00381         CProcessor proc;
00382         const ProcessorInfo* info = proc.GetCPUInfo();
00383         // proc.WriteInfoTextFile("procInfo.txt");
00384         mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
00385         mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
00386         mHasAltivec = info->_Ext.Altivec_Extensions;
00387         mCPUMhz = (S32)(proc.GetCPUFrequency(50)/1000000.0);
00388         mFamily.assign( info->strFamily );
00389         mCPUString = "Unknown";
00390 
00391 #if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
00392         out << proc.strCPUName;
00393         if (200 < mCPUMhz && mCPUMhz < 10000)           // *NOTE: cpu speed is often way wrong, do a sanity check
00394         {
00395                 out << " (" << mCPUMhz << " MHz)";
00396         }
00397         mCPUString = out.str();
00398         
00399 #elif LL_LINUX
00400         std::map< LLString, LLString > cpuinfo;
00401         LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
00402         if(cpuinfo_fp)
00403         {
00404                 char line[MAX_STRING];
00405                 memset(line, 0, MAX_STRING);
00406                 while(fgets(line, MAX_STRING, cpuinfo_fp))
00407                 {
00408                         // /proc/cpuinfo on Linux looks like:
00409                         // name\t*: value\n
00410                         char* tabspot = strchr( line, '\t' );
00411                         if (tabspot == NULL)
00412                                 continue;
00413                         char* colspot = strchr( tabspot, ':' );
00414                         if (colspot == NULL)
00415                                 continue;
00416                         char* spacespot = strchr( colspot, ' ' );
00417                         if (spacespot == NULL)
00418                                 continue;
00419                         char* nlspot = strchr( line, '\n' );
00420                         if (nlspot == NULL)
00421                                 nlspot = line + strlen( line ); // Fallback to terminating NUL
00422                         std::string linename( line, tabspot );
00423                         LLString llinename(linename);
00424                         LLString::toLower(llinename);
00425                         std::string lineval( spacespot + 1, nlspot );
00426                         cpuinfo[ llinename ] = lineval;
00427                 }
00428                 fclose(cpuinfo_fp);
00429         }
00430 # if LL_X86
00431         LLString flags = " " + cpuinfo["flags"] + " ";
00432         LLString::toLower(flags);
00433         mHasSSE = ( flags.find( " sse " ) != std::string::npos );
00434         mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos );
00435         
00436         F64 mhz;
00437         if (LLString::convertToF64(cpuinfo["cpu mhz"], mhz)
00438             && 200.0 < mhz && mhz < 10000.0)
00439         {
00440                 mCPUMhz = (S32)llrint(mhz);
00441         }
00442         if (!cpuinfo["model name"].empty())
00443                 mCPUString = cpuinfo["model name"];
00444 # endif // LL_X86
00445 #endif // LL_LINUX
00446 }
00447 
00448 bool LLCPUInfo::hasAltivec() const
00449 {
00450         return mHasAltivec;
00451 }
00452 
00453 bool LLCPUInfo::hasSSE() const
00454 {
00455         return mHasSSE;
00456 }
00457 
00458 bool LLCPUInfo::hasSSE2() const
00459 {
00460         return mHasSSE2;
00461 }
00462 
00463 S32 LLCPUInfo::getMhz() const
00464 {
00465         return mCPUMhz;
00466 }
00467 
00468 std::string LLCPUInfo::getCPUString() const
00469 {
00470         return mCPUString;
00471 }
00472 
00473 void LLCPUInfo::stream(std::ostream& s) const
00474 {
00475 #if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
00476         // gather machine information.
00477         char proc_buf[CPUINFO_BUFFER_SIZE];             /* Flawfinder: ignore */
00478         CProcessor proc;
00479         if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE))
00480         {
00481                 s << proc_buf;
00482         }
00483         else
00484         {
00485                 s << "Unable to collect processor information" << std::endl;
00486         }
00487 #else
00488         // *NOTE: This works on linux. What will it do on other systems?
00489         LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
00490         if(cpuinfo)
00491         {
00492                 char line[MAX_STRING];
00493                 memset(line, 0, MAX_STRING);
00494                 while(fgets(line, MAX_STRING, cpuinfo))
00495                 {
00496                         line[strlen(line)-1] = ' ';
00497                         s << line;
00498                 }
00499                 fclose(cpuinfo);
00500                 s << std::endl;
00501         }
00502         else
00503         {
00504                 s << "Unable to collect processor information" << std::endl;
00505         }
00506 #endif
00507         // These are interesting as they reflect our internal view of the
00508         // CPU's attributes regardless of platform
00509         s << "->mHasSSE:     " << (U32)mHasSSE << std::endl;
00510         s << "->mHasSSE2:    " << (U32)mHasSSE2 << std::endl;
00511         s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
00512         s << "->mCPUMhz:     " << mCPUMhz << std::endl;
00513         s << "->mCPUString:  " << mCPUString << std::endl;
00514 }
00515 
00516 LLMemoryInfo::LLMemoryInfo()
00517 {
00518 }
00519 
00520 #if LL_WINDOWS
00521 static U32 LLMemoryAdjustKBResult(U32 inKB)
00522 {
00523         // Moved this here from llfloaterabout.cpp
00524 
00526         // For some reason, the reported amount of memory is always wrong.
00527         // The original adjustment assumes it's always off by one meg, however
00528         // errors of as much as 2520 KB have been observed in the value
00529         // returned from the GetMemoryStatusEx function.  Here we keep the
00530         // original adjustment from llfoaterabout.cpp until this can be
00531         // fixed somehow.
00532         inKB += 1024;
00533 
00534         return inKB;
00535 }
00536 #endif
00537 
00538 U32 LLMemoryInfo::getPhysicalMemoryKB() const
00539 {
00540 #if LL_WINDOWS
00541         MEMORYSTATUSEX state;
00542         state.dwLength = sizeof(state);
00543         GlobalMemoryStatusEx(&state);
00544 
00545         return LLMemoryAdjustKBResult((U32)(state.ullTotalPhys >> 10));
00546 
00547 #elif LL_DARWIN
00548         // This might work on Linux as well.  Someone check...
00549         uint64_t phys = 0;
00550         int mib[2] = { CTL_HW, HW_MEMSIZE };
00551 
00552         size_t len = sizeof(phys);      
00553         sysctl(mib, 2, &phys, &len, NULL, 0);
00554         
00555         return (U32)(phys >> 10);
00556 
00557 #elif LL_LINUX
00558         U64 phys = 0;
00559         phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
00560         return (U32)(phys >> 10);
00561 
00562 #elif LL_SOLARIS
00563         U64 phys = 0;
00564         phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
00565         return (U32)(phys >> 10);
00566 
00567 #else
00568         return 0;
00569 
00570 #endif
00571 }
00572 
00573 U32 LLMemoryInfo::getPhysicalMemoryClamped() const
00574 {
00575         // Return the total physical memory in bytes, but clamp it
00576         // to no more than U32_MAX
00577         
00578         U32 phys_kb = getPhysicalMemoryKB();
00579         if (phys_kb >= 4194304 /* 4GB in KB */)
00580         {
00581                 return U32_MAX;
00582         }
00583         else
00584         {
00585                 return phys_kb << 10;
00586         }
00587 }
00588 
00589 void LLMemoryInfo::stream(std::ostream& s) const
00590 {
00591 #if LL_WINDOWS
00592         MEMORYSTATUSEX state;
00593         state.dwLength = sizeof(state);
00594         GlobalMemoryStatusEx(&state);
00595 
00596         s << "Percent Memory use: " << (U32)state.dwMemoryLoad << '%' << std::endl;
00597         s << "Total Physical KB:  " << (U32)(state.ullTotalPhys/1024) << std::endl;
00598         s << "Avail Physical KB:  " << (U32)(state.ullAvailPhys/1024) << std::endl;
00599         s << "Total page KB:      " << (U32)(state.ullTotalPageFile/1024) << std::endl;
00600         s << "Avail page KB:      " << (U32)(state.ullAvailPageFile/1024) << std::endl;
00601         s << "Total Virtual KB:   " << (U32)(state.ullTotalVirtual/1024) << std::endl;
00602         s << "Avail Virtual KB:   " << (U32)(state.ullAvailVirtual/1024) << std::endl;
00603 #elif LL_DARWIN
00604         uint64_t phys = 0;
00605 
00606         size_t len = sizeof(phys);      
00607         
00608         if(sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0)
00609         {
00610                 s << "Total Physical KB:  " << phys/1024 << std::endl;
00611         }
00612         else
00613         {
00614                 s << "Unable to collect memory information";
00615         }
00616 #elif LL_SOLARIS
00617         U64 phys = 0;
00618 
00619         phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024);
00620 
00621         s << "Total Physical KB:  " << phys << std::endl;
00622 #else
00623         // *NOTE: This works on linux. What will it do on other systems?
00624         LLFILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb");
00625         if(meminfo)
00626         {
00627                 char line[MAX_STRING];          /* Flawfinder: ignore */
00628                 memset(line, 0, MAX_STRING);
00629                 while(fgets(line, MAX_STRING, meminfo))
00630                 {
00631                         line[strlen(line)-1] = ' ';              /*Flawfinder: ignore*/
00632                         s << line;
00633                 }
00634                 fclose(meminfo);
00635         }
00636         else
00637         {
00638                 s << "Unable to collect memory information";
00639         }
00640 #endif
00641 }
00642 
00643 std::ostream& operator<<(std::ostream& s, const LLOSInfo& info)
00644 {
00645         info.stream(s);
00646         return s;
00647 }
00648 
00649 std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info)
00650 {
00651         info.stream(s);
00652         return s;
00653 }
00654 
00655 std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info)
00656 {
00657         info.stream(s);
00658         return s;
00659 }
00660 
00661 BOOL gunzip_file(const char *srcfile, const char *dstfile)
00662 {
00663         char tmpfile[LL_MAX_PATH];              /* Flawfinder: ignore */
00664         const S32 UNCOMPRESS_BUFFER_SIZE = 32768;
00665         BOOL retval = FALSE;
00666         gzFile src = NULL;
00667         U8 buffer[UNCOMPRESS_BUFFER_SIZE];
00668         LLFILE *dst = NULL;
00669         S32 bytes = 0;
00670         (void *) strcpy(tmpfile, dstfile);              /* Flawfinder: ignore */
00671         (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1);          /* Flawfinder: ignore */
00672         src = gzopen(srcfile, "rb");
00673         if (! src) goto err;
00674         dst = LLFile::fopen(tmpfile, "wb");             /* Flawfinder: ignore */
00675         if (! dst) goto err;
00676         do
00677         {
00678                 bytes = gzread(src, buffer, UNCOMPRESS_BUFFER_SIZE);
00679                 size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
00680                 if (nwrit < (size_t) bytes)
00681                 {
00682                         llwarns << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << llendl;
00683                         goto err;
00684                 }
00685         } while(gzeof(src) == 0);
00686         fclose(dst); 
00687         dst = NULL;     
00688         if (LLFile::rename(tmpfile, dstfile) == -1) goto err;           /* Flawfinder: ignore */
00689         retval = TRUE;
00690 err:
00691         if (src != NULL) gzclose(src);
00692         if (dst != NULL) fclose(dst);
00693         return retval;
00694 }
00695 
00696 BOOL gzip_file(const char *srcfile, const char *dstfile)
00697 {
00698         const S32 COMPRESS_BUFFER_SIZE = 32768;
00699         char tmpfile[LL_MAX_PATH];              /* Flawfinder: ignore */
00700         BOOL retval = FALSE;
00701         U8 buffer[COMPRESS_BUFFER_SIZE];
00702         gzFile dst = NULL;
00703         LLFILE *src = NULL;
00704         S32 bytes = 0;
00705         (void *) strcpy(tmpfile, dstfile);              /* Flawfinder: ignore */
00706         (void *) strncat(tmpfile, ".t", sizeof(tmpfile) - strlen(tmpfile) -1);          /* Flawfinder: ignore */
00707         dst = gzopen(tmpfile, "wb");            /* Flawfinder: ignore */
00708         if (! dst) goto err;
00709         src = LLFile::fopen(srcfile, "rb");             /* Flawfinder: ignore */
00710         if (! src) goto err;
00711 
00712         do
00713         {
00714                 bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE,src);
00715                 gzwrite(dst, buffer, bytes);
00716         } while(feof(src) == 0);
00717         gzclose(dst);
00718         dst = NULL;
00719 #if LL_WINDOWS
00720         // Rename in windows needs the dstfile to not exist.
00721         LLFile::remove(dstfile);
00722 #endif
00723         if (LLFile::rename(tmpfile, dstfile) == -1) goto err;           /* Flawfinder: ignore */
00724         retval = TRUE;
00725  err:
00726         if (src != NULL) fclose(src);
00727         if (dst != NULL) gzclose(dst);
00728         return retval;
00729 }

Generated on Fri May 16 08:32:09 2008 for SecondLife by  doxygen 1.5.5