clang  10.0.0git
Distro.cpp
Go to the documentation of this file.
1 //===--- Distro.cpp - Linux distribution detection support ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Driver/Distro.h"
10 #include "clang/Basic/LLVM.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/Support/ErrorOr.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/ADT/Triple.h"
17 
18 using namespace clang::driver;
19 using namespace clang;
20 
21 static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS,
22  const llvm::Triple &TargetOrHost) {
23  // If we don't target Linux, no need to check the distro. This saves a few
24  // OS calls.
25  if (!TargetOrHost.isOSLinux())
26  return Distro::UnknownDistro;
27 
28  // If the host is not running Linux, and we're backed by a real file system,
29  // no need to check the distro. This is the case where someone is
30  // cross-compiling from BSD or Windows to Linux, and it would be meaningless
31  // to try to figure out the "distro" of the non-Linux host.
33  llvm::vfs::getRealFileSystem();
34  llvm::Triple HostTriple(llvm::sys::getProcessTriple());
35  if (!HostTriple.isOSLinux() && &VFS == RealFS.get())
36  return Distro::UnknownDistro;
37 
38  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
39  VFS.getBufferForFile("/etc/lsb-release");
40  if (File) {
41  StringRef Data = File.get()->getBuffer();
43  Data.split(Lines, "\n");
45  for (StringRef Line : Lines)
46  if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
47  Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(17))
48  .Case("hardy", Distro::UbuntuHardy)
49  .Case("intrepid", Distro::UbuntuIntrepid)
50  .Case("jaunty", Distro::UbuntuJaunty)
51  .Case("karmic", Distro::UbuntuKarmic)
52  .Case("lucid", Distro::UbuntuLucid)
53  .Case("maverick", Distro::UbuntuMaverick)
54  .Case("natty", Distro::UbuntuNatty)
55  .Case("oneiric", Distro::UbuntuOneiric)
56  .Case("precise", Distro::UbuntuPrecise)
57  .Case("quantal", Distro::UbuntuQuantal)
58  .Case("raring", Distro::UbuntuRaring)
59  .Case("saucy", Distro::UbuntuSaucy)
60  .Case("trusty", Distro::UbuntuTrusty)
61  .Case("utopic", Distro::UbuntuUtopic)
62  .Case("vivid", Distro::UbuntuVivid)
63  .Case("wily", Distro::UbuntuWily)
64  .Case("xenial", Distro::UbuntuXenial)
65  .Case("yakkety", Distro::UbuntuYakkety)
66  .Case("zesty", Distro::UbuntuZesty)
67  .Case("artful", Distro::UbuntuArtful)
68  .Case("bionic", Distro::UbuntuBionic)
69  .Case("cosmic", Distro::UbuntuCosmic)
70  .Case("disco", Distro::UbuntuDisco)
71  .Case("eoan", Distro::UbuntuEoan)
72  .Case("focal", Distro::UbuntuFocal)
73  .Default(Distro::UnknownDistro);
74  if (Version != Distro::UnknownDistro)
75  return Version;
76  }
77 
78  File = VFS.getBufferForFile("/etc/redhat-release");
79  if (File) {
80  StringRef Data = File.get()->getBuffer();
81  if (Data.startswith("Fedora release"))
82  return Distro::Fedora;
83  if (Data.startswith("Red Hat Enterprise Linux") ||
84  Data.startswith("CentOS") ||
85  Data.startswith("Scientific Linux")) {
86  if (Data.find("release 7") != StringRef::npos)
87  return Distro::RHEL7;
88  else if (Data.find("release 6") != StringRef::npos)
89  return Distro::RHEL6;
90  else if (Data.find("release 5") != StringRef::npos)
91  return Distro::RHEL5;
92  }
93  return Distro::UnknownDistro;
94  }
95 
96  File = VFS.getBufferForFile("/etc/debian_version");
97  if (File) {
98  StringRef Data = File.get()->getBuffer();
99  // Contents: < major.minor > or < codename/sid >
100  int MajorVersion;
101  if (!Data.split('.').first.getAsInteger(10, MajorVersion)) {
102  switch (MajorVersion) {
103  case 5:
104  return Distro::DebianLenny;
105  case 6:
106  return Distro::DebianSqueeze;
107  case 7:
108  return Distro::DebianWheezy;
109  case 8:
110  return Distro::DebianJessie;
111  case 9:
112  return Distro::DebianStretch;
113  case 10:
114  return Distro::DebianBuster;
115  case 11:
116  return Distro::DebianBullseye;
117  default:
118  return Distro::UnknownDistro;
119  }
120  }
121  return llvm::StringSwitch<Distro::DistroType>(Data.split("\n").first)
122  .Case("squeeze/sid", Distro::DebianSqueeze)
123  .Case("wheezy/sid", Distro::DebianWheezy)
124  .Case("jessie/sid", Distro::DebianJessie)
125  .Case("stretch/sid", Distro::DebianStretch)
126  .Case("buster/sid", Distro::DebianBuster)
127  .Case("bullseye/sid", Distro::DebianBullseye)
128  .Default(Distro::UnknownDistro);
129  }
130 
131  File = VFS.getBufferForFile("/etc/SuSE-release");
132  if (File) {
133  StringRef Data = File.get()->getBuffer();
135  Data.split(Lines, "\n");
136  for (const StringRef& Line : Lines) {
137  if (!Line.trim().startswith("VERSION"))
138  continue;
139  std::pair<StringRef, StringRef> SplitLine = Line.split('=');
140  // Old versions have split VERSION and PATCHLEVEL
141  // Newer versions use VERSION = x.y
142  std::pair<StringRef, StringRef> SplitVer = SplitLine.second.trim().split('.');
143  int Version;
144 
145  // OpenSUSE/SLES 10 and older are not supported and not compatible
146  // with our rules, so just treat them as Distro::UnknownDistro.
147  if (!SplitVer.first.getAsInteger(10, Version) && Version > 10)
148  return Distro::OpenSUSE;
149  return Distro::UnknownDistro;
150  }
151  return Distro::UnknownDistro;
152  }
153 
154  if (VFS.exists("/etc/exherbo-release"))
155  return Distro::Exherbo;
156 
157  if (VFS.exists("/etc/alpine-release"))
158  return Distro::AlpineLinux;
159 
160  if (VFS.exists("/etc/arch-release"))
161  return Distro::ArchLinux;
162 
163  if (VFS.exists("/etc/gentoo-release"))
164  return Distro::Gentoo;
165 
166  return Distro::UnknownDistro;
167 }
168 
169 Distro::Distro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost)
170  : DistroVal(DetectDistro(VFS, TargetOrHost)) {}
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
const AnnotatedLine * Line
Distro()
Default constructor leaves the distribution unknown.
Definition: Distro.h:82
static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS, const llvm::Triple &TargetOrHost)
Definition: Distro.cpp:21
Dataflow Directional Tag Classes.