| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "rlimit_parser.h" |
| |
| #include <android-base/parseint.h> |
| #include <android-base/strings.h> |
| |
| using android::base::EqualsIgnoreCase; |
| using android::base::ParseInt; |
| using android::base::ParseUint; |
| using android::base::StartsWith; |
| |
| namespace android { |
| namespace init { |
| |
| // Builtins and service definitions both have their arguments start at 1 and finish at 3. |
| Result<std::pair<int, rlimit>> ParseRlimit(const std::vector<std::string>& args) { |
| static const std::vector<std::pair<const char*, int>> text_to_resources = { |
| {"cpu", RLIMIT_CPU}, {"fsize", RLIMIT_FSIZE}, |
| {"data", RLIMIT_DATA}, {"stack", RLIMIT_STACK}, |
| {"core", RLIMIT_CORE}, {"rss", RLIMIT_RSS}, |
| {"nproc", RLIMIT_NPROC}, {"nofile", RLIMIT_NOFILE}, |
| {"memlock", RLIMIT_MEMLOCK}, {"as", RLIMIT_AS}, |
| {"locks", RLIMIT_LOCKS}, {"sigpending", RLIMIT_SIGPENDING}, |
| {"msgqueue", RLIMIT_MSGQUEUE}, {"nice", RLIMIT_NICE}, |
| {"rtprio", RLIMIT_RTPRIO}, {"rttime", RLIMIT_RTTIME}, |
| }; |
| |
| int resource; |
| |
| if (ParseInt(args[1], &resource)) { |
| if (resource >= RLIM_NLIMITS) { |
| return Error() << "Resource '" << args[1] << "' over the maximum resource value '" |
| << RLIM_NLIMITS << "'"; |
| } else if (resource < 0) { |
| return Error() << "Resource '" << args[1] << "' below the minimum resource value '0'"; |
| } |
| } else { |
| std::string resource_string; |
| if (StartsWith(args[1], "RLIM_")) { |
| resource_string = args[1].substr(5); |
| } else if (StartsWith(args[1], "RLIMIT_")) { |
| resource_string = args[1].substr(7); |
| } else { |
| resource_string = args[1]; |
| } |
| |
| auto it = std::find_if(text_to_resources.begin(), text_to_resources.end(), |
| [&resource_string](const auto& entry) { |
| return EqualsIgnoreCase(resource_string, entry.first); |
| }); |
| if (it == text_to_resources.end()) { |
| return Error() << "Could not parse resource '" << args[1] << "'"; |
| } |
| |
| resource = it->second; |
| } |
| |
| rlimit limit; |
| if (args[2] == "-1" || args[2] == "unlimited") { |
| limit.rlim_cur = RLIM_INFINITY; |
| } else if (!ParseUint(args[2], &limit.rlim_cur)) { |
| return Error() << "Could not parse soft limit '" << args[2] << "'"; |
| } |
| |
| if (args[3] == "-1" || args[3] == "unlimited") { |
| limit.rlim_max = RLIM_INFINITY; |
| } else if (!ParseUint(args[3], &limit.rlim_max)) { |
| return Error() << "Could not parse hard limit '" << args[3] << "'"; |
| } |
| |
| return std::pair{resource, limit}; |
| } |
| |
| } // namespace init |
| } // namespace android |