1 /*
2 * Copyright (C) 2023 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/commands/cvd/selector/selector_common_parser.h"
18
19 #include <unistd.h>
20
21 #include "common/libs/utils/contains.h"
22 #include "common/libs/utils/flag_parser.h"
23 #include "common/libs/utils/users.h"
24 #include "host/commands/cvd/selector/instance_database_utils.h"
25 #include "host/commands/cvd/selector/selector_constants.h"
26 #include "host/commands/cvd/selector/selector_option_parser_utils.h"
27
28 namespace cuttlefish {
29 namespace selector {
30
Parse(const uid_t client_uid,cvd_common::Args & selector_args,const cvd_common::Envs & envs)31 Result<SelectorCommonParser> SelectorCommonParser::Parse(
32 const uid_t client_uid, cvd_common::Args& selector_args,
33 const cvd_common::Envs& envs) {
34 std::string system_wide_home = CF_EXPECT(SystemWideUserHome(client_uid));
35 SelectorCommonParser parser(system_wide_home, envs);
36 CF_EXPECT(parser.ParseOptions(selector_args));
37 return std::move(parser);
38 }
39
SelectorCommonParser(const std::string & client_user_home,const cvd_common::Envs & envs)40 SelectorCommonParser::SelectorCommonParser(const std::string& client_user_home,
41 const cvd_common::Envs& envs)
42 : client_user_home_(client_user_home), envs_{envs} {}
43
HomeOverridden() const44 Result<bool> SelectorCommonParser::HomeOverridden() const {
45 return Contains(envs_, "HOME") && (client_user_home_ != envs_.at("HOME"));
46 }
47
Home() const48 std::optional<std::string> SelectorCommonParser::Home() const {
49 if (Contains(envs_, "HOME")) {
50 return envs_.at("HOME");
51 }
52 return std::nullopt;
53 }
54
ParseOptions(cvd_common::Args & selector_args)55 Result<void> SelectorCommonParser::ParseOptions(
56 cvd_common::Args& selector_args) {
57 // Handling name-related options
58 auto group_name_flag =
59 CF_EXPECT(SelectorFlags::Get().GetFlag(SelectorFlags::kGroupName));
60 auto instance_name_flag =
61 CF_EXPECT(SelectorFlags::Get().GetFlag(SelectorFlags::kInstanceName));
62 std::optional<std::string> group_name_opt =
63 CF_EXPECT(group_name_flag.FilterFlag<std::string>(selector_args));
64 std::optional<std::string> instance_name_opt =
65 CF_EXPECT(instance_name_flag.FilterFlag<std::string>(selector_args));
66
67 NameFlagsParam name_flags_param{.group_name = group_name_opt,
68 .instance_names = instance_name_opt};
69 auto parsed_name_flags = CF_EXPECT(HandleNameOpts(name_flags_param));
70 group_name_ = parsed_name_flags.group_name;
71 instance_names_ = parsed_name_flags.instance_names;
72 return {};
73 }
74
75 Result<SelectorCommonParser::ParsedNameFlags>
HandleNameOpts(const NameFlagsParam & name_flags) const76 SelectorCommonParser::HandleNameOpts(const NameFlagsParam& name_flags) const {
77 std::optional<std::string> group_name_output;
78 std::optional<std::vector<std::string>> instance_names_output;
79 if (name_flags.group_name) {
80 group_name_output = CF_EXPECT(HandleGroupName(name_flags.group_name));
81 }
82
83 if (name_flags.instance_names) {
84 instance_names_output =
85 std::move(CF_EXPECT(HandleInstanceNames(name_flags.instance_names)));
86 }
87 return {ParsedNameFlags{.group_name = std::move(group_name_output),
88 .instance_names = std::move(instance_names_output)}};
89 }
90
HandleInstanceNames(const std::optional<std::string> & per_instance_names) const91 Result<std::vector<std::string>> SelectorCommonParser::HandleInstanceNames(
92 const std::optional<std::string>& per_instance_names) const {
93 CF_EXPECT(per_instance_names && !per_instance_names.value().empty());
94
95 auto instance_names =
96 CF_EXPECT(SeparateButWithNoEmptyToken(per_instance_names.value(), ","));
97 for (const auto& instance_name : instance_names) {
98 CF_EXPECT(IsValidInstanceName(instance_name));
99 }
100 std::unordered_set<std::string> duplication_check{instance_names.cbegin(),
101 instance_names.cend()};
102 CF_EXPECT(duplication_check.size() == instance_names.size());
103 return instance_names;
104 }
105
HandleGroupName(const std::optional<std::string> & group_name) const106 Result<std::string> SelectorCommonParser::HandleGroupName(
107 const std::optional<std::string>& group_name) const {
108 CF_EXPECT(group_name && !group_name.value().empty());
109 CF_EXPECT(IsValidGroupName(group_name.value()), group_name.value()
110 << " failed");
111 return {group_name.value()};
112 }
113
114 } // namespace selector
115 } // namespace cuttlefish
116