Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/wasmfs/virtual.h
6174 views
1
// Copyright 2022 The Emscripten Authors. All rights reserved.
2
// Emscripten is available under two separate licenses, the MIT license and the
3
// University of Illinois/NCSA Open Source License. Both these licenses can be
4
// found in the LICENSE file.
5
6
// Utilities for creating virtual backends that forward operations to underlying
7
// "real" files. Virtual backends must wrap all underlying files, even if the
8
// wrapper is a no-op, so that no part of the system observes mixed backends. To
9
// the backend-independent code, the root directory of the virtual backend and
10
// all of its descendants must appear to have the same virtual backend. To the
11
// underlying "real" backend, all of its files must appear to have parents of
12
// the same real backend. Without these invariants, renames would not work
13
// correctly and without wrapping all files, these invariants would not be
14
// upheld.
15
16
#pragma once
17
18
#include "file.h"
19
20
namespace wasmfs {
21
22
static inline std::shared_ptr<File> devirtualize(std::shared_ptr<File>);
23
24
class VirtualDataFile : public DataFile {
25
protected:
26
std::shared_ptr<DataFile> real;
27
28
public:
29
VirtualDataFile(std::shared_ptr<DataFile> real, backend_t backend)
30
: DataFile(real->locked().getMode(), backend), real(real) {}
31
32
protected:
33
virtual off_t getSize() override { return real->locked().getSize(); }
34
virtual int open(oflags_t flags) override {
35
return real->locked().open(flags);
36
}
37
virtual int close() override { return real->locked().close(); }
38
virtual ssize_t read(uint8_t* buf, size_t len, off_t offset) override {
39
return real->locked().read(buf, len, offset);
40
}
41
virtual ssize_t write(const uint8_t* buf, size_t len, off_t offset) override {
42
return real->locked().write(buf, len, offset);
43
}
44
virtual int setSize(off_t size) override {
45
return real->locked().setSize(size);
46
}
47
virtual int flush() override { return real->locked().flush(); }
48
49
friend std::shared_ptr<File> devirtualize(std::shared_ptr<File>);
50
};
51
52
// Forward operations through Directory::Handle to get the proper dcache logic.
53
class VirtualDirectory : public Directory {
54
protected:
55
std::shared_ptr<Directory> real;
56
57
public:
58
VirtualDirectory(std::shared_ptr<Directory> real, backend_t backend)
59
: Directory(real->locked().getMode(), backend), real(real) {}
60
61
protected:
62
virtual std::shared_ptr<File> getChild(const std::string& name) override {
63
return real->locked().getChild(name);
64
}
65
virtual std::shared_ptr<DataFile> insertDataFile(const std::string& name,
66
mode_t mode) override {
67
return real->locked().insertDataFile(name, mode);
68
}
69
virtual std::shared_ptr<Directory> insertDirectory(const std::string& name,
70
mode_t mode) override {
71
return real->locked().insertDirectory(name, mode);
72
}
73
virtual std::shared_ptr<Symlink>
74
insertSymlink(const std::string& name, const std::string& target) override {
75
return real->locked().insertSymlink(name, target);
76
}
77
virtual int insertMove(const std::string& name,
78
std::shared_ptr<File> file) override {
79
return real->locked().insertMove(name, file);
80
}
81
virtual int removeChild(const std::string& name) override {
82
return real->locked().removeChild(name);
83
}
84
virtual ssize_t getNumEntries() override {
85
return real->locked().getNumEntries();
86
}
87
virtual MaybeEntries getEntries() override {
88
return real->locked().getEntries();
89
}
90
virtual std::string getName(std::shared_ptr<File> file) override {
91
return real->locked().getName(file);
92
}
93
94
friend std::shared_ptr<File> devirtualize(std::shared_ptr<File>);
95
};
96
97
class VirtualSymlink : public Symlink {
98
protected:
99
std::shared_ptr<Symlink> real;
100
101
public:
102
VirtualSymlink(std::shared_ptr<Symlink> real, backend_t backend)
103
: Symlink(backend), real(real) {}
104
105
protected:
106
virtual std::string getTarget() const override { return real->getTarget(); }
107
108
friend std::shared_ptr<File> devirtualize(std::shared_ptr<File>);
109
};
110
111
// Unwrap a virtual file and get the underlying real file of the same kind.
112
inline std::shared_ptr<File> devirtualize(std::shared_ptr<File> file) {
113
if (file->is<DataFile>()) {
114
return std::static_pointer_cast<VirtualDataFile>(file)->real;
115
} else if (file->is<Directory>()) {
116
return std::static_pointer_cast<VirtualDirectory>(file)->real;
117
} else if (file->is<Symlink>()) {
118
return std::static_pointer_cast<VirtualDirectory>(file)->real;
119
}
120
WASMFS_UNREACHABLE("unexpected file kind");
121
}
122
123
} // namespace wasmfs
124
125