1*9190c2a8SAndroid Build Coastguard Worker /*
2*9190c2a8SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*9190c2a8SAndroid Build Coastguard Worker *
4*9190c2a8SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*9190c2a8SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*9190c2a8SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*9190c2a8SAndroid Build Coastguard Worker *
8*9190c2a8SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*9190c2a8SAndroid Build Coastguard Worker *
10*9190c2a8SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*9190c2a8SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*9190c2a8SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9190c2a8SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*9190c2a8SAndroid Build Coastguard Worker * limitations under the License.
15*9190c2a8SAndroid Build Coastguard Worker */
16*9190c2a8SAndroid Build Coastguard Worker
17*9190c2a8SAndroid Build Coastguard Worker #pragma once
18*9190c2a8SAndroid Build Coastguard Worker
19*9190c2a8SAndroid Build Coastguard Worker #include <iterator>
20*9190c2a8SAndroid Build Coastguard Worker #include <optional>
21*9190c2a8SAndroid Build Coastguard Worker #include <string>
22*9190c2a8SAndroid Build Coastguard Worker #include <string_view>
23*9190c2a8SAndroid Build Coastguard Worker
24*9190c2a8SAndroid Build Coastguard Worker #include <dirent.h>
25*9190c2a8SAndroid Build Coastguard Worker
26*9190c2a8SAndroid Build Coastguard Worker namespace android::incfs::path {
27*9190c2a8SAndroid Build Coastguard Worker
28*9190c2a8SAndroid Build Coastguard Worker namespace details {
29*9190c2a8SAndroid Build Coastguard Worker void appendNextPath(std::string& res, std::string_view c);
30*9190c2a8SAndroid Build Coastguard Worker }
31*9190c2a8SAndroid Build Coastguard Worker
32*9190c2a8SAndroid Build Coastguard Worker constexpr auto procfsFdDir = std::string_view("/proc/self/fd");
33*9190c2a8SAndroid Build Coastguard Worker
34*9190c2a8SAndroid Build Coastguard Worker std::string fromFd(int fd);
35*9190c2a8SAndroid Build Coastguard Worker std::string procfsForFd(int fd);
36*9190c2a8SAndroid Build Coastguard Worker std::string readlink(std::string_view path);
37*9190c2a8SAndroid Build Coastguard Worker bool isAbsolute(std::string_view path);
38*9190c2a8SAndroid Build Coastguard Worker std::string normalize(std::string_view path);
39*9190c2a8SAndroid Build Coastguard Worker
40*9190c2a8SAndroid Build Coastguard Worker std::string_view relativize(std::string_view parent, std::string_view nested);
relativize(const char * parent,const char * nested)41*9190c2a8SAndroid Build Coastguard Worker inline std::string_view relativize(const char* parent, const char* nested) {
42*9190c2a8SAndroid Build Coastguard Worker return relativize(std::string_view(parent), std::string_view(nested));
43*9190c2a8SAndroid Build Coastguard Worker }
relativize(std::string_view parent,const char * nested)44*9190c2a8SAndroid Build Coastguard Worker inline std::string_view relativize(std::string_view parent, const char* nested) {
45*9190c2a8SAndroid Build Coastguard Worker return relativize(parent, std::string_view(nested));
46*9190c2a8SAndroid Build Coastguard Worker }
relativize(const char * parent,std::string_view nested)47*9190c2a8SAndroid Build Coastguard Worker inline std::string_view relativize(const char* parent, std::string_view nested) {
48*9190c2a8SAndroid Build Coastguard Worker return relativize(std::string_view(parent), nested);
49*9190c2a8SAndroid Build Coastguard Worker }
50*9190c2a8SAndroid Build Coastguard Worker
51*9190c2a8SAndroid Build Coastguard Worker std::string_view relativize(std::string&& parent, std::string_view nested) = delete;
52*9190c2a8SAndroid Build Coastguard Worker std::string_view relativize(std::string_view parent, std::string&& nested) = delete;
53*9190c2a8SAndroid Build Coastguard Worker
54*9190c2a8SAndroid Build Coastguard Worker // Note: some system headers #define 'dirname' and 'basename' as macros
55*9190c2a8SAndroid Build Coastguard Worker
baseName(std::string_view path)56*9190c2a8SAndroid Build Coastguard Worker inline std::string_view baseName(std::string_view path) {
57*9190c2a8SAndroid Build Coastguard Worker using namespace std::literals;
58*9190c2a8SAndroid Build Coastguard Worker if (path.empty()) {
59*9190c2a8SAndroid Build Coastguard Worker return {};
60*9190c2a8SAndroid Build Coastguard Worker }
61*9190c2a8SAndroid Build Coastguard Worker if (path == "/"sv) {
62*9190c2a8SAndroid Build Coastguard Worker return "/"sv;
63*9190c2a8SAndroid Build Coastguard Worker }
64*9190c2a8SAndroid Build Coastguard Worker auto pos = path.rfind('/');
65*9190c2a8SAndroid Build Coastguard Worker while (!path.empty() && pos == path.size() - 1) {
66*9190c2a8SAndroid Build Coastguard Worker path.remove_suffix(1);
67*9190c2a8SAndroid Build Coastguard Worker pos = path.rfind('/');
68*9190c2a8SAndroid Build Coastguard Worker }
69*9190c2a8SAndroid Build Coastguard Worker if (pos == path.npos) {
70*9190c2a8SAndroid Build Coastguard Worker return path.empty() ? "/"sv : path;
71*9190c2a8SAndroid Build Coastguard Worker }
72*9190c2a8SAndroid Build Coastguard Worker return path.substr(pos + 1);
73*9190c2a8SAndroid Build Coastguard Worker }
74*9190c2a8SAndroid Build Coastguard Worker
dirName(std::string_view path)75*9190c2a8SAndroid Build Coastguard Worker inline std::string_view dirName(std::string_view path) {
76*9190c2a8SAndroid Build Coastguard Worker using namespace std::literals;
77*9190c2a8SAndroid Build Coastguard Worker if (path.empty()) {
78*9190c2a8SAndroid Build Coastguard Worker return {};
79*9190c2a8SAndroid Build Coastguard Worker }
80*9190c2a8SAndroid Build Coastguard Worker if (path == "/"sv) {
81*9190c2a8SAndroid Build Coastguard Worker return "/"sv;
82*9190c2a8SAndroid Build Coastguard Worker }
83*9190c2a8SAndroid Build Coastguard Worker const auto pos = path.rfind('/');
84*9190c2a8SAndroid Build Coastguard Worker if (pos == 0) {
85*9190c2a8SAndroid Build Coastguard Worker return "/"sv;
86*9190c2a8SAndroid Build Coastguard Worker }
87*9190c2a8SAndroid Build Coastguard Worker if (pos == path.npos) {
88*9190c2a8SAndroid Build Coastguard Worker return "."sv;
89*9190c2a8SAndroid Build Coastguard Worker }
90*9190c2a8SAndroid Build Coastguard Worker return path.substr(0, pos);
91*9190c2a8SAndroid Build Coastguard Worker }
92*9190c2a8SAndroid Build Coastguard Worker
93*9190c2a8SAndroid Build Coastguard Worker // Split the |full| path into its directory and basename components.
94*9190c2a8SAndroid Build Coastguard Worker // This modifies the input string to null-terminate the output directory
95*9190c2a8SAndroid Build Coastguard Worker std::pair<std::string_view, std::string_view> splitDirBase(std::string& full);
96*9190c2a8SAndroid Build Coastguard Worker
97*9190c2a8SAndroid Build Coastguard Worker int isEmptyDir(std::string_view dir);
98*9190c2a8SAndroid Build Coastguard Worker bool startsWith(std::string_view path, std::string_view prefix);
99*9190c2a8SAndroid Build Coastguard Worker bool endsWith(std::string_view path, std::string_view prefix);
100*9190c2a8SAndroid Build Coastguard Worker
101*9190c2a8SAndroid Build Coastguard Worker struct PathDirCloser {
operatorPathDirCloser102*9190c2a8SAndroid Build Coastguard Worker void operator()(DIR* d) const { ::closedir(d); }
103*9190c2a8SAndroid Build Coastguard Worker };
104*9190c2a8SAndroid Build Coastguard Worker
openDir(const char * path)105*9190c2a8SAndroid Build Coastguard Worker inline auto openDir(const char* path) {
106*9190c2a8SAndroid Build Coastguard Worker auto dir = std::unique_ptr<DIR, PathDirCloser>(::opendir(path));
107*9190c2a8SAndroid Build Coastguard Worker return dir;
108*9190c2a8SAndroid Build Coastguard Worker }
109*9190c2a8SAndroid Build Coastguard Worker
openDir(int dirFd)110*9190c2a8SAndroid Build Coastguard Worker inline auto openDir(int dirFd) {
111*9190c2a8SAndroid Build Coastguard Worker auto dir = std::unique_ptr<DIR, PathDirCloser>(::fdopendir(dirFd));
112*9190c2a8SAndroid Build Coastguard Worker return dir;
113*9190c2a8SAndroid Build Coastguard Worker }
114*9190c2a8SAndroid Build Coastguard Worker
115*9190c2a8SAndroid Build Coastguard Worker template <class... Paths>
join(std::string && first,std::string_view second,Paths &&...paths)116*9190c2a8SAndroid Build Coastguard Worker std::string join(std::string&& first, std::string_view second, Paths&&... paths) {
117*9190c2a8SAndroid Build Coastguard Worker std::string& result = first;
118*9190c2a8SAndroid Build Coastguard Worker {
119*9190c2a8SAndroid Build Coastguard Worker using std::size;
120*9190c2a8SAndroid Build Coastguard Worker result.reserve(first.size() + second.size() + 1 + (sizeof...(paths) + ... + size(paths)));
121*9190c2a8SAndroid Build Coastguard Worker }
122*9190c2a8SAndroid Build Coastguard Worker (details::appendNextPath(result, second), ...,
123*9190c2a8SAndroid Build Coastguard Worker details::appendNextPath(result, std::forward<Paths>(paths)));
124*9190c2a8SAndroid Build Coastguard Worker return result;
125*9190c2a8SAndroid Build Coastguard Worker }
126*9190c2a8SAndroid Build Coastguard Worker
127*9190c2a8SAndroid Build Coastguard Worker template <class... Paths>
join(std::string_view first,std::string_view second,Paths &&...paths)128*9190c2a8SAndroid Build Coastguard Worker std::string join(std::string_view first, std::string_view second, Paths&&... paths) {
129*9190c2a8SAndroid Build Coastguard Worker return join(std::string(), first, second, std::forward<Paths>(paths)...);
130*9190c2a8SAndroid Build Coastguard Worker }
131*9190c2a8SAndroid Build Coastguard Worker template <class... Paths>
join(const char * first,std::string_view second,Paths &&...paths)132*9190c2a8SAndroid Build Coastguard Worker std::string join(const char* first, std::string_view second, Paths&&... paths) {
133*9190c2a8SAndroid Build Coastguard Worker return path::join(std::string_view(first), second, std::forward<Paths>(paths)...);
134*9190c2a8SAndroid Build Coastguard Worker }
135*9190c2a8SAndroid Build Coastguard Worker
136*9190c2a8SAndroid Build Coastguard Worker } // namespace android::incfs::path
137