Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/sys_info.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/file_path.h"
      9 #include "base/file_util.h"
     10 #include "base/lazy_instance.h"
     11 #include "base/string_number_conversions.h"
     12 #include "base/string_tokenizer.h"
     13 #include "base/threading/thread_restrictions.h"
     14 
     15 #include <execinfo.h>
     16 
     17 namespace base {
     18 
     19 static const char* kLinuxStandardBaseVersionKeys[] = {
     20   "CHROMEOS_RELEASE_VERSION",
     21   "GOOGLE_RELEASE",
     22   "DISTRIB_RELEASE",
     23   NULL
     24 };
     25 
     26 const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release";
     27 
     28 struct ChromeOSVersionNumbers {
     29   ChromeOSVersionNumbers()
     30       : major_version(0),
     31         minor_version(0),
     32         bugfix_version(0),
     33         parsed(false) {
     34   }
     35 
     36   int32 major_version;
     37   int32 minor_version;
     38   int32 bugfix_version;
     39   bool parsed;
     40 };
     41 
     42 static base::LazyInstance<ChromeOSVersionNumbers>
     43     g_chrome_os_version_numbers(base::LINKER_INITIALIZED);
     44 
     45 // static
     46 void SysInfo::OperatingSystemVersionNumbers(int32* major_version,
     47                                             int32* minor_version,
     48                                             int32* bugfix_version) {
     49   if (!g_chrome_os_version_numbers.Get().parsed) {
     50     // The other implementations of SysInfo don't block on the disk.
     51     // See http://code.google.com/p/chromium/issues/detail?id=60394
     52     // Perhaps the caller ought to cache this?
     53     // Temporary allowing while we work the bug out.
     54     base::ThreadRestrictions::ScopedAllowIO allow_io;
     55 
     56     FilePath path(kLinuxStandardBaseReleaseFile);
     57     std::string contents;
     58     if (file_util::ReadFileToString(path, &contents)) {
     59       g_chrome_os_version_numbers.Get().parsed = true;
     60       ParseLsbRelease(contents,
     61           &(g_chrome_os_version_numbers.Get().major_version),
     62           &(g_chrome_os_version_numbers.Get().minor_version),
     63           &(g_chrome_os_version_numbers.Get().bugfix_version));
     64     }
     65   }
     66   *major_version = g_chrome_os_version_numbers.Get().major_version;
     67   *minor_version = g_chrome_os_version_numbers.Get().minor_version;
     68   *bugfix_version = g_chrome_os_version_numbers.Get().bugfix_version;
     69 }
     70 
     71 // static
     72 std::string SysInfo::GetLinuxStandardBaseVersionKey() {
     73   return std::string(kLinuxStandardBaseVersionKeys[0]);
     74 }
     75 
     76 // static
     77 void SysInfo::ParseLsbRelease(const std::string& lsb_release,
     78                               int32* major_version,
     79                               int32* minor_version,
     80                               int32* bugfix_version) {
     81   size_t version_key_index = std::string::npos;
     82   for (int i = 0; kLinuxStandardBaseVersionKeys[i] != NULL; ++i) {
     83     version_key_index = lsb_release.find(kLinuxStandardBaseVersionKeys[i]);
     84     if (std::string::npos != version_key_index) {
     85       break;
     86     }
     87   }
     88   if (std::string::npos == version_key_index) {
     89     return;
     90   }
     91 
     92   size_t start_index = lsb_release.find_first_of('=', version_key_index);
     93   start_index++;  // Move past '='.
     94   size_t length = lsb_release.find_first_of('\n', start_index) - start_index;
     95   std::string version = lsb_release.substr(start_index, length);
     96   StringTokenizer tokenizer(version, ".");
     97   // TODO(rkc): Ignore the 0. here; fix this once we move Chrome OS version
     98   // numbers from the 0.xx.yyy.zz format to the xx.yyy.zz format.
     99   // Refer to http://code.google.com/p/chromium-os/issues/detail?id=15789
    100   for (int i = 0; i < 4 && tokenizer.GetNext(); i++) {
    101     if (1 == i) {
    102       StringToInt(tokenizer.token_begin(),
    103                   tokenizer.token_end(),
    104                   major_version);
    105       *minor_version = *bugfix_version = 0;
    106     } else if (2 == i) {
    107       StringToInt(tokenizer.token_begin(),
    108                   tokenizer.token_end(),
    109                   minor_version);
    110     } else {  // 3 == i
    111       StringToInt(tokenizer.token_begin(),
    112                   tokenizer.token_end(),
    113                   bugfix_version);
    114     }
    115   }
    116 }
    117 
    118 }  // namespace base
    119