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 "host/libs/config/config_utils.h"
18 
19 #include <string.h>
20 
21 #include <iomanip>
22 #include <sstream>
23 
24 #include <android-base/logging.h>
25 #include <android-base/strings.h>
26 
27 #include "common/libs/utils/contains.h"
28 #include "common/libs/utils/environment.h"
29 #include "host/libs/config/config_constants.h"
30 #include "host/libs/config/cuttlefish_config.h"
31 
32 namespace cuttlefish {
33 
InstanceFromString(std::string instance_str)34 int InstanceFromString(std::string instance_str) {
35   if (android::base::StartsWith(instance_str, kVsocUserPrefix)) {
36     instance_str = instance_str.substr(std::string(kVsocUserPrefix).size());
37   } else if (android::base::StartsWith(instance_str, kCvdNamePrefix)) {
38     instance_str = instance_str.substr(std::string(kCvdNamePrefix).size());
39   }
40 
41   int instance = std::stoi(instance_str);
42   if (instance <= 0) {
43     LOG(INFO) << "Failed to interpret \"" << instance_str << "\" as an id, "
44               << "using instance id " << kDefaultInstance;
45     return kDefaultInstance;
46   }
47   return instance;
48 }
49 
InstanceFromEnvironment()50 int InstanceFromEnvironment() {
51   std::string instance_str = StringFromEnv(kCuttlefishInstanceEnvVarName, "");
52   if (instance_str.empty()) {
53     // Try to get it from the user instead
54     instance_str = StringFromEnv("USER", "");
55 
56     if (instance_str.empty()) {
57       LOG(DEBUG) << kCuttlefishInstanceEnvVarName
58                  << " and USER unset, using instance id " << kDefaultInstance;
59       return kDefaultInstance;
60     }
61     if (!android::base::StartsWith(instance_str, kVsocUserPrefix)) {
62       // No user or we don't recognize this user
63       LOG(DEBUG) << "Non-vsoc user, using instance id " << kDefaultInstance;
64       return kDefaultInstance;
65     }
66   }
67   return InstanceFromString(instance_str);
68 }
69 
GetInstance()70 int GetInstance() {
71   static int instance_id = InstanceFromEnvironment();
72   return instance_id;
73 }
74 
GetDefaultVsockCid()75 int GetDefaultVsockCid() {
76   // we assume that this function is used to configure CuttlefishConfig once
77   static const int default_vsock_cid = 3 + GetInstance() - 1;
78   return default_vsock_cid;
79 }
80 
GetVsockServerPort(const int base,const int vsock_guest_cid)81 int GetVsockServerPort(const int base,
82                        const int vsock_guest_cid /**< per instance guest cid */) {
83     return base + (vsock_guest_cid - 3);
84 }
85 
GetGlobalConfigFileLink()86 std::string GetGlobalConfigFileLink() {
87   return StringFromEnv("HOME", ".") + "/.cuttlefish_config.json";
88 }
89 
ForCurrentInstance(const char * prefix)90 std::string ForCurrentInstance(const char* prefix) {
91   std::ostringstream stream;
92   stream << prefix << std::setfill('0') << std::setw(2) << GetInstance();
93   return stream.str();
94 }
ForCurrentInstance(int base)95 int ForCurrentInstance(int base) { return base + GetInstance() - 1; }
96 
RandomSerialNumber(const std::string & prefix)97 std::string RandomSerialNumber(const std::string& prefix) {
98   const char hex_characters[] = "0123456789ABCDEF";
99   std::srand(time(0));
100   char str[10];
101   for(int i=0; i<10; i++){
102     str[i] = hex_characters[rand() % strlen(hex_characters)];
103   }
104   return prefix + str;
105 }
106 
DefaultHostArtifactsPath(const std::string & file_name)107 std::string DefaultHostArtifactsPath(const std::string& file_name) {
108   return (StringFromEnv("ANDROID_HOST_OUT", StringFromEnv("HOME", ".")) + "/") +
109          file_name;
110 }
111 
HostBinaryDir()112 std::string HostBinaryDir() {
113   return DefaultHostArtifactsPath("bin");
114 }
115 
UseQemuPrebuilt()116 bool UseQemuPrebuilt() {
117   const std::string target_prod_str = StringFromEnv("TARGET_PRODUCT", "");
118   if (!Contains(target_prod_str, "arm")) {
119     return true;
120   }
121   return false;
122 }
123 
DefaultQemuBinaryDir()124 std::string DefaultQemuBinaryDir() {
125   if (UseQemuPrebuilt()) {
126     return HostBinaryDir() + "/" + HostArchStr() + "-linux-gnu/qemu";
127   }
128   return "/usr/bin";
129 }
130 
HostBinaryPath(const std::string & binary_name)131 std::string HostBinaryPath(const std::string& binary_name) {
132 #ifdef __ANDROID__
133   return binary_name;
134 #else
135   return HostBinaryDir() + "/" + binary_name;
136 #endif
137 }
138 
HostUsrSharePath(const std::string & binary_name)139 std::string HostUsrSharePath(const std::string& binary_name) {
140   return DefaultHostArtifactsPath("usr/share/" + binary_name);
141 }
142 
HostQemuBiosPath()143 std::string HostQemuBiosPath() {
144   if (UseQemuPrebuilt()) {
145     return DefaultHostArtifactsPath(
146         "usr/share/qemu/" + HostArchStr() + "-linux-gnu");
147   }
148   return "/usr/share/qemu";
149 }
150 
DefaultGuestImagePath(const std::string & file_name)151 std::string DefaultGuestImagePath(const std::string& file_name) {
152   return (StringFromEnv("ANDROID_PRODUCT_OUT", StringFromEnv("HOME", "."))) +
153          file_name;
154 }
155 
HostSupportsQemuCli()156 bool HostSupportsQemuCli() {
157   static bool supported =
158 #ifdef __linux__
159       std::system(
160           "/usr/lib/cuttlefish-common/bin/capability_query.py qemu_cli") == 0;
161 #else
162       true;
163 #endif
164   return supported;
165 }
166 
167 }
168