-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilesystem.hh
388 lines (309 loc) · 8.72 KB
/
filesystem.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
#pragma once
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
#include <string>
#include <unordered_map>
#include <boost/filesystem.hpp>
#include <elle/Buffer.hh>
#include <elle/Exception.hh>
#include <elle/filesystem.hh>
#include <elle/reactor/Waitable.hh>
#include <elle/reactor/exception.hh>
#include <elle/reactor/fwd.hh>
static_assert(sizeof(off_t) == 8,
"off_t is 32 bits long, define _FILE_OFFSET_BITS to 64");
#if defined ELLE_WINDOWS || defined ELLE_ANDROID
struct statvfs
{
unsigned long f_bsize; /* filesystem block size */
unsigned long f_frsize; /* fragment size */
unsigned long f_blocks; /* size of fs in f_frsize units */
unsigned long f_bfree; /* # free blocks */
unsigned long f_bavail; /* # free blocks for unprivileged users */
unsigned long f_files; /* # inodes */
unsigned long f_ffree; /* # free inodes */
unsigned long f_favail; /* # free inodes for unprivileged users */
unsigned long f_fsid; /* filesystem ID */
unsigned long f_flag; /* mount flags */
unsigned long f_namemax; /* maximum filename length */
};
#else
# include <sys/statvfs.h>
#endif
struct stat;
struct statvfs;
namespace elle
{
namespace reactor
{
namespace filesystem
{
namespace bfs = boost::filesystem;
using OnDirectoryEntry =
std::function<void(std::string const&, struct stat* stbuf)>;
/// Handle to an open file.
class Handle
{
public:
virtual
~Handle()
{}
virtual
int
read(elle::WeakBuffer buffer, size_t size, off_t offset) = 0;
virtual
int
write(elle::ConstWeakBuffer buffer, size_t size, off_t offset) = 0;
virtual
void
ftruncate(off_t offset);
virtual
void
fsync(int datasync);
virtual
void
fsyncdir(int datasync);
virtual
void
close() = 0;
};
class Path
: public std::enable_shared_from_this<Path>
{
public:
virtual
~Path()
{}
virtual
void
stat(struct stat*) = 0;
virtual
void
list_directory(OnDirectoryEntry cb) = 0;
virtual
std::unique_ptr<Handle>
open(int flags, mode_t mode) = 0;
/// Will bounce to open() if not implemented
virtual
std::unique_ptr<Handle>
create(int flags, mode_t mode);
/// Delete a file. Defaults to error(not implemented)
virtual
void
unlink();
virtual
void
mkdir(mode_t mode);
virtual
void
rmdir();
virtual
void
rename(bfs::path const& where);
virtual
bfs::path
readlink();
virtual
void
symlink(bfs::path const& where);
virtual
void
link(bfs::path const& where);
virtual
void
chmod(mode_t mode);
virtual
void
chown(int uid, int gid);
virtual
void
statfs(struct statvfs*);
virtual
void
utimens(const struct timespec tv[2]);
virtual
void
truncate(off_t new_size);
virtual
void
setxattr(std::string const& name, std::string const& value, int flags);
virtual
std::string
getxattr(std::string const& name);
virtual
std::vector<std::string> listxattr();
virtual
void
removexattr(std::string const& name);
/// Return a Path for given child name.
virtual
std::shared_ptr<Path>
child(std::string const& name) = 0;
/// Return true to allow the filesystem to keep this Path in cache.
virtual
bool
allow_cache()
{
return true;
}
virtual std::shared_ptr<Path> unwrap()
{
return shared_from_this();
}
};
class Operations
{
public:
Operations();
virtual
~Operations() {}
virtual
std::shared_ptr<Path>
path(std::string const& path) = 0;
virtual
std::shared_ptr<Path>
wrap(std::string const& path, std::shared_ptr<Path> source)
{
return source;
}
virtual
void
filesystem(FileSystem* fs) { _filesystem = fs;}
ELLE_ATTRIBUTE_R(FileSystem*, filesystem, protected);
};
class FileSystemImpl;
class FileSystem
: public reactor::Waitable
{
public:
/// Create a new file system with given operations
///
/// @path operations Operations root.
/// \param full_tree: If set, will use Operations.path('/') only and
/// traverse the filesystem tree using Path::child().
/// Otherwise Operations::path() will be used with full pathes
/// and Path::child will never be called.
///
FileSystem(std::unique_ptr<Operations> op, bool full_tree);
~FileSystem();
void
mount(bfs::path const& where,
std::vector<std::string> const& options);
/// Unmount waiting gracefully for current operations to end.
void
unmount();
/// Kill current operations and the process loop. Use only while
/// unmounting.
void
kill();
std::shared_ptr<Path>
path(std::string const& path);
/*-----------------.
| Cache operations |
`-----------------*/
public:
std::shared_ptr<Path>
extract(std::string const& path);
std::shared_ptr<Path>
set(std::string const& path,
std::shared_ptr<Path> new_content);
std::shared_ptr<Path>
get(std::string const& path);
/*---------.
| Waitable |
`---------*/
protected:
virtual
bool
_wait(Thread* thread, Waker const& waker) override;
/*--------.
| Details |
`--------*/
private:
ELLE_ATTRIBUTE_R(FileSystemImpl*, impl);
std::shared_ptr<Path>
fetch_recurse(std::string path);
ELLE_ATTRIBUTE_RX(std::unique_ptr<Operations>, operations);
ELLE_ATTRIBUTE_R(std::vector<std::string>, mount_options);
ELLE_ATTRIBUTE_RW(bool, full_tree);
std::string _where;
std::unordered_map<std::string, std::shared_ptr<Path>> _cache;
};
/// Handle implementation reading/writing to the local filesystem
class BindHandle: public Handle
{
public:
BindHandle(int fd, bfs::path);
int
read(elle::WeakBuffer buffer, size_t size, off_t offset) override;
int
write(elle::ConstWeakBuffer buffer, size_t size, off_t offset) override;
void
ftruncate(off_t offset) override;
void
close() override;
protected:
int _fd;
bfs::path _where;
};
class BindOperations
: public Operations
{
public:
BindOperations(bfs::path source);
std::shared_ptr<Path>
path(std::string const& path) override;
ELLE_ATTRIBUTE_R(bfs::path, source);
};
/// Default Path implementation acting on the local filesystem.
class BindPath
: public Path
{
public:
BindPath(bfs::path const& where,
BindOperations& ops);
void
stat(struct stat*) override;
void
list_directory(OnDirectoryEntry cb) override;
std::unique_ptr<Handle>
open(int flags, mode_t mode) override;
void
unlink() override;
void
mkdir(mode_t mode) override;
void
rmdir() override;
void
rename(bfs::path const& where) override;
bfs::path
readlink() override;
void
symlink(bfs::path const& where) override;
void
link(bfs::path const& where) override;
void
chmod(mode_t mode) override;
void
chown(int uid, int gid) override;
void
statfs(struct statvfs *) override;
void
utimens(const struct timespec tv[2]) override;
void
truncate(off_t new_size) override;
/// Return a Path for given child name.
std::shared_ptr<Path>
child(std::string const& name) override;
virtual
std::unique_ptr<BindHandle>
make_handle(bfs::path& where, int fd);
private:
ELLE_ATTRIBUTE_R(bfs::path, where);
ELLE_ATTRIBUTE_R(BindOperations&, ops);
};
std::unique_ptr<Operations> install_journal(std::unique_ptr<Operations> backend,
std::string const& path);
}
}
}