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

Generated on Thu Jul 1 06:09:15 2010 for Second Life Viewer by  doxygen 1.4.7