1
1
#include " file.h"
2
2
3
- #include < dirent.h>
4
- #include < fcntl.h>
5
3
#include < string.h>
6
- #include < sys/mman.h>
7
- #include < sys/stat.h>
8
- #include < unistd.h>
9
4
10
5
#include < algorithm>
11
6
#include < sstream>
12
7
13
- #include " logger.h"
14
-
15
8
namespace d2d {
16
9
17
- class AutoFD {
18
- public:
19
- AutoFD (int fd) : fd_(fd) {}
20
-
21
- AutoFD (AutoFD&& fd) = delete ;
22
-
23
- AutoFD (const AutoFD& fd) = delete ;
24
-
25
- AutoFD& operator =(const AutoFD&) = delete ;
26
-
27
- AutoFD& operator =(AutoFD&& other) {
28
- Reset (other.fd_ );
29
- other.fd_ = -1 ;
30
- return *this ;
31
- };
32
-
33
- int Get () const { return fd_; };
34
-
35
- bool IsValid () const { return fd_ > 0 ; };
36
-
37
- void Reset (int fd = -1 ) {
38
- if (fd_ != fd && fd_ > 0 ) {
39
- int result = D2D_TEMP_FAILURE_RETRY (::close (fd_));
40
- if (result == -1 ) {
41
- D2D_ERROR << " Could not close a file descriptor." ;
42
- }
43
- }
44
- fd_ = fd;
45
- }
46
-
47
- ~AutoFD () { Reset (); }
48
-
49
- private:
50
- int fd_ = -1 ;
51
- };
52
-
53
- class AutoDir {
54
- public:
55
- AutoDir (DIR* dir) : dir_(dir) {}
56
-
57
- DIR* Get () const { return dir_; }
58
-
59
- bool IsValid () const { return dir_ != nullptr ; }
60
-
61
- ~AutoDir () {
62
- if (dir_ != nullptr ) {
63
- ::closedir (dir_);
64
- }
65
- }
66
-
67
- private:
68
- DIR* dir_ = nullptr ;
69
- D2D_DISALLOW_COPY_AND_ASSIGN (AutoDir);
70
- };
71
-
72
- class AutoMapping {
73
- public:
74
- AutoMapping (void * mapping, size_t size) : mapping_(mapping), size_(size) {}
75
-
76
- ~AutoMapping () {
77
- if (mapping_ != MAP_FAILED) {
78
- if (::munmap (mapping_, size_) != 0 ) {
79
- D2D_ERROR << " Error unmapping file." ;
80
- }
81
- }
82
- }
83
-
84
- void * Get () const { return mapping_; }
85
-
86
- bool IsValid () const { return mapping_ != MAP_FAILED; }
87
-
88
- private:
89
- void * mapping_ = MAP_FAILED;
90
- size_t size_ = 0 ;
91
-
92
- D2D_DISALLOW_COPY_AND_ASSIGN (AutoMapping);
93
- };
94
-
95
10
bool MakeDirectories (const std::vector<std::string>& directories) {
96
11
AutoFD current_level (AT_FDCWD);
97
12
@@ -121,7 +36,8 @@ bool MakeDirectories(const std::vector<std::string>& directories) {
121
36
return true ;
122
37
}
123
38
124
- bool CopyData (const void * data, size_t length, const std::string& to_path) {
39
+ bool CopyData (const void * from_data, size_t from_length,
40
+ const std::string& to_path) {
125
41
AutoFD to_file (
126
42
D2D_TEMP_FAILURE_RETRY (::open (to_path.c_str (), O_CREAT | O_TRUNC | O_RDWR,
127
43
S_IRUSR | S_IWUSR | S_IXUSR)));
@@ -131,31 +47,31 @@ bool CopyData(const void* data, size_t length, const std::string& to_path) {
131
47
return false ;
132
48
}
133
49
134
- if (::ftruncate (to_file.Get (), length ) != 0 ) {
50
+ if (::ftruncate (to_file.Get (), from_length ) != 0 ) {
135
51
D2D_ERROR << " Could not truncate file " << to_path;
136
52
return false ;
137
53
}
138
- AutoMapping to_mapping (::mmap (nullptr , length , PROT_WRITE,
54
+ AutoMapping to_mapping (::mmap (nullptr , from_length , PROT_WRITE,
139
55
MAP_FILE | MAP_SHARED, to_file.Get (), 0 ),
140
- length );
56
+ from_length );
141
57
142
58
if (!to_mapping.IsValid ()) {
143
59
D2D_ERROR << " Could not setup mapping to perform file copy." ;
144
60
return false ;
145
61
}
146
62
147
- ::memcpy (to_mapping.Get(), data, length );
63
+ ::memcpy (to_mapping.Get(), from_data, from_length );
148
64
149
- if (::msync (to_mapping.Get (), length , MS_SYNC) != 0 ) {
65
+ if (::msync (to_mapping.Get (), from_length , MS_SYNC) != 0 ) {
150
66
D2D_ERROR << " Could not sync file contents." ;
151
67
return false ;
152
68
}
153
69
154
70
return true ;
155
71
}
156
72
157
- static bool CopyFile (const struct stat & from_stat, const AutoFD& from,
158
- const std::string& to_path) {
73
+ bool CopyFile (const struct stat & from_stat, const AutoFD& from,
74
+ const std::string& to_path) {
159
75
AutoMapping from_mapping (::mmap (nullptr , from_stat.st_size , PROT_READ,
160
76
MAP_FILE | MAP_PRIVATE, from.Get (), 0 ),
161
77
from_stat.st_size );
@@ -212,10 +128,6 @@ bool CopyFiles(const std::string& from_path,
212
128
continue ;
213
129
}
214
130
215
- if (!predicate (file_name)) {
216
- continue ;
217
- }
218
-
219
131
AutoFD from_fd (D2D_TEMP_FAILURE_RETRY (
220
132
::openat (::dirfd(from.Get()), file_name.c_str(), O_RDONLY)));
221
133
if (!from_fd.IsValid ()) {
@@ -238,7 +150,11 @@ bool CopyFiles(const std::string& from_path,
238
150
return false ;
239
151
}
240
152
} else {
241
- if (!CopyFile (from_stat, from_fd, JoinPaths (to_path, file_name))) {
153
+ if (!predicate (file_name, //
154
+ from_stat, //
155
+ from_fd, //
156
+ JoinPaths (to_path, file_name) //
157
+ )) {
242
158
D2D_ERROR << " Could not copy file " << file_name;
243
159
return false ;
244
160
}
@@ -284,4 +200,48 @@ std::string JoinPaths(const std::vector<std::string>& paths,
284
200
return JoinPaths (merged);
285
201
}
286
202
203
+ std::unique_ptr<AutoMapping> OpenFileReadOnly (const AutoFD& fd, size_t size) {
204
+ if (!fd.IsValid ()) {
205
+ D2D_ERROR << " File descriptor was invalid" ;
206
+ return nullptr ;
207
+ }
208
+
209
+ auto mapping =
210
+ std::make_unique<AutoMapping>(::mmap (nullptr , //
211
+ size, //
212
+ PROT_READ, //
213
+ MAP_FILE | MAP_PRIVATE, //
214
+ fd.Get (), //
215
+ 0 ),
216
+ size);
217
+ if (!mapping || !mapping->IsValid ()) {
218
+ D2D_ERROR << " Could not create file mapping." ;
219
+ return nullptr ;
220
+ }
221
+
222
+ return mapping;
223
+ }
224
+
225
+ std::unique_ptr<AutoMapping> OpenFileReadOnly (const std::string& path) {
226
+ if (path.size () == 0 ) {
227
+ D2D_ERROR << " Path was empty when attempting to open file." ;
228
+ return nullptr ;
229
+ }
230
+
231
+ AutoFD fd (D2D_TEMP_FAILURE_RETRY (::open (path.c_str (), O_RDONLY)));
232
+
233
+ if (!fd.IsValid ()) {
234
+ D2D_ERROR << " Could not open file: " << path;
235
+ return nullptr ;
236
+ }
237
+
238
+ struct stat stat_buf = {0 };
239
+ if (::fstat (fd.Get (), &stat_buf) != 0 ) {
240
+ D2D_ERROR << " Could not stat file." ;
241
+ return nullptr ;
242
+ }
243
+
244
+ return OpenFileReadOnly (fd, stat_buf.st_size );
245
+ }
246
+
287
247
} // namespace d2d
0 commit comments