Add executable_path() and convert SubprocessTest to use it
[folly.git] / folly / experimental / io / FsUtil.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
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 <folly/experimental/io/FsUtil.h>
18
19 #include <unistd.h>
20 #include <folly/Exception.h>
21
22 namespace bsys = ::boost::system;
23
24 namespace folly {
25 namespace fs {
26
27 namespace {
28 bool skipPrefix(const path& pth, const path& prefix, path::const_iterator& it) {
29   it = pth.begin();
30   for (auto& p : prefix) {
31     if (it == pth.end()) {
32       return false;
33     }
34     if (p == ".") {
35       // Should only occur at the end, if prefix ends with a slash
36       continue;
37     }
38     if (*it++ != p) {
39       return false;
40     }
41   }
42   return true;
43 }
44 }  // namespace
45
46 bool starts_with(const path& pth, const path& prefix) {
47   path::const_iterator it;
48   return skipPrefix(pth, prefix, it);
49 }
50
51 path remove_prefix(const path& pth, const path& prefix) {
52   path::const_iterator it;
53   if (!skipPrefix(pth, prefix, it)) {
54     throw filesystem_error(
55         "Path does not start with prefix",
56         pth, prefix,
57         bsys::errc::make_error_code(bsys::errc::invalid_argument));
58   }
59
60   path p;
61   for (; it != pth.end(); ++it) {
62     p /= *it;
63   }
64
65   return p;
66 }
67
68 path canonical_parent(const path& pth, const path& base) {
69   return canonical(pth.parent_path(), base) / pth.filename();
70 }
71
72 path executable_path() {
73   return read_symlink("/proc/self/exe");
74 }
75
76 }  // namespace fs
77 }  // namespace folly