Distro.cpp revision 1.1 1 1.1 joerg //===--- Distro.cpp - Linux distribution detection support ------*- C++ -*-===//
2 1.1 joerg //
3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information.
5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 1.1 joerg //
7 1.1 joerg //===----------------------------------------------------------------------===//
8 1.1 joerg
9 1.1 joerg #include "clang/Driver/Distro.h"
10 1.1 joerg #include "clang/Basic/LLVM.h"
11 1.1 joerg #include "llvm/ADT/SmallVector.h"
12 1.1 joerg #include "llvm/ADT/StringRef.h"
13 1.1 joerg #include "llvm/ADT/StringSwitch.h"
14 1.1 joerg #include "llvm/Support/ErrorOr.h"
15 1.1 joerg #include "llvm/Support/MemoryBuffer.h"
16 1.1 joerg
17 1.1 joerg using namespace clang::driver;
18 1.1 joerg using namespace clang;
19 1.1 joerg
20 1.1 joerg static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) {
21 1.1 joerg llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
22 1.1 joerg VFS.getBufferForFile("/etc/lsb-release");
23 1.1 joerg if (File) {
24 1.1 joerg StringRef Data = File.get()->getBuffer();
25 1.1 joerg SmallVector<StringRef, 16> Lines;
26 1.1 joerg Data.split(Lines, "\n");
27 1.1 joerg Distro::DistroType Version = Distro::UnknownDistro;
28 1.1 joerg for (StringRef Line : Lines)
29 1.1 joerg if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
30 1.1 joerg Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(17))
31 1.1 joerg .Case("hardy", Distro::UbuntuHardy)
32 1.1 joerg .Case("intrepid", Distro::UbuntuIntrepid)
33 1.1 joerg .Case("jaunty", Distro::UbuntuJaunty)
34 1.1 joerg .Case("karmic", Distro::UbuntuKarmic)
35 1.1 joerg .Case("lucid", Distro::UbuntuLucid)
36 1.1 joerg .Case("maverick", Distro::UbuntuMaverick)
37 1.1 joerg .Case("natty", Distro::UbuntuNatty)
38 1.1 joerg .Case("oneiric", Distro::UbuntuOneiric)
39 1.1 joerg .Case("precise", Distro::UbuntuPrecise)
40 1.1 joerg .Case("quantal", Distro::UbuntuQuantal)
41 1.1 joerg .Case("raring", Distro::UbuntuRaring)
42 1.1 joerg .Case("saucy", Distro::UbuntuSaucy)
43 1.1 joerg .Case("trusty", Distro::UbuntuTrusty)
44 1.1 joerg .Case("utopic", Distro::UbuntuUtopic)
45 1.1 joerg .Case("vivid", Distro::UbuntuVivid)
46 1.1 joerg .Case("wily", Distro::UbuntuWily)
47 1.1 joerg .Case("xenial", Distro::UbuntuXenial)
48 1.1 joerg .Case("yakkety", Distro::UbuntuYakkety)
49 1.1 joerg .Case("zesty", Distro::UbuntuZesty)
50 1.1 joerg .Case("artful", Distro::UbuntuArtful)
51 1.1 joerg .Case("bionic", Distro::UbuntuBionic)
52 1.1 joerg .Case("cosmic", Distro::UbuntuCosmic)
53 1.1 joerg .Case("disco", Distro::UbuntuDisco)
54 1.1 joerg .Case("eoan", Distro::UbuntuEoan)
55 1.1 joerg .Default(Distro::UnknownDistro);
56 1.1 joerg if (Version != Distro::UnknownDistro)
57 1.1 joerg return Version;
58 1.1 joerg }
59 1.1 joerg
60 1.1 joerg File = VFS.getBufferForFile("/etc/redhat-release");
61 1.1 joerg if (File) {
62 1.1 joerg StringRef Data = File.get()->getBuffer();
63 1.1 joerg if (Data.startswith("Fedora release"))
64 1.1 joerg return Distro::Fedora;
65 1.1 joerg if (Data.startswith("Red Hat Enterprise Linux") ||
66 1.1 joerg Data.startswith("CentOS") ||
67 1.1 joerg Data.startswith("Scientific Linux")) {
68 1.1 joerg if (Data.find("release 7") != StringRef::npos)
69 1.1 joerg return Distro::RHEL7;
70 1.1 joerg else if (Data.find("release 6") != StringRef::npos)
71 1.1 joerg return Distro::RHEL6;
72 1.1 joerg else if (Data.find("release 5") != StringRef::npos)
73 1.1 joerg return Distro::RHEL5;
74 1.1 joerg }
75 1.1 joerg return Distro::UnknownDistro;
76 1.1 joerg }
77 1.1 joerg
78 1.1 joerg File = VFS.getBufferForFile("/etc/debian_version");
79 1.1 joerg if (File) {
80 1.1 joerg StringRef Data = File.get()->getBuffer();
81 1.1 joerg // Contents: < major.minor > or < codename/sid >
82 1.1 joerg int MajorVersion;
83 1.1 joerg if (!Data.split('.').first.getAsInteger(10, MajorVersion)) {
84 1.1 joerg switch (MajorVersion) {
85 1.1 joerg case 5:
86 1.1 joerg return Distro::DebianLenny;
87 1.1 joerg case 6:
88 1.1 joerg return Distro::DebianSqueeze;
89 1.1 joerg case 7:
90 1.1 joerg return Distro::DebianWheezy;
91 1.1 joerg case 8:
92 1.1 joerg return Distro::DebianJessie;
93 1.1 joerg case 9:
94 1.1 joerg return Distro::DebianStretch;
95 1.1 joerg case 10:
96 1.1 joerg return Distro::DebianBuster;
97 1.1 joerg case 11:
98 1.1 joerg return Distro::DebianBullseye;
99 1.1 joerg default:
100 1.1 joerg return Distro::UnknownDistro;
101 1.1 joerg }
102 1.1 joerg }
103 1.1 joerg return llvm::StringSwitch<Distro::DistroType>(Data.split("\n").first)
104 1.1 joerg .Case("squeeze/sid", Distro::DebianSqueeze)
105 1.1 joerg .Case("wheezy/sid", Distro::DebianWheezy)
106 1.1 joerg .Case("jessie/sid", Distro::DebianJessie)
107 1.1 joerg .Case("stretch/sid", Distro::DebianStretch)
108 1.1 joerg .Case("buster/sid", Distro::DebianBuster)
109 1.1 joerg .Case("bullseye/sid", Distro::DebianBullseye)
110 1.1 joerg .Default(Distro::UnknownDistro);
111 1.1 joerg }
112 1.1 joerg
113 1.1 joerg File = VFS.getBufferForFile("/etc/SuSE-release");
114 1.1 joerg if (File) {
115 1.1 joerg StringRef Data = File.get()->getBuffer();
116 1.1 joerg SmallVector<StringRef, 8> Lines;
117 1.1 joerg Data.split(Lines, "\n");
118 1.1 joerg for (const StringRef& Line : Lines) {
119 1.1 joerg if (!Line.trim().startswith("VERSION"))
120 1.1 joerg continue;
121 1.1 joerg std::pair<StringRef, StringRef> SplitLine = Line.split('=');
122 1.1 joerg // Old versions have split VERSION and PATCHLEVEL
123 1.1 joerg // Newer versions use VERSION = x.y
124 1.1 joerg std::pair<StringRef, StringRef> SplitVer = SplitLine.second.trim().split('.');
125 1.1 joerg int Version;
126 1.1 joerg
127 1.1 joerg // OpenSUSE/SLES 10 and older are not supported and not compatible
128 1.1 joerg // with our rules, so just treat them as Distro::UnknownDistro.
129 1.1 joerg if (!SplitVer.first.getAsInteger(10, Version) && Version > 10)
130 1.1 joerg return Distro::OpenSUSE;
131 1.1 joerg return Distro::UnknownDistro;
132 1.1 joerg }
133 1.1 joerg return Distro::UnknownDistro;
134 1.1 joerg }
135 1.1 joerg
136 1.1 joerg if (VFS.exists("/etc/exherbo-release"))
137 1.1 joerg return Distro::Exherbo;
138 1.1 joerg
139 1.1 joerg if (VFS.exists("/etc/alpine-release"))
140 1.1 joerg return Distro::AlpineLinux;
141 1.1 joerg
142 1.1 joerg if (VFS.exists("/etc/arch-release"))
143 1.1 joerg return Distro::ArchLinux;
144 1.1 joerg
145 1.1 joerg if (VFS.exists("/etc/gentoo-release"))
146 1.1 joerg return Distro::Gentoo;
147 1.1 joerg
148 1.1 joerg return Distro::UnknownDistro;
149 1.1 joerg }
150 1.1 joerg
151 1.1 joerg Distro::Distro(llvm::vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}
152