1 | |
2 | |
3 | |
4 | |
5 | |
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 | |
17 | using namespace clang::driver; |
18 | using namespace clang; |
19 | |
20 | static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) { |
21 | llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File = |
22 | VFS.getBufferForFile("/etc/lsb-release"); |
23 | if (File) { |
24 | StringRef Data = File.get()->getBuffer(); |
25 | SmallVector<StringRef, 16> Lines; |
26 | Data.split(Lines, "\n"); |
27 | Distro::DistroType Version = Distro::UnknownDistro; |
28 | for (StringRef Line : Lines) |
29 | if (Version == Distro::UnknownDistro && Line.startswith("DISTRIB_CODENAME=")) |
30 | Version = llvm::StringSwitch<Distro::DistroType>(Line.substr(17)) |
31 | .Case("hardy", Distro::UbuntuHardy) |
32 | .Case("intrepid", Distro::UbuntuIntrepid) |
33 | .Case("jaunty", Distro::UbuntuJaunty) |
34 | .Case("karmic", Distro::UbuntuKarmic) |
35 | .Case("lucid", Distro::UbuntuLucid) |
36 | .Case("maverick", Distro::UbuntuMaverick) |
37 | .Case("natty", Distro::UbuntuNatty) |
38 | .Case("oneiric", Distro::UbuntuOneiric) |
39 | .Case("precise", Distro::UbuntuPrecise) |
40 | .Case("quantal", Distro::UbuntuQuantal) |
41 | .Case("raring", Distro::UbuntuRaring) |
42 | .Case("saucy", Distro::UbuntuSaucy) |
43 | .Case("trusty", Distro::UbuntuTrusty) |
44 | .Case("utopic", Distro::UbuntuUtopic) |
45 | .Case("vivid", Distro::UbuntuVivid) |
46 | .Case("wily", Distro::UbuntuWily) |
47 | .Case("xenial", Distro::UbuntuXenial) |
48 | .Case("yakkety", Distro::UbuntuYakkety) |
49 | .Case("zesty", Distro::UbuntuZesty) |
50 | .Case("artful", Distro::UbuntuArtful) |
51 | .Case("bionic", Distro::UbuntuBionic) |
52 | .Case("cosmic", Distro::UbuntuCosmic) |
53 | .Case("disco", Distro::UbuntuDisco) |
54 | .Default(Distro::UnknownDistro); |
55 | if (Version != Distro::UnknownDistro) |
56 | return Version; |
57 | } |
58 | |
59 | File = VFS.getBufferForFile("/etc/redhat-release"); |
60 | if (File) { |
61 | StringRef Data = File.get()->getBuffer(); |
62 | if (Data.startswith("Fedora release")) |
63 | return Distro::Fedora; |
64 | if (Data.startswith("Red Hat Enterprise Linux") || |
65 | Data.startswith("CentOS") || |
66 | Data.startswith("Scientific Linux")) { |
67 | if (Data.find("release 7") != StringRef::npos) |
68 | return Distro::RHEL7; |
69 | else if (Data.find("release 6") != StringRef::npos) |
70 | return Distro::RHEL6; |
71 | else if (Data.find("release 5") != StringRef::npos) |
72 | return Distro::RHEL5; |
73 | } |
74 | return Distro::UnknownDistro; |
75 | } |
76 | |
77 | File = VFS.getBufferForFile("/etc/debian_version"); |
78 | if (File) { |
79 | StringRef Data = File.get()->getBuffer(); |
80 | |
81 | int MajorVersion; |
82 | if (!Data.split('.').first.getAsInteger(10, MajorVersion)) { |
83 | switch (MajorVersion) { |
84 | case 5: |
85 | return Distro::DebianLenny; |
86 | case 6: |
87 | return Distro::DebianSqueeze; |
88 | case 7: |
89 | return Distro::DebianWheezy; |
90 | case 8: |
91 | return Distro::DebianJessie; |
92 | case 9: |
93 | return Distro::DebianStretch; |
94 | case 10: |
95 | return Distro::DebianBuster; |
96 | default: |
97 | return Distro::UnknownDistro; |
98 | } |
99 | } |
100 | return llvm::StringSwitch<Distro::DistroType>(Data.split("\n").first) |
101 | .Case("squeeze/sid", Distro::DebianSqueeze) |
102 | .Case("wheezy/sid", Distro::DebianWheezy) |
103 | .Case("jessie/sid", Distro::DebianJessie) |
104 | .Case("stretch/sid", Distro::DebianStretch) |
105 | .Default(Distro::UnknownDistro); |
106 | } |
107 | |
108 | File = VFS.getBufferForFile("/etc/SuSE-release"); |
109 | if (File) { |
110 | StringRef Data = File.get()->getBuffer(); |
111 | SmallVector<StringRef, 8> Lines; |
112 | Data.split(Lines, "\n"); |
113 | for (const StringRef& Line : Lines) { |
114 | if (!Line.trim().startswith("VERSION")) |
115 | continue; |
116 | std::pair<StringRef, StringRef> SplitLine = Line.split('='); |
117 | |
118 | |
119 | std::pair<StringRef, StringRef> SplitVer = SplitLine.second.trim().split('.'); |
120 | int Version; |
121 | |
122 | |
123 | |
124 | if (!SplitVer.first.getAsInteger(10, Version) && Version > 10) |
125 | return Distro::OpenSUSE; |
126 | return Distro::UnknownDistro; |
127 | } |
128 | return Distro::UnknownDistro; |
129 | } |
130 | |
131 | if (VFS.exists("/etc/exherbo-release")) |
132 | return Distro::Exherbo; |
133 | |
134 | if (VFS.exists("/etc/alpine-release")) |
135 | return Distro::AlpineLinux; |
136 | |
137 | if (VFS.exists("/etc/arch-release")) |
138 | return Distro::ArchLinux; |
139 | |
140 | if (VFS.exists("/etc/gentoo-release")) |
141 | return Distro::Gentoo; |
142 | |
143 | return Distro::UnknownDistro; |
144 | } |
145 | |
146 | Distro::Distro(llvm::vfs::FileSystem &VFS) : DistroVal(DetectDistro(VFS)) {} |
147 | |