xref: /aosp_15_r20/system/incremental_delivery/incfs/include/path.h (revision 9190c2a8bd3622b7aa9bd7bfe4b3aec77820f478)
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