blob: e531a0a2b1404593f7ad75d62f7c4abb7b258452 [file] [log] [blame]
Narayan Kamathaef84a12020-01-02 15:20:13 +00001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specic language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef MEDIA_PROVIDER_JNI_NODE_INL_H_
18#define MEDIA_PROVIDER_JNI_NODE_INL_H_
19
20#include <android-base/logging.h>
21
Biswarup Pal93f4ec12021-02-15 13:39:36 +000022#include <sys/types.h>
Zimbb7c3762020-09-23 13:50:08 +010023#include <atomic>
Nikita Ioffe890e6f22020-06-18 17:35:08 +010024#include <cstdint>
25#include <limits>
Narayan Kamathaef84a12020-01-02 15:20:13 +000026#include <list>
27#include <memory>
28#include <mutex>
Nikita Ioffe890e6f22020-06-18 17:35:08 +010029#include <set>
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +000030#include <sstream>
Narayan Kamathaef84a12020-01-02 15:20:13 +000031#include <string>
Narayan Kamath568f17a2020-02-19 13:45:29 +000032#include <unordered_set>
Nikita Ioffe890e6f22020-06-18 17:35:08 +010033#include <utility>
Narayan Kamathaef84a12020-01-02 15:20:13 +000034#include <vector>
35
36#include "libfuse_jni/ReaddirHelper.h"
37#include "libfuse_jni/RedactionInfo.h"
38
39class NodeTest;
40
41namespace mediaprovider {
42namespace fuse {
43
44struct handle {
Manish Singh9a6ccce2021-02-05 23:50:08 +000045 explicit handle(int fd, const RedactionInfo* ri, bool cached, bool passthrough, uid_t uid,
46 uid_t transforms_uid)
47 : fd(fd),
48 ri(ri),
49 cached(cached),
50 passthrough(passthrough),
51 uid(uid),
52 transforms_uid(transforms_uid) {
Narayan Kamathbd22bb02020-01-08 16:02:50 +000053 CHECK(ri != nullptr);
54 }
55
Narayan Kamathbd22bb02020-01-08 16:02:50 +000056 const int fd;
57 const std::unique_ptr<const RedactionInfo> ri;
58 const bool cached;
Zim148cbe22020-11-17 15:58:29 +000059 const bool passthrough;
Zim9aa6f542020-10-19 15:39:33 +010060 const uid_t uid;
Manish Singh9a6ccce2021-02-05 23:50:08 +000061 const uid_t transforms_uid;
Narayan Kamathaef84a12020-01-02 15:20:13 +000062
63 ~handle() { close(fd); }
64};
65
66struct dirhandle {
Narayan Kamathbd22bb02020-01-08 16:02:50 +000067 explicit dirhandle(DIR* dir) : d(dir), next_off(0) { CHECK(dir != nullptr); }
Narayan Kamathaef84a12020-01-02 15:20:13 +000068
69 DIR* const d;
70 off_t next_off;
71 // Fuse readdir() is called multiple times based on the size of the buffer and
72 // number of directory entries in the given directory. 'de' holds the list
73 // of directory entries for the directory handle and this list is available
74 // across subsequent readdir() calls for the same directory handle.
75 std::vector<std::shared_ptr<DirectoryEntry>> de;
76
77 ~dirhandle() { closedir(d); }
78};
79
Narayan Kamath568f17a2020-02-19 13:45:29 +000080// Whether inode tracking is enabled or not. When enabled, we maintain a
81// separate mapping from inode numbers to "live" nodes so we can detect when
82// we receive a request to a node that has been deleted.
83static constexpr bool kEnableInodeTracking = true;
84
85class node;
86
87// Tracks the set of active nodes associated with a FUSE instance so that we
88// can assert that we only ever return an active node in response to a lookup.
89class NodeTracker {
90 public:
Nandana Duttaa76d1e2020-04-29 09:42:42 +010091 explicit NodeTracker(std::recursive_mutex* lock) : lock_(lock) {}
Narayan Kamath568f17a2020-02-19 13:45:29 +000092
93 void CheckTracked(__u64 ino) const {
94 if (kEnableInodeTracking) {
95 const node* node = reinterpret_cast<const class node*>(ino);
96 std::lock_guard<std::recursive_mutex> guard(*lock_);
97 CHECK(active_nodes_.find(node) != active_nodes_.end());
98 }
99 }
100
101 void NodeDeleted(const node* node) {
102 if (kEnableInodeTracking) {
103 std::lock_guard<std::recursive_mutex> guard(*lock_);
104 LOG(DEBUG) << "Node: " << reinterpret_cast<uintptr_t>(node) << " deleted.";
105
106 CHECK(active_nodes_.find(node) != active_nodes_.end());
107 active_nodes_.erase(node);
108 }
109 }
110
111 void NodeCreated(const node* node) {
112 if (kEnableInodeTracking) {
113 std::lock_guard<std::recursive_mutex> guard(*lock_);
114 LOG(DEBUG) << "Node: " << reinterpret_cast<uintptr_t>(node) << " created.";
115
116 CHECK(active_nodes_.find(node) == active_nodes_.end());
117 active_nodes_.insert(node);
118 }
119 }
120
121 private:
122 std::recursive_mutex* lock_;
123 std::unordered_set<const node*> active_nodes_;
124};
125
Narayan Kamathaef84a12020-01-02 15:20:13 +0000126class node {
127 public:
128 // Creates a new node with the specified parent, name and lock.
Zimbb7c3762020-09-23 13:50:08 +0100129 static node* Create(node* parent, const std::string& name, const std::string& io_path,
Zimded1ab92021-01-15 10:36:17 +0000130 bool should_invalidate, bool transforms_complete, const int transforms,
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000131 const int transforms_reason, std::recursive_mutex* lock, ino_t ino,
Zim801d9852021-01-26 18:30:53 +0000132 NodeTracker* tracker) {
Narayan Kamath568f17a2020-02-19 13:45:29 +0000133 // Place the entire constructor under a critical section to make sure
134 // node creation, tracking (if enabled) and the addition to a parent are
135 // atomic.
136 std::lock_guard<std::recursive_mutex> guard(*lock);
Zimded1ab92021-01-15 10:36:17 +0000137 return new node(parent, name, io_path, should_invalidate, transforms_complete, transforms,
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000138 transforms_reason, lock, ino, tracker);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000139 }
140
141 // Creates a new root node. Root nodes have no parents by definition
142 // and their "name" must signify an absolute path.
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000143 static node* CreateRoot(const std::string& path, std::recursive_mutex* lock, ino_t ino,
Narayan Kamath568f17a2020-02-19 13:45:29 +0000144 NodeTracker* tracker) {
145 std::lock_guard<std::recursive_mutex> guard(*lock);
Zimded1ab92021-01-15 10:36:17 +0000146 node* root = new node(nullptr, path, path, false /* should_invalidate */,
Zim801d9852021-01-26 18:30:53 +0000147 true /* transforms_complete */, 0 /* transforms */,
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000148 0 /* transforms_reason */, lock, ino, tracker);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000149
150 // The root always has one extra reference to avoid it being
151 // accidentally collected.
152 root->Acquire();
153 return root;
154 }
155
156 // Maps an inode to its associated node.
Narayan Kamath568f17a2020-02-19 13:45:29 +0000157 static inline node* FromInode(__u64 ino, const NodeTracker* tracker) {
158 tracker->CheckTracked(ino);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000159 return reinterpret_cast<node*>(static_cast<uintptr_t>(ino));
160 }
161
162 // Maps a node to its associated inode.
163 static __u64 ToInode(node* node) {
164 return static_cast<__u64>(reinterpret_cast<uintptr_t>(node));
165 }
166
Narayan Kamathaef84a12020-01-02 15:20:13 +0000167 // Releases a reference to a node. Returns true iff the refcount dropped to
168 // zero as a result of this call to Release, meaning that it's no longer
169 // safe to perform any operations on references to this node.
170 bool Release(uint32_t count) {
171 std::lock_guard<std::recursive_mutex> guard(*lock_);
172 if (refcount_ >= count) {
173 refcount_ -= count;
174 if (refcount_ == 0) {
175 delete this;
176 return true;
177 }
178 } else {
179 LOG(ERROR) << "Mismatched reference count: refcount_ = " << this->refcount_
180 << " ,count = " << count;
181 }
182
183 return false;
184 }
185
186 // Builds the full path associated with this node, including all path segments
187 // associated with its descendants.
188 std::string BuildPath() const;
189
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +0000190 // Builds the full PII safe path associated with this node, including all path segments
191 // associated with its descendants.
192 std::string BuildSafePath() const;
193
Zimd2b59b42021-01-12 17:06:10 +0000194 // Looks up a direct descendant of this node by case-insensitive |name|. If |acquire| is true,
Narayan Kamatheca34252020-02-11 13:08:37 +0000195 // also Acquire the node before returning a reference to it.
Zimd2b59b42021-01-12 17:06:10 +0000196 // |transforms| is an opaque flag that is used to distinguish multiple nodes sharing the same
197 // |name| but requiring different IO transformations as determined by the MediaProvider.
Zimbb7c3762020-09-23 13:50:08 +0100198 node* LookupChildByName(const std::string& name, bool acquire, const int transforms = 0) const {
199 return ForChild(name, [acquire, transforms](node* child) {
200 if (child->transforms_ == transforms) {
201 if (acquire) {
202 child->Acquire();
203 }
204 return true;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000205 }
Zimbb7c3762020-09-23 13:50:08 +0100206 return false;
Zim53c2d702020-09-23 12:18:27 +0100207 });
Narayan Kamathaef84a12020-01-02 15:20:13 +0000208 }
209
Zim53c2d702020-09-23 12:18:27 +0100210 // Marks this node children as deleted. They are still associated with their parent, and
211 // all open handles etc. to the deleted nodes are preserved until their refcount goes
Narayan Kamathaef84a12020-01-02 15:20:13 +0000212 // to zero.
Zim53c2d702020-09-23 12:18:27 +0100213 void SetDeletedForChild(const std::string& name) {
214 ForChild(name, [](node* child) {
215 child->SetDeleted();
216 return false;
217 });
218 }
219
Narayan Kamathaef84a12020-01-02 15:20:13 +0000220 void SetDeleted() {
221 std::lock_guard<std::recursive_mutex> guard(*lock_);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000222 deleted_ = true;
223 }
224
Zim53c2d702020-09-23 12:18:27 +0100225 void RenameChild(const std::string& old_name, const std::string& new_name, node* new_parent) {
226 ForChild(old_name, [=](node* child) {
227 child->Rename(new_name, new_parent);
228 return false;
229 });
230 }
231
Narayan Kamathaef84a12020-01-02 15:20:13 +0000232 void Rename(const std::string& name, node* new_parent) {
Narayan Kamathaef84a12020-01-02 15:20:13 +0000233 std::lock_guard<std::recursive_mutex> guard(*lock_);
234
Zim87c7bf82020-01-07 18:11:27 +0000235 if (new_parent != parent_) {
236 RemoveFromParent();
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100237 name_ = name;
Zim87c7bf82020-01-07 18:11:27 +0000238 AddToParent(new_parent);
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100239 return;
240 }
241
242 // Changing name_ will change the expected position of this node in parent's set of
243 // children. Consider following scenario:
244 // 1. This node: "b"; parent's set: {"a", "b", "c"}
245 // 2. Rename("b", "d")
246 //
247 // After rename, parent's set should become: {"a", "b", "d"}, but if we simply change the
248 // name it will be {"a", "d", "b"}, which violates properties of the set.
249 //
250 // To make sure that parent's set is always valid, changing name is 3 steps procedure:
251 // 1. Remove this node from parent's set.
252 // 2 Change the name.
253 // 3. Add it back to the set.
254 // Rename of node without changing its parent. Still need to remove and re-add it to make
255 // sure lookup index is correct.
256 if (name_ != name) {
257 // If this is a root node, simply rename it.
258 if (parent_ == nullptr) {
259 name_ = name;
260 return;
261 }
262
263 auto it = parent_->children_.find(this);
264 CHECK(it != parent_->children_.end());
265 parent_->children_.erase(it);
266
267 name_ = name;
268
269 parent_->children_.insert(this);
Zim87c7bf82020-01-07 18:11:27 +0000270 }
Narayan Kamathaef84a12020-01-02 15:20:13 +0000271 }
272
273 const std::string& GetName() const {
274 std::lock_guard<std::recursive_mutex> guard(*lock_);
275 return name_;
276 }
277
Zimbb7c3762020-09-23 13:50:08 +0100278 const std::string& GetIoPath() const { return io_path_; }
279
280 int GetTransforms() const { return transforms_; }
281
Zim801d9852021-01-26 18:30:53 +0000282 int GetTransformsReason() const { return transforms_reason_; }
283
Zimbb7c3762020-09-23 13:50:08 +0100284 bool IsTransformsComplete() const {
285 return transforms_complete_.load(std::memory_order_acquire);
286 }
287
Zime5433682021-03-10 12:06:54 +0000288 void SetTransformsComplete(bool complete) {
289 transforms_complete_.store(complete, std::memory_order_release);
290 }
Zimbb7c3762020-09-23 13:50:08 +0100291
Zima76c3492020-02-19 01:23:26 +0000292 node* GetParent() const {
293 std::lock_guard<std::recursive_mutex> guard(*lock_);
294 return parent_;
295 }
296
Narayan Kamathaef84a12020-01-02 15:20:13 +0000297 inline void AddHandle(handle* h) {
298 std::lock_guard<std::recursive_mutex> guard(*lock_);
299 handles_.emplace_back(std::unique_ptr<handle>(h));
300 }
301
302 void DestroyHandle(handle* h) {
303 std::lock_guard<std::recursive_mutex> guard(*lock_);
304
305 auto comp = [h](const std::unique_ptr<handle>& ptr) { return ptr.get() == h; };
306 auto it = std::find_if(handles_.begin(), handles_.end(), comp);
307 CHECK(it != handles_.end());
308 handles_.erase(it);
309 }
310
311 bool HasCachedHandle() const {
312 std::lock_guard<std::recursive_mutex> guard(*lock_);
313
314 for (const auto& handle : handles_) {
315 if (handle->cached) {
316 return true;
317 }
318 }
319 return false;
320 }
321
Zimded1ab92021-01-15 10:36:17 +0000322 bool ShouldInvalidate() const {
Zimf2b47b42020-09-16 14:54:06 +0100323 std::lock_guard<std::recursive_mutex> guard(*lock_);
Zimded1ab92021-01-15 10:36:17 +0000324 return should_invalidate_;
Zimf2b47b42020-09-16 14:54:06 +0100325 }
326
Zimded1ab92021-01-15 10:36:17 +0000327 void SetShouldInvalidate() {
Zimf2b47b42020-09-16 14:54:06 +0100328 std::lock_guard<std::recursive_mutex> guard(*lock_);
Zimded1ab92021-01-15 10:36:17 +0000329 should_invalidate_ = true;
Zimf2b47b42020-09-16 14:54:06 +0100330 }
331
Zim329ba2c2020-09-16 14:23:26 +0100332 bool HasRedactedCache() const {
333 std::lock_guard<std::recursive_mutex> guard(*lock_);
334 return has_redacted_cache_;
335 }
336
337 void SetRedactedCache(bool state) {
338 std::lock_guard<std::recursive_mutex> guard(*lock_);
339 has_redacted_cache_ = state;
340 }
341
Narayan Kamathaef84a12020-01-02 15:20:13 +0000342 inline void AddDirHandle(dirhandle* d) {
343 std::lock_guard<std::recursive_mutex> guard(*lock_);
344
345 dirhandles_.emplace_back(std::unique_ptr<dirhandle>(d));
346 }
347
348 void DestroyDirHandle(dirhandle* d) {
349 std::lock_guard<std::recursive_mutex> guard(*lock_);
350
351 auto comp = [d](const std::unique_ptr<dirhandle>& ptr) { return ptr.get() == d; };
352 auto it = std::find_if(dirhandles_.begin(), dirhandles_.end(), comp);
353 CHECK(it != dirhandles_.end());
354 dirhandles_.erase(it);
355 }
356
357 // Deletes the tree of nodes rooted at |tree|.
358 static void DeleteTree(node* tree);
359
360 // Looks up an absolute path rooted at |root|, or nullptr if no such path
361 // through the hierarchy exists.
362 static const node* LookupAbsolutePath(const node* root, const std::string& absolute_path);
363
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000364 // Looks up for the node with the given ino rooted at |root|, or nullptr if no such node exists.
365 static const node* LookupInode(const node* root, ino_t ino);
366
Narayan Kamathaef84a12020-01-02 15:20:13 +0000367 private:
Zimded1ab92021-01-15 10:36:17 +0000368 node(node* parent, const std::string& name, const std::string& io_path,
369 const bool should_invalidate, const bool transforms_complete, const int transforms,
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000370 const int transforms_reason, std::recursive_mutex* lock, ino_t ino, NodeTracker* tracker)
Narayan Kamath568f17a2020-02-19 13:45:29 +0000371 : name_(name),
Zimbb7c3762020-09-23 13:50:08 +0100372 io_path_(io_path),
373 transforms_complete_(transforms_complete),
374 transforms_(transforms),
Zim801d9852021-01-26 18:30:53 +0000375 transforms_reason_(transforms_reason),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000376 refcount_(0),
377 parent_(nullptr),
Zim329ba2c2020-09-16 14:23:26 +0100378 has_redacted_cache_(false),
Zimded1ab92021-01-15 10:36:17 +0000379 should_invalidate_(should_invalidate),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000380 deleted_(false),
381 lock_(lock),
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000382 ino_(ino),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000383 tracker_(tracker) {
384 tracker_->NodeCreated(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000385 Acquire();
386 // This is a special case for the root node. All other nodes will have a
387 // non-null parent.
388 if (parent != nullptr) {
389 AddToParent(parent);
390 }
Zimded1ab92021-01-15 10:36:17 +0000391 // If the node requires transforms, we MUST never cache it in the VFS
392 if (transforms) {
393 CHECK(should_invalidate_);
394 }
Narayan Kamathaef84a12020-01-02 15:20:13 +0000395 }
396
Narayan Kamatheca34252020-02-11 13:08:37 +0000397 // Acquires a reference to a node. This maps to the "lookup count" specified
398 // by the FUSE documentation and must only happen under the circumstances
399 // documented in libfuse/include/fuse_lowlevel.h.
400 inline void Acquire() {
401 std::lock_guard<std::recursive_mutex> guard(*lock_);
402 refcount_++;
403 }
404
Narayan Kamathaef84a12020-01-02 15:20:13 +0000405 // Adds this node to a specified parent.
406 void AddToParent(node* parent) {
407 std::lock_guard<std::recursive_mutex> guard(*lock_);
408 // This method assumes this node is currently unparented.
409 CHECK(parent_ == nullptr);
410 // Check that the new parent isn't nullptr either.
411 CHECK(parent != nullptr);
412
413 parent_ = parent;
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100414 parent_->children_.insert(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000415
416 // TODO(narayan, zezeozue): It's unclear why we need to call Acquire on the
417 // parent node when we're adding a child to it.
418 parent_->Acquire();
419 }
420
421 // Removes this node from its current parent, and set its parent to nullptr.
422 void RemoveFromParent() {
423 std::lock_guard<std::recursive_mutex> guard(*lock_);
424
425 if (parent_ != nullptr) {
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100426 auto it = parent_->children_.find(this);
427 CHECK(it != parent_->children_.end());
428 parent_->children_.erase(it);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000429
Narayan Kamathaef84a12020-01-02 15:20:13 +0000430 parent_->Release(1);
431 parent_ = nullptr;
432 }
433 }
434
Zim53c2d702020-09-23 12:18:27 +0100435 // Finds *all* non-deleted nodes matching |name| and runs the function |callback| on each
436 // node until |callback| returns true.
437 // When |callback| returns true, the matched node is returned
438 node* ForChild(const std::string& name, const std::function<bool(node*)>& callback) const {
439 std::lock_guard<std::recursive_mutex> guard(*lock_);
440
441 // lower_bound will give us the first child with strcasecmp(child->name, name) >=0.
442 // For more context see comment on the NodeCompare struct.
443 auto start = children_.lower_bound(std::make_pair(name, 0));
444 // upper_bound will give us the first child with strcasecmp(child->name, name) > 0
445 auto end =
446 children_.upper_bound(std::make_pair(name, std::numeric_limits<uintptr_t>::max()));
447
448 // Make a copy of the matches because calling callback might modify the list which will
449 // cause issues while iterating over them.
450 std::vector<node*> children(start, end);
451
452 for (node* child : children) {
453 if (!child->deleted_ && callback(child)) {
454 return child;
455 }
456 }
457
458 return nullptr;
459 }
460
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100461 // A custom heterogeneous comparator used for set of this node's children_ to speed up child
462 // node by name lookups.
463 //
464 // This comparator treats node* as pair (node->name_, node): two nodes* are first
465 // compared by their name using case-insenstive comparison function. If their names are equal,
466 // then pointers are compared as integers.
467 //
468 // See LookupChildByName function to see how this comparator is used.
469 //
470 // Note that it's important to first compare by name_, since it will make all nodes with same
471 // name (compared using strcasecmp) together, which allows LookupChildByName function to find
472 // range of the candidate nodes by issuing two binary searches.
473 struct NodeCompare {
474 using is_transparent = void;
475
476 bool operator()(const node* lhs, const node* rhs) const {
477 int cmp = strcasecmp(lhs->name_.c_str(), rhs->name_.c_str());
478 if (cmp != 0) {
479 return cmp < 0;
480 }
481 return reinterpret_cast<uintptr_t>(lhs) < reinterpret_cast<uintptr_t>(rhs);
482 }
483
484 bool operator()(const node* lhs, const std::pair<std::string, uintptr_t>& rhs) const {
485 int cmp = strcasecmp(lhs->name_.c_str(), rhs.first.c_str());
486 if (cmp != 0) {
487 return cmp < 0;
488 }
489 return reinterpret_cast<uintptr_t>(lhs) < rhs.second;
490 }
491
492 bool operator()(const std::pair<std::string, uintptr_t>& lhs, const node* rhs) const {
493 int cmp = strcasecmp(lhs.first.c_str(), rhs->name_.c_str());
494 if (cmp != 0) {
495 return cmp < 0;
496 }
497 return lhs.second < reinterpret_cast<uintptr_t>(rhs);
498 }
499 };
500
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +0000501 // A helper function to recursively construct the absolute path of a given node.
502 // If |safe| is true, builds a PII safe path instead
503 void BuildPathForNodeRecursive(bool safe, const node* node, std::stringstream* path) const;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000504
505 // The name of this node. Non-const because it can change during renames.
506 std::string name_;
Zimbb7c3762020-09-23 13:50:08 +0100507 // Filesystem path that will be used for IO (if it is non-empty) instead of node->BuildPath
508 const std::string io_path_;
509 // Whether any transforms required on |io_path_| are complete.
510 // If false, might need to call a node transform function with |transforms| below
511 std::atomic_bool transforms_complete_;
Zim801d9852021-01-26 18:30:53 +0000512 // Opaque flags that determines the 'required' transforms to perform on node
513 // before IO. These flags should not be interpreted in native but should be passed to the
514 // MediaProvider as part of a transform function and if successful, |transforms_complete_|
515 // should be set to true
Zimbb7c3762020-09-23 13:50:08 +0100516 const int transforms_;
Zim801d9852021-01-26 18:30:53 +0000517 // Opaque value indicating the reason why transforms are required.
518 // This value should not be interpreted in native but should be passed to the MediaProvider
519 // as part of a transform function
520 const int transforms_reason_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000521 // The reference count for this node. Guarded by |lock_|.
522 uint32_t refcount_;
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100523 // Set of children of this node. All of them contain a back reference
Narayan Kamathaef84a12020-01-02 15:20:13 +0000524 // to their parent. Guarded by |lock_|.
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100525 std::set<node*, NodeCompare> children_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000526 // Containing directory for this node. Guarded by |lock_|.
527 node* parent_;
528 // List of file handles associated with this node. Guarded by |lock_|.
529 std::vector<std::unique_ptr<handle>> handles_;
530 // List of directory handles associated with this node. Guarded by |lock_|.
531 std::vector<std::unique_ptr<dirhandle>> dirhandles_;
Zim329ba2c2020-09-16 14:23:26 +0100532 bool has_redacted_cache_;
Zimded1ab92021-01-15 10:36:17 +0000533 bool should_invalidate_;
Zim329ba2c2020-09-16 14:23:26 +0100534 bool deleted_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000535 std::recursive_mutex* lock_;
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000536 // Inode number of the file represented by this node.
537 const ino_t ino_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000538
Narayan Kamath568f17a2020-02-19 13:45:29 +0000539 NodeTracker* const tracker_;
540
Narayan Kamathaef84a12020-01-02 15:20:13 +0000541 ~node() {
542 RemoveFromParent();
543
544 handles_.clear();
545 dirhandles_.clear();
Narayan Kamath568f17a2020-02-19 13:45:29 +0000546
547 tracker_->NodeDeleted(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000548 }
549
550 friend class ::NodeTest;
551};
552
553} // namespace fuse
554} // namespace mediaprovider
555
556#endif // MEDIA_PROVIDER_JNI_MODE_INL_H_