Home | History | Annotate | Line # | Download | only in Driver
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