• 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 #include "common/libs/utils/files.h"
19 
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <iostream>
23 
24 #include <android-base/logging.h>
25 
26 namespace cuttlefish {
27 
StringFromEnv(const std::string & varname,const std::string & defval)28 std::string StringFromEnv(const std::string& varname,
29                           const std::string& defval) {
30   const char* const valstr = getenv(varname.c_str());
31   if (!valstr) {
32     return defval;
33   }
34   return valstr;
35 }
36 
37 /**
38  * at runtime, return the arch of the host: e.g. aarch64, x86_64, etc
39  *
40  * uses "`which uname` -m"
41  *
42  * @return arch string on success, "" on failure
43  */
HostArchStr()44 std::string HostArchStr() {
45   static std::string arch;
46   static bool cached = false;
47 
48   if (cached) {
49     return arch;
50   }
51   cached = true;
52 
53   // good to check if uname exists and is executable
54   // or, guarantee uname is available by dependency list
55   FILE* pip = popen("uname -m", "r");
56   if (!pip) {
57     return std::string{};
58   }
59 
60   auto read_from_file =
61       [](FILE* fp, size_t len) {
62         /*
63          * to see if input is longer than len,
64          * we read up to len+1. If the length is len+1,
65          * then the input is too long
66          */
67         decltype(len) upper = len + 1;
68         std::string format("%");
69         format.append(std::to_string(upper)).append("s");
70         std::shared_ptr<char> buf(new char[upper],
71                                   std::default_delete<char[]>());
72         if (fscanf(fp, format.c_str(), buf.get()) == EOF) {
73           return std::string{};
74         }
75         std::string result(buf.get());
76         return (result.length() < upper) ? result : std::string{};
77       };
78   arch = read_from_file(pip, 20);
79   pclose(pip);
80 
81   // l and r trim on arch
82   static const char* whitespace = "\t\n\r\f\v ";
83   arch.erase(arch.find_last_not_of(whitespace) + 1); // r trim
84   arch.erase(0, arch.find_first_not_of(whitespace)); // l trim
85   return arch;
86 }
87 
HostArch()88 Arch HostArch() {
89   std::string arch_str = HostArchStr();
90   if (arch_str == "aarch64") {
91     return Arch::Arm64;
92   } else if (arch_str == "arm") {
93     return Arch::Arm;
94   } else if (arch_str == "x86_64") {
95     return Arch::X86_64;
96   } else if (arch_str.size() == 4 && arch_str[0] == 'i' && arch_str[2] == '8' &&
97              arch_str[3] == '6') {
98     return Arch::X86;
99   } else {
100     LOG(FATAL) << "Unknown host architecture: " << arch_str;
101     return Arch::X86;
102   }
103 }
104 
IsHostCompatible(Arch arch)105 bool IsHostCompatible(Arch arch) {
106   Arch host_arch = HostArch();
107   return arch == host_arch || (arch == Arch::Arm && host_arch == Arch::Arm64) ||
108          (arch == Arch::X86 && host_arch == Arch::X86_64);
109 }
110 
IsRunningInDocker()111 static bool IsRunningInDocker() {
112   // if /.dockerenv exists, it's inside a docker container
113   static std::string docker_env_path("/.dockerenv");
114   static bool ret =
115       FileExists(docker_env_path) || DirectoryExists(docker_env_path);
116   return ret;
117 }
118 
IsRunningInContainer()119 bool IsRunningInContainer() {
120   // TODO: add more if we support other containers than docker
121   return IsRunningInDocker();
122 }
123 
124 }  // namespace cuttlefish
125