// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/sys_info.h" #include "base/basictypes.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/lazy_instance.h" #include "base/string_number_conversions.h" #include "base/string_tokenizer.h" #include "base/threading/thread_restrictions.h" #include <execinfo.h> namespace base { static const char* kLinuxStandardBaseVersionKeys[] = { "CHROMEOS_RELEASE_VERSION", "GOOGLE_RELEASE", "DISTRIB_RELEASE", NULL }; const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release"; struct ChromeOSVersionNumbers { ChromeOSVersionNumbers() : major_version(0), minor_version(0), bugfix_version(0), parsed(false) { } int32 major_version; int32 minor_version; int32 bugfix_version; bool parsed; }; static base::LazyInstance<ChromeOSVersionNumbers> g_chrome_os_version_numbers(base::LINKER_INITIALIZED); // static void SysInfo::OperatingSystemVersionNumbers(int32* major_version, int32* minor_version, int32* bugfix_version) { if (!g_chrome_os_version_numbers.Get().parsed) { // The other implementations of SysInfo don't block on the disk. // See http://code.google.com/p/chromium/issues/detail?id=60394 // Perhaps the caller ought to cache this? // Temporary allowing while we work the bug out. base::ThreadRestrictions::ScopedAllowIO allow_io; FilePath path(kLinuxStandardBaseReleaseFile); std::string contents; if (file_util::ReadFileToString(path, &contents)) { g_chrome_os_version_numbers.Get().parsed = true; ParseLsbRelease(contents, &(g_chrome_os_version_numbers.Get().major_version), &(g_chrome_os_version_numbers.Get().minor_version), &(g_chrome_os_version_numbers.Get().bugfix_version)); } } *major_version = g_chrome_os_version_numbers.Get().major_version; *minor_version = g_chrome_os_version_numbers.Get().minor_version; *bugfix_version = g_chrome_os_version_numbers.Get().bugfix_version; } // static std::string SysInfo::GetLinuxStandardBaseVersionKey() { return std::string(kLinuxStandardBaseVersionKeys[0]); } // static void SysInfo::ParseLsbRelease(const std::string& lsb_release, int32* major_version, int32* minor_version, int32* bugfix_version) { size_t version_key_index = std::string::npos; for (int i = 0; kLinuxStandardBaseVersionKeys[i] != NULL; ++i) { version_key_index = lsb_release.find(kLinuxStandardBaseVersionKeys[i]); if (std::string::npos != version_key_index) { break; } } if (std::string::npos == version_key_index) { return; } size_t start_index = lsb_release.find_first_of('=', version_key_index); start_index++; // Move past '='. size_t length = lsb_release.find_first_of('\n', start_index) - start_index; std::string version = lsb_release.substr(start_index, length); StringTokenizer tokenizer(version, "."); // TODO(rkc): Ignore the 0. here; fix this once we move Chrome OS version // numbers from the 0.xx.yyy.zz format to the xx.yyy.zz format. // Refer to http://code.google.com/p/chromium-os/issues/detail?id=15789 for (int i = 0; i < 4 && tokenizer.GetNext(); i++) { if (1 == i) { StringToInt(tokenizer.token_begin(), tokenizer.token_end(), major_version); *minor_version = *bugfix_version = 0; } else if (2 == i) { StringToInt(tokenizer.token_begin(), tokenizer.token_end(), minor_version); } else { // 3 == i StringToInt(tokenizer.token_begin(), tokenizer.token_end(), bugfix_version); } } } } // namespace base