Apache Mesos
copyfile.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_POSIX_COPYFILE_HPP__
14 #define __STOUT_OS_POSIX_COPYFILE_HPP__
15 
16 #include <string>
17 
18 #include <stout/error.hpp>
19 #include <stout/nothing.hpp>
20 #include <stout/option.hpp>
21 #include <stout/path.hpp>
22 #include <stout/stringify.hpp>
23 #include <stout/try.hpp>
24 
25 #include <stout/os/shell.hpp>
26 #include <stout/os/stat.hpp>
27 
28 namespace os {
29 
30 // This implementation works by running the `cp` command with some
31 // additional conditions to ensure we copy a single file only,
32 // from an absolute file path to another absolute file path.
33 //
34 // Directories are not supported as a destination path for two reasons:
35 // 1. No callers depended on that behavior,
36 // 2. Consistency with Windows implementation.
37 //
38 // Relative paths are not allowed, as these are resolved based on
39 // the current working directory and may be inconsistent.
41  const std::string& source, const std::string& destination)
42 {
43  // NOTE: We check the form of the path too in case it does not exist, and to
44  // prevent user error.
45  if (stat::isdir(source) || source.back() == '/') {
46  return Error("`source` was a directory");
47  }
48 
49  if (stat::isdir(destination) || destination.back() == '/') {
50  return Error("`destination` was a directory");
51  }
52 
53  if (!path::is_absolute(source)) {
54  return Error("`source` was a relative path");
55  }
56 
57  if (!path::is_absolute(destination)) {
58  return Error("`destination` was a relative path");
59  }
60 
61  const Option<int> status = os::spawn("cp", {"cp", source, destination});
62 
63  if (status.isNone()) {
64  return ErrnoError("os::spawn failed");
65  }
66 
67  if (!(WIFEXITED(status.get()) && WEXITSTATUS(status.get()) == 0)) {
68  return Error("cp failed with status: " + stringify(status.get()));
69  }
70 
71  return Nothing();
72 }
73 
74 } // namespace os {
75 
76 #endif // __STOUT_OS_POSIX_COPYFILE_HPP__
bool is_absolute(const std::string &path)
Returns whether the given path is an absolute path.
Definition: path.hpp:158
Definition: nothing.hpp:16
Definition: errorbase.hpp:36
Try< Nothing > copyfile(const std::string &source, const std::string &destination)
Definition: copyfile.hpp:40
Definition: check.hpp:33
Result< ProcessStatus > status(pid_t pid)
Definition: proc.hpp:166
Definition: errorbase.hpp:50
Option< int > spawn(const std::string &command, const std::vector< std::string > &arguments)
Definition: shell.hpp:162
Definition: posix_signalhandler.hpp:23
const T & get() const &
Definition: option.hpp:119
#define WEXITSTATUS(x)
Definition: windows.hpp:368
#define WIFEXITED(x)
Definition: windows.hpp:362
bool isdir(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:91
bool isNone() const
Definition: option.hpp:117
std::string stringify(int flags)