• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "common/libs/utils/environment.h"
18 
19 #include <cstdio>
20 #include <cstdlib>
21 #include <memory>
22 #include <ostream>
23 #include <string>
24 
25 #include <android-base/logging.h>
26 
27 #include "common/libs/utils/files.h"
28 
29 namespace cuttlefish {
30 
StringFromEnv(const std::string & varname,const std::string & defval)31 std::string StringFromEnv(const std::string& varname,
32                           const std::string& defval) {
33   const char* const valstr = getenv(varname.c_str());
34   if (!valstr) {
35     return defval;
36   }
37   return valstr;
38 }
39 
40 /**
41  * at runtime, return the arch of the host: e.g. aarch64, x86_64, etc
42  *
43  * uses "`which uname` -m"
44  *
45  * @return arch string on success, "" on failure
46  */
HostArchStr()47 std::string HostArchStr() {
48   static std::string arch;
49   static bool cached = false;
50 
51   if (cached) {
52     return arch;
53   }
54   cached = true;
55 
56   // good to check if uname exists and is executable
57   // or, guarantee uname is available by dependency list
58   FILE* pip = popen("uname -m", "r");
59   if (!pip) {
60     return std::string{};
61   }
62 
63   auto read_from_file =
64       [](FILE* fp, size_t len) {
65         /*
66          * to see if input is longer than len,
67          * we read up to len+1. If the length is len+1,
68          * then the input is too long
69          */
70         decltype(len) upper = len + 1;
71         std::string format("%");
72         format.append(std::to_string(upper)).append("s");
73         std::shared_ptr<char> buf(new char[upper],
74                                   std::default_delete<char[]>());
75         if (fscanf(fp, format.c_str(), buf.get()) == EOF) {
76           return std::string{};
77         }
78         std::string result(buf.get());
79         return (result.length() < upper) ? result : std::string{};
80       };
81   arch = read_from_file(pip, 20);
82   pclose(pip);
83 
84   // l and r trim on arch
85   static const char* whitespace = "\t\n\r\f\v ";
86   arch.erase(arch.find_last_not_of(whitespace) + 1); // r trim
87   arch.erase(0, arch.find_first_not_of(whitespace)); // l trim
88   return arch;
89 }
90 
HostArch()91 Arch HostArch() {
92   std::string arch_str = HostArchStr();
93   if (arch_str == "aarch64") {
94     return Arch::Arm64;
95   } else if (arch_str == "arm") {
96     return Arch::Arm;
97   } else if (arch_str == "x86_64") {
98     return Arch::X86_64;
99   } else if (arch_str.size() == 4 && arch_str[0] == 'i' && arch_str[2] == '8' &&
100              arch_str[3] == '6') {
101     return Arch::X86;
102   } else {
103     LOG(FATAL) << "Unknown host architecture: " << arch_str;
104     return Arch::X86;
105   }
106 }
107 
IsHostCompatible(Arch arch)108 bool IsHostCompatible(Arch arch) {
109   Arch host_arch = HostArch();
110   return arch == host_arch || (arch == Arch::Arm && host_arch == Arch::Arm64) ||
111          (arch == Arch::X86 && host_arch == Arch::X86_64);
112 }
113 
IsRunningInDocker()114 static bool IsRunningInDocker() {
115   // if /.dockerenv exists, it's inside a docker container
116   static std::string docker_env_path("/.dockerenv");
117   static bool ret =
118       FileExists(docker_env_path) || DirectoryExists(docker_env_path);
119   return ret;
120 }
121 
IsRunningInContainer()122 bool IsRunningInContainer() {
123   // TODO: add more if we support other containers than docker
124   return IsRunningInDocker();
125 }
126 
127 }  // namespace cuttlefish
128