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