aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/Distro.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/Distro.cpp')
-rw-r--r--lib/Driver/Distro.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/lib/Driver/Distro.cpp b/lib/Driver/Distro.cpp
new file mode 100644
index 000000000000..d305b179449f
--- /dev/null
+++ b/lib/Driver/Distro.cpp
@@ -0,0 +1,134 @@
+//===--- Distro.cpp - Linux distribution detection support ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Distro.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace clang::driver;
+using namespace clang;
+
+static Distro::DistroType DetectDistro(vfs::FileSystem &VFS) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+ VFS.getBufferForFile("/etc/lsb-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ SmallVector<StringRef, 16> Lines;
+ Data.split(Lines, "\n");
+ Distro::DistroType Version = Distro::UnknownDistro;
+ for (StringRef Line : Lines)
+ if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME="))
+ Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(17))
+ .Case("hardy", Distro::UbuntuHardy)
+ .Case("intrepid", Distro::UbuntuIntrepid)
+ .Case("jaunty", Distro::UbuntuJaunty)
+ .Case("karmic", Distro::UbuntuKarmic)
+ .Case("lucid", Distro::UbuntuLucid)
+ .Case("maverick", Distro::UbuntuMaverick)
+ .Case("natty", Distro::UbuntuNatty)
+ .Case("oneiric", Distro::UbuntuOneiric)
+ .Case("precise", Distro::UbuntuPrecise)
+ .Case("quantal", Distro::UbuntuQuantal)
+ .Case("raring", Distro::UbuntuRaring)
+ .Case("saucy", Distro::UbuntuSaucy)
+ .Case("trusty", Distro::UbuntuTrusty)
+ .Case("utopic", Distro::UbuntuUtopic)
+ .Case("vivid", Distro::UbuntuVivid)
+ .Case("wily", Distro::UbuntuWily)
+ .Case("xenial", Distro::UbuntuXenial)
+ .Case("yakkety", Distro::UbuntuYakkety)
+ .Case("zesty", Distro::UbuntuZesty)
+ .Default(Distro::UnknownDistro);
+ if (Version != Distro::UnknownDistro)
+ return Version;
+ }
+
+ File = VFS.getBufferForFile("/etc/redhat-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ if (Data.startswith("Fedora release"))
+ return Distro::Fedora;
+ if (Data.startswith("Red Hat Enterprise Linux") ||
+ Data.startswith("CentOS") ||
+ Data.startswith("Scientific Linux")) {
+ if (Data.find("release 7") != StringRef::npos)
+ return Distro::RHEL7;
+ else if (Data.find("release 6") != StringRef::npos)
+ return Distro::RHEL6;
+ else if (Data.find("release 5") != StringRef::npos)
+ return Distro::RHEL5;
+ }
+ return Distro::UnknownDistro;
+ }
+
+ File = VFS.getBufferForFile("/etc/debian_version");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ // Contents: < major.minor > or < codename/sid >
+ int MajorVersion;
+ if (!Data.split('.').first.getAsInteger(10, MajorVersion)) {
+ switch (MajorVersion) {
+ case 5:
+ return Distro::DebianLenny;
+ case 6:
+ return Distro::DebianSqueeze;
+ case 7:
+ return Distro::DebianWheezy;
+ case 8:
+ return Distro::DebianJessie;
+ case 9:
+ return Distro::DebianStretch;
+ default:
+ return Distro::UnknownDistro;
+ }
+ }
+ return llvm::StringSwitch<Distro::DistroType>(Data.split("\n").first)
+ .Case("squeeze/sid", Distro::DebianSqueeze)
+ .Case("wheezy/sid", Distro::DebianWheezy)
+ .Case("jessie/sid", Distro::DebianJessie)
+ .Case("stretch/sid", Distro::DebianStretch)
+ .Default(Distro::UnknownDistro);
+ }
+
+ File = VFS.getBufferForFile("/etc/SuSE-release");
+ if (File) {
+ StringRef Data = File.get()->getBuffer();
+ SmallVector<StringRef, 8> Lines;
+ Data.split(Lines, "\n");
+ for (const StringRef& Line : Lines) {
+ if (!Line.trim().startswith("VERSION"))
+ continue;
+ std::pair<StringRef, StringRef> SplitLine = Line.split('=');
+ // Old versions have split VERSION and PATCHLEVEL
+ // Newer versions use VERSION = x.y
+ std::pair<StringRef, StringRef> SplitVer = SplitLine.second.trim().split('.');
+ int Version;
+
+ // OpenSUSE/SLES 10 and older are not supported and not compatible
+ // with our rules, so just treat them as Distro::UnknownDistro.
+ if (!SplitVer.first.getAsInteger(10, Version) && Version > 10)
+ return Distro::OpenSUSE;
+ return Distro::UnknownDistro;
+ }
+ return Distro::UnknownDistro;
+ }
+
+ if (VFS.exists("/etc/exherbo-release"))
+ return Distro::Exherbo;
+
+ if (VFS.exists("/etc/arch-release"))
+ return Distro::ArchLinux;
+
+ return Distro::UnknownDistro;
+}
+
+Distro::Distro(vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {}