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/os/stat.hpp>
21 #include <stout/path.hpp>
22 #include <stout/stringify.hpp>
23 #include <stout/try.hpp>
24 
25 
26 namespace os {
27 
28 // This implementation works by running the `cp` command with some
29 // additional conditions to ensure we copy a single file only,
30 // from an absolute file path to another absolute file path.
31 //
32 // Directories are not supported as a destination path for two reasons:
33 // 1. No callers depended on that behavior,
34 // 2. Consistency with Windows implementation.
35 //
36 // Relative paths are not allowed, as these are resolved based on
37 // the current working directory and may be inconsistent.
39  const std::string& source, const std::string& destination)
40 {
41  // NOTE: We check the form of the path too in case it does not exist, and to
42  // prevent user error.
43  if (stat::isdir(source) || source.back() == '/') {
44  return Error("`source` was a directory");
45  }
46 
47  if (stat::isdir(destination) || destination.back() == '/') {
48  return Error("`destination` was a directory");
49  }
50 
51  if (!path::absolute(source)) {
52  return Error("`source` was a relative path");
53  }
54 
55  if (!path::absolute(destination)) {
56  return Error("`destination` was a relative path");
57  }
58 
59  const int status = os::spawn("cp", {"cp", source, destination});
60 
61  if (status == -1) {
62  return ErrnoError("os::spawn failed");
63  }
64 
65  if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
66  return Error("cp failed with status: " + stringify(status));
67  }
68 
69  return Nothing();
70 }
71 
72 } // namespace os {
73 
74 #endif // __STOUT_OS_POSIX_COPYFILE_HPP__
Definition: nothing.hpp:16
Definition: errorbase.hpp:35
Try< Nothing > copyfile(const std::string &source, const std::string &destination)
Definition: copyfile.hpp:38
Definition: try.hpp:34
int spawn(const std::string &command, const std::vector< std::string > &arguments)
Definition: shell.hpp:159
Result< ProcessStatus > status(pid_t pid)
Definition: proc.hpp:166
Definition: errorbase.hpp:49
bool absolute(const std::string &path)
Returns whether the given path is an absolute path.
Definition: path.hpp:96
#define WEXITSTATUS(x)
Definition: windows.hpp:376
#define WIFEXITED(x)
Definition: windows.hpp:370
bool isdir(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:78
std::string stringify(int flags)