]>
git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/src/core/uname.cc
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.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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
20 * Copyright (C) 2019 ScyllaDB
25 #include <boost/algorithm/cxx11/any_of.hpp>
26 #include <sys/utsname.h>
33 int uname_t::component_count() const {
46 bool uname_t::has_distro_extra(std::string extra
) const {
47 return distro_extra
.find(extra
) != std::string::npos
;
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));
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
59 if (version
== x
.version
&& patchlevel
< x
.patchlevel
) {
60 return false; // 4.0 vs 4.1
62 if (!has_distro_extra(x
.distro_extra
)) {
65 switch (x
.component_count()) {
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;
73 return version
== x
.version
74 && patchlevel
== x
.patchlevel
75 && cmp(sublevel
, x
.sublevel
) == 0
76 && cmp(subsublevel
, x
.subsublevel
) >= 0;
78 return version
== x
.version
79 && patchlevel
== x
.patchlevel
80 && cmp(sublevel
, x
.sublevel
) >= 0;
88 uname_t
parse_uname(const char* u
) {
89 static std::regex
re(R
"XX((\d+)\.(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:-(\d*)(.+))?)XX");
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());
99 return uname_t
{*num(m
[1]), *num(m
[2]), num(m
[3]), num(m
[4]), num(m
[5]), m
[6].str()};
101 return uname_t
{0, 0, std::nullopt
, std::nullopt
, std::nullopt
, ""};
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
));
112 std::ostream
& operator<<(std::ostream
& os
, const uname_t
& u
) {
113 os
<< u
.version
<< "." << u
.patchlevel
;
115 os
<< "." << *u
.sublevel
;
118 os
<< "." << *u
.subsublevel
;
120 if (u
.distro_patch
|| !u
.distro_extra
.empty()) {
123 if (u
.distro_patch
) {
124 os
<< *u
.distro_patch
;
126 os
<< u
.distro_extra
;
131 uname_t
kernel_uname() {
132 struct ::utsname buf
;
134 return parse_uname(buf
.release
);