-
Notifications
You must be signed in to change notification settings - Fork 671
/
Copy pathvfs.h
324 lines (268 loc) · 10.5 KB
/
vfs.h
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
/*
* Copyright (C) by Christian Kamm <mail@ckamm.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#pragma once
#include "assert.h"
#include "csync/csync.h"
#include "libsync/accountfwd.h"
#include "ocsynclib.h"
#include "pinstate.h"
#include "result.h"
#include "syncfilestatus.h"
#include "utility.h"
#include <QObject>
#include <QScopedPointer>
#include <QSharedPointer>
#include <QUrl>
#include <QVersionNumber>
#include <memory>
namespace OCC {
class Account;
class SyncJournalDb;
class SyncFileItem;
class SyncEngine;
/** Collection of parameters for initializing a Vfs instance. */
struct OCSYNC_EXPORT VfsSetupParams
{
explicit VfsSetupParams(const AccountPtr &account, const QUrl &baseUrl, bool groupInSidebar, SyncEngine *syncEngine);
/** The full path to the folder on the local filesystem
*
* Always ends with /.
*/
QString filesystemPath;
/** The path to the synced folder on the account
*
* Always ends with /.
*/
QString remotePath;
/// Account url, credentials etc for network calls
AccountPtr account;
/** Access to the sync folder's database.
*
* Note: The journal must live at least until the Vfs::stop() call.
*/
SyncJournalDb *journal = nullptr;
/// Strings potentially passed on to the platform
QString providerDisplayName;
QString providerName;
QVersionNumber providerVersion;
/** when registering with the system we might use
* a different presentaton to identify the accounts
*/
bool multipleAccountsRegistered = false;
const QUrl &baseUrl() const
{
return _baseUrl;
}
bool groupInSidebar() const
{
return _groupInSidebar;
}
SyncEngine *syncEngine() const;
private:
QUrl _baseUrl;
bool _groupInSidebar = false;
SyncEngine *_syncEngine;
};
/** Interface describing how to deal with virtual/placeholder files.
*
* There are different ways of representing files locally that will only
* be filled with data (hydrated) on demand. One such way would be suffixed
* files, others could be FUSE based or use Windows CfAPI.
*
* This interface intends to decouple the sync algorithm and Folder from
* the details of how a particular VFS solution works.
*
* An instance is usually created through a plugin via the createVfsFromPlugin()
* function.
*/
class OCSYNC_EXPORT Vfs : public QObject
{
Q_OBJECT
public:
/** The kind of VFS in use (or no-VFS)
*
* Currently plugins and modes are one-to-one but that's not required.
*/
enum Mode {
Off,
WithSuffix,
WindowsCfApi
};
Q_ENUM(Mode)
enum class ConvertToPlaceholderResult {
Ok,
Locked
};
Q_ENUM(ConvertToPlaceholderResult)
static Optional<Mode> modeFromString(const QString &str);
static Result<void, QString> checkAvailability(const QString &path, OCC::Vfs::Mode mode);
enum class AvailabilityError
{
// Availability can't be retrieved due to db error
DbError,
// Availability not available since the item doesn't exist
NoSuchItem,
};
using AvailabilityResult = Result<VfsItemAvailability, AvailabilityError>;
public:
explicit Vfs(QObject* parent = nullptr);
~Vfs() override;
virtual Mode mode() const = 0;
/// For WithSuffix modes: the suffix (including the dot)
virtual QString fileSuffix() const = 0;
/// The fileName without fileSuffix
/// TODO: better naming welcome
virtual QString underlyingFileName(const QString &fileName) const;
/// Access to the parameters the instance was start()ed with.
const VfsSetupParams ¶ms() const { return *_setupParams.get(); }
/** Initializes interaction with the VFS provider.
*
* The plugin-specific work is done in startImpl().
*
* \warning Please read the comments to \a startImpl() about the
* asynchronous behaviour!
*/
void start(const VfsSetupParams ¶ms);
/// Stop interaction with VFS provider. Like when the client application quits.
virtual void stop() = 0;
/// Deregister the folder with the sync provider, like when a folder is removed.
virtual void unregisterFolder() = 0;
/** Whether the socket api should show pin state options
*
* Some plugins might provide alternate shell integration, making the normal
* context menu actions redundant.
*/
virtual bool socketApiPinStateActionsShown() const = 0;
/// Create a new dehydrated placeholder. Called from PropagateDownload.
[[nodiscard]] virtual Result<void, QString> createPlaceholder(const SyncFileItem &item) = 0;
/** Discovery hook: even unchanged files may need UPDATE_METADATA.
*
* For instance cfapi vfs wants local hydrated non-placeholder files to
* become hydrated placeholder files.
*/
[[nodiscard]] virtual bool needsMetadataUpdate(const SyncFileItem &item) = 0;
/// Determine whether the file at the given absolute path is a dehydrated placeholder.
[[nodiscard]] virtual bool isDehydratedPlaceholder(const QString &filePath) = 0;
/** Similar to isDehydratedPlaceholder() but used from sync discovery.
*
* This function shall set stat->type if appropriate.
* It may rely on stat->path and stat_data (platform specific data).
*
* Returning true means that type was fully determined.
*/
[[nodiscard]] virtual bool statTypeVirtualFile(csync_file_stat_t *stat, void *stat_data) = 0;
/** Sets the pin state for the item at a path.
*
* The pin state is set on the item and for all items below it.
*
* Usually this would forward to setting the pin state flag in the db table,
* but some vfs plugins will store the pin state in file attributes instead.
*
* relFilePath is relative to the sync folder. Can be "" for root folder.
*/
[[nodiscard]] virtual bool setPinState(const QString &relFilePath, PinState state) = 0;
/** Returns the pin state of an item at a path.
*
* Usually backed by the db's effectivePinState() function but some vfs
* plugins will override it to retrieve the state from elsewhere.
*
* relFilePath is relative to the sync folder. Can be "" for root folder.
*
* Returns none on retrieval error.
*/
[[nodiscard]] virtual Optional<PinState> pinState(const QString &relFilePath) = 0;
/** Returns availability status of an item at a path.
*
* The availability is a condensed user-facing version of PinState. See
* VfsItemAvailability for details.
*
* folderPath is relative to the sync folder. Can be "" for root folder.
*/
[[nodiscard]] virtual AvailabilityResult availability(const QString &folderPath) = 0;
/** Removes all virtual file db entries and dehydrated local placeholders.
*
* Particularly useful when switching off vfs mode or switching to a
* different kind of vfs.
*/
void wipeDehydratedVirtualFiles();
public Q_SLOTS:
/** Update in-sync state based on SyncFileStatusTracker signal.
*
* For some vfs plugins the icons aren't based on SocketAPI but rather on data shared
* via the vfs plugin. The connection to SyncFileStatusTracker allows both to be based
* on the same data.
*/
virtual void fileStatusChanged(const QString &systemFileName, SyncFileStatus fileStatus) = 0;
Q_SIGNALS:
/// start complete
void started();
/// we encountered an error
void error(const QString &error);
/// The vfs plugin detected that the meta data are out of sync and requests a sync with the server
void needSync();
protected:
/** Update placeholder metadata during discovery.
*
* If the remote metadata changes, the local placeholder's metadata should possibly
* change as well.
*/
[[nodiscard]] virtual Result<ConvertToPlaceholderResult, QString> updateMetadata(const SyncFileItem &item, const QString &filePath, const QString &replacesFile) = 0;
/** Setup the plugin for the folder.
*
* For example, the VFS provider might monitor files to be able to start a file
* hydration (download of a file's remote contents) when the user wants to open
* it.
*
* Usually some registration needs to be done with the backend. This function
* should take care of it if necessary.
*
* \note The implementation is allowed to run asynchronously, meaning the method
* can return before the start is fully complete. On completion, the
* \a started() signal is emitted.
* \warning For VFS implementations: the rest of the code in the client assumes
* that it is safe to do multiple calls to this method, EVEN IF A PREVIOUS
* START IS NOT FULLY FINISHED. If ANY synchronization needs to be done
* (e.g. reading/writing to the Windows registry, or searching for
* StorageProvider information), this has to be implemented in the
* plugin itself.
*/
virtual void startImpl(const VfsSetupParams ¶ms) = 0;
// Db-backed pin state handling. Derived classes may use it to implement pin states.
bool setPinStateInDb(const QString &folderPath, PinState state);
Optional<PinState> pinStateInDb(const QString &folderPath);
AvailabilityResult availabilityInDb(const QString &folderPath);
private:
// the parameters passed to start()
std::unique_ptr<VfsSetupParams> _setupParams;
friend class OwncloudPropagator;
};
class OCSYNC_EXPORT VfsPluginManager
{
public:
/// Check whether the plugin for the mode is available.
bool isVfsPluginAvailable(Vfs::Mode mode) const;
/// Return the best available VFS mode.
Vfs::Mode bestAvailableVfsMode() const;
/// Create a VFS instance for the mode, returns nullptr on failure.
std::unique_ptr<Vfs> createVfsFromPlugin(Vfs::Mode mode) const;
static const VfsPluginManager &instance();
protected:
VfsPluginManager() = default;
private:
static VfsPluginManager *_instance;
mutable QMap<Vfs::Mode, bool> _pluginCache;
};
template <>
OCSYNC_EXPORT QString Utility::enumToString(Vfs::Mode mode);
} // namespace OCC