]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/core/uname.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / seastar / src / core / uname.cc
1 /*
2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
6 *
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
16 * under the License.
17 */
18
19 /*
20 * Copyright (C) 2019 ScyllaDB
21 */
22
23 #include "uname.hh"
24 #include <regex>
25 #include <boost/algorithm/cxx11/any_of.hpp>
26 #include <sys/utsname.h>
27 #include <iostream>
28
29 namespace seastar {
30
31 namespace internal {
32
33 int uname_t::component_count() const {
34 if (distro_patch) {
35 return 5;
36 }
37 if (subsublevel) {
38 return 4;
39 }
40 if (sublevel) {
41 return 3;
42 }
43 return 2;
44 }
45
46 bool uname_t::has_distro_extra(std::string extra) const {
47 return distro_extra.find(extra) != std::string::npos;
48 }
49
50 // Can't use optional compares, C++17 only
51 static int cmp(const std::optional<int>& u1, const std::optional<int>& u2) {
52 return int(u1.value_or(0) - u2.value_or(0));
53 }
54
55 bool uname_t::same_as_or_descendant_of(const uname_t& x) const {
56 if (version < x.version) {
57 return false; // 4.2 vs. 5.1
58 }
59 if (version == x.version && patchlevel < x.patchlevel) {
60 return false; // 4.0 vs 4.1
61 }
62 if (!has_distro_extra(x.distro_extra)) {
63 return false;
64 }
65 switch (x.component_count()) {
66 case 5:
67 return version == x.version
68 && patchlevel == x.patchlevel
69 && cmp(sublevel, x.sublevel) == 0
70 && cmp(subsublevel, x.subsublevel) == 0
71 && cmp(distro_patch, x.distro_patch) >= 0;
72 case 4:
73 return version == x.version
74 && patchlevel == x.patchlevel
75 && cmp(sublevel, x.sublevel) == 0
76 && cmp(subsublevel, x.subsublevel) >= 0;
77 case 3:
78 return version == x.version
79 && patchlevel == x.patchlevel
80 && cmp(sublevel, x.sublevel) >= 0;
81 case 2:
82 return true;
83 default:
84 return false;
85 }
86 }
87
88 uname_t parse_uname(const char* u) {
89 static std::regex re(R"XX((\d+)\.(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:-(\d*)(.+))?)XX");
90 std::cmatch m;
91 if (std::regex_match(u, m, re)) {
92 auto num = [] (std::csub_match sm) -> std::optional<int> {
93 if (sm.length() > 0) {
94 return std::atoi(sm.str().c_str());
95 } else {
96 return std::nullopt;
97 }
98 };
99 return uname_t{*num(m[1]), *num(m[2]), num(m[3]), num(m[4]), num(m[5]), m[6].str()};
100 } else {
101 return uname_t{0, 0, std::nullopt, std::nullopt, std::nullopt, ""};
102 }
103 }
104
105
106 bool uname_t::whitelisted(std::initializer_list<const char*> wl) const {
107 return boost::algorithm::any_of(wl, [this] (const char* v) {
108 return same_as_or_descendant_of(parse_uname(v));
109 });
110 }
111
112 std::ostream& operator<<(std::ostream& os, const uname_t& u) {
113 os << u.version << "." << u.patchlevel;
114 if (u.sublevel) {
115 os << "." << *u.sublevel;
116 }
117 if (u.subsublevel) {
118 os << "." << *u.subsublevel;
119 }
120 if (u.distro_patch || !u.distro_extra.empty()) {
121 os << "-";
122 }
123 if (u.distro_patch) {
124 os << *u.distro_patch;
125 }
126 os << u.distro_extra;
127 return os;
128 }
129
130
131 uname_t kernel_uname() {
132 struct ::utsname buf;
133 ::uname(&buf);
134 return parse_uname(buf.release);
135 }
136
137 }
138 }