blob: 15844e3c9b71562aad9f7110d5fffa56c29f1257 [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
Zim4fd99fd2022-01-13 15:43:38 +000080/** Represents file open result from MediaProvider */
81struct FdAccessResult {
82 FdAccessResult(const std::string& file_path, const bool should_redact)
83 : file_path(file_path), should_redact(should_redact) {}
84
85 const std::string file_path;
86 const bool should_redact;
87};
88
Narayan Kamath568f17a2020-02-19 13:45:29 +000089// Whether inode tracking is enabled or not. When enabled, we maintain a
90// separate mapping from inode numbers to "live" nodes so we can detect when
91// we receive a request to a node that has been deleted.
92static constexpr bool kEnableInodeTracking = true;
93
94class node;
95
96// Tracks the set of active nodes associated with a FUSE instance so that we
97// can assert that we only ever return an active node in response to a lookup.
98class NodeTracker {
99 public:
Nandana Duttaa76d1e2020-04-29 09:42:42 +0100100 explicit NodeTracker(std::recursive_mutex* lock) : lock_(lock) {}
Narayan Kamath568f17a2020-02-19 13:45:29 +0000101
Alessio Balsini6e7d5942022-01-17 15:21:49 +0000102 bool Exists(__u64 ino) const {
103 if (kEnableInodeTracking) {
104 const node* node = reinterpret_cast<const class node*>(ino);
105 std::lock_guard<std::recursive_mutex> guard(*lock_);
106 return active_nodes_.find(node) != active_nodes_.end();
107 }
108 }
109
Narayan Kamath568f17a2020-02-19 13:45:29 +0000110 void CheckTracked(__u64 ino) const {
111 if (kEnableInodeTracking) {
112 const node* node = reinterpret_cast<const class node*>(ino);
113 std::lock_guard<std::recursive_mutex> guard(*lock_);
114 CHECK(active_nodes_.find(node) != active_nodes_.end());
115 }
116 }
117
118 void NodeDeleted(const node* node) {
119 if (kEnableInodeTracking) {
120 std::lock_guard<std::recursive_mutex> guard(*lock_);
121 LOG(DEBUG) << "Node: " << reinterpret_cast<uintptr_t>(node) << " deleted.";
122
123 CHECK(active_nodes_.find(node) != active_nodes_.end());
124 active_nodes_.erase(node);
125 }
126 }
127
128 void NodeCreated(const node* node) {
129 if (kEnableInodeTracking) {
130 std::lock_guard<std::recursive_mutex> guard(*lock_);
131 LOG(DEBUG) << "Node: " << reinterpret_cast<uintptr_t>(node) << " created.";
132
133 CHECK(active_nodes_.find(node) == active_nodes_.end());
134 active_nodes_.insert(node);
135 }
136 }
137
138 private:
139 std::recursive_mutex* lock_;
140 std::unordered_set<const node*> active_nodes_;
141};
142
Narayan Kamathaef84a12020-01-02 15:20:13 +0000143class node {
144 public:
145 // Creates a new node with the specified parent, name and lock.
Zimbb7c3762020-09-23 13:50:08 +0100146 static node* Create(node* parent, const std::string& name, const std::string& io_path,
Zimd37b9772021-10-13 19:43:37 +0100147 const bool transforms_complete, const int transforms,
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000148 const int transforms_reason, std::recursive_mutex* lock, ino_t ino,
Zim801d9852021-01-26 18:30:53 +0000149 NodeTracker* tracker) {
Narayan Kamath568f17a2020-02-19 13:45:29 +0000150 // Place the entire constructor under a critical section to make sure
151 // node creation, tracking (if enabled) and the addition to a parent are
152 // atomic.
153 std::lock_guard<std::recursive_mutex> guard(*lock);
Zimd37b9772021-10-13 19:43:37 +0100154 return new node(parent, name, io_path, transforms_complete, transforms, transforms_reason,
155 lock, ino, tracker);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000156 }
157
158 // Creates a new root node. Root nodes have no parents by definition
159 // and their "name" must signify an absolute path.
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000160 static node* CreateRoot(const std::string& path, std::recursive_mutex* lock, ino_t ino,
Narayan Kamath568f17a2020-02-19 13:45:29 +0000161 NodeTracker* tracker) {
162 std::lock_guard<std::recursive_mutex> guard(*lock);
Zimd37b9772021-10-13 19:43:37 +0100163 node* root = new node(nullptr, path, path, true /* transforms_complete */,
164 0 /* transforms */, 0 /* transforms_reason */, lock, ino, tracker);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000165
166 // The root always has one extra reference to avoid it being
167 // accidentally collected.
168 root->Acquire();
169 return root;
170 }
171
172 // Maps an inode to its associated node.
Narayan Kamath568f17a2020-02-19 13:45:29 +0000173 static inline node* FromInode(__u64 ino, const NodeTracker* tracker) {
174 tracker->CheckTracked(ino);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000175 return reinterpret_cast<node*>(static_cast<uintptr_t>(ino));
176 }
177
Alessio Balsini6e7d5942022-01-17 15:21:49 +0000178 // TODO(b/215235604)
179 static inline node* FromInodeNoThrow(__u64 ino, const NodeTracker* tracker) {
180 if (!tracker->Exists(ino)) return nullptr;
181 return reinterpret_cast<node*>(static_cast<uintptr_t>(ino));
182 }
183
Narayan Kamathaef84a12020-01-02 15:20:13 +0000184 // Maps a node to its associated inode.
185 static __u64 ToInode(node* node) {
186 return static_cast<__u64>(reinterpret_cast<uintptr_t>(node));
187 }
188
Narayan Kamathaef84a12020-01-02 15:20:13 +0000189 // Releases a reference to a node. Returns true iff the refcount dropped to
190 // zero as a result of this call to Release, meaning that it's no longer
191 // safe to perform any operations on references to this node.
192 bool Release(uint32_t count) {
193 std::lock_guard<std::recursive_mutex> guard(*lock_);
194 if (refcount_ >= count) {
195 refcount_ -= count;
196 if (refcount_ == 0) {
197 delete this;
198 return true;
199 }
200 } else {
201 LOG(ERROR) << "Mismatched reference count: refcount_ = " << this->refcount_
202 << " ,count = " << count;
203 }
204
205 return false;
206 }
207
208 // Builds the full path associated with this node, including all path segments
209 // associated with its descendants.
210 std::string BuildPath() const;
211
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +0000212 // Builds the full PII safe path associated with this node, including all path segments
213 // associated with its descendants.
214 std::string BuildSafePath() const;
215
Zimd2b59b42021-01-12 17:06:10 +0000216 // Looks up a direct descendant of this node by case-insensitive |name|. If |acquire| is true,
Narayan Kamatheca34252020-02-11 13:08:37 +0000217 // also Acquire the node before returning a reference to it.
Zimd2b59b42021-01-12 17:06:10 +0000218 // |transforms| is an opaque flag that is used to distinguish multiple nodes sharing the same
219 // |name| but requiring different IO transformations as determined by the MediaProvider.
Zimbb7c3762020-09-23 13:50:08 +0100220 node* LookupChildByName(const std::string& name, bool acquire, const int transforms = 0) const {
221 return ForChild(name, [acquire, transforms](node* child) {
222 if (child->transforms_ == transforms) {
223 if (acquire) {
224 child->Acquire();
225 }
226 return true;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000227 }
Zimbb7c3762020-09-23 13:50:08 +0100228 return false;
Zim53c2d702020-09-23 12:18:27 +0100229 });
Narayan Kamathaef84a12020-01-02 15:20:13 +0000230 }
231
Zim53c2d702020-09-23 12:18:27 +0100232 // Marks this node children as deleted. They are still associated with their parent, and
233 // all open handles etc. to the deleted nodes are preserved until their refcount goes
Narayan Kamathaef84a12020-01-02 15:20:13 +0000234 // to zero.
Zim53c2d702020-09-23 12:18:27 +0100235 void SetDeletedForChild(const std::string& name) {
236 ForChild(name, [](node* child) {
237 child->SetDeleted();
238 return false;
239 });
240 }
241
Narayan Kamathaef84a12020-01-02 15:20:13 +0000242 void SetDeleted() {
243 std::lock_guard<std::recursive_mutex> guard(*lock_);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000244 deleted_ = true;
245 }
246
Zim53c2d702020-09-23 12:18:27 +0100247 void RenameChild(const std::string& old_name, const std::string& new_name, node* new_parent) {
248 ForChild(old_name, [=](node* child) {
249 child->Rename(new_name, new_parent);
250 return false;
251 });
252 }
253
Narayan Kamathaef84a12020-01-02 15:20:13 +0000254 void Rename(const std::string& name, node* new_parent) {
Narayan Kamathaef84a12020-01-02 15:20:13 +0000255 std::lock_guard<std::recursive_mutex> guard(*lock_);
256
Zim87c7bf82020-01-07 18:11:27 +0000257 if (new_parent != parent_) {
258 RemoveFromParent();
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100259 name_ = name;
Zim87c7bf82020-01-07 18:11:27 +0000260 AddToParent(new_parent);
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100261 return;
262 }
263
264 // Changing name_ will change the expected position of this node in parent's set of
265 // children. Consider following scenario:
266 // 1. This node: "b"; parent's set: {"a", "b", "c"}
267 // 2. Rename("b", "d")
268 //
269 // After rename, parent's set should become: {"a", "b", "d"}, but if we simply change the
270 // name it will be {"a", "d", "b"}, which violates properties of the set.
271 //
272 // To make sure that parent's set is always valid, changing name is 3 steps procedure:
273 // 1. Remove this node from parent's set.
274 // 2 Change the name.
275 // 3. Add it back to the set.
276 // Rename of node without changing its parent. Still need to remove and re-add it to make
277 // sure lookup index is correct.
278 if (name_ != name) {
279 // If this is a root node, simply rename it.
280 if (parent_ == nullptr) {
281 name_ = name;
282 return;
283 }
284
285 auto it = parent_->children_.find(this);
286 CHECK(it != parent_->children_.end());
287 parent_->children_.erase(it);
288
289 name_ = name;
290
291 parent_->children_.insert(this);
Zim87c7bf82020-01-07 18:11:27 +0000292 }
Narayan Kamathaef84a12020-01-02 15:20:13 +0000293 }
294
295 const std::string& GetName() const {
296 std::lock_guard<std::recursive_mutex> guard(*lock_);
297 return name_;
298 }
299
Zimbb7c3762020-09-23 13:50:08 +0100300 const std::string& GetIoPath() const { return io_path_; }
301
302 int GetTransforms() const { return transforms_; }
303
Zim801d9852021-01-26 18:30:53 +0000304 int GetTransformsReason() const { return transforms_reason_; }
305
Zimbb7c3762020-09-23 13:50:08 +0100306 bool IsTransformsComplete() const {
307 return transforms_complete_.load(std::memory_order_acquire);
308 }
309
Zime5433682021-03-10 12:06:54 +0000310 void SetTransformsComplete(bool complete) {
311 transforms_complete_.store(complete, std::memory_order_release);
312 }
Zimbb7c3762020-09-23 13:50:08 +0100313
Zima76c3492020-02-19 01:23:26 +0000314 node* GetParent() const {
315 std::lock_guard<std::recursive_mutex> guard(*lock_);
316 return parent_;
317 }
318
Narayan Kamathaef84a12020-01-02 15:20:13 +0000319 inline void AddHandle(handle* h) {
320 std::lock_guard<std::recursive_mutex> guard(*lock_);
321 handles_.emplace_back(std::unique_ptr<handle>(h));
322 }
323
324 void DestroyHandle(handle* h) {
325 std::lock_guard<std::recursive_mutex> guard(*lock_);
326
327 auto comp = [h](const std::unique_ptr<handle>& ptr) { return ptr.get() == h; };
328 auto it = std::find_if(handles_.begin(), handles_.end(), comp);
329 CHECK(it != handles_.end());
330 handles_.erase(it);
331 }
332
333 bool HasCachedHandle() const {
334 std::lock_guard<std::recursive_mutex> guard(*lock_);
335
336 for (const auto& handle : handles_) {
337 if (handle->cached) {
338 return true;
339 }
340 }
341 return false;
342 }
343
Zim4fd99fd2022-01-13 15:43:38 +0000344 std::unique_ptr<FdAccessResult> CheckHandleForUid(const uid_t uid) const {
345 std::lock_guard<std::recursive_mutex> guard(*lock_);
346
347 bool found_handle = false;
348 bool redaction_not_needed = false;
349 for (const auto& handle : handles_) {
350 if (handle->uid == uid) {
351 found_handle = true;
352 redaction_not_needed |= !handle->ri->isRedactionNeeded();
353 }
354 }
355
356 if (found_handle) {
357 return std::make_unique<FdAccessResult>(BuildPath(), !redaction_not_needed);
358 }
359
360 return std::make_unique<FdAccessResult>(std::string(), false);
361 }
362
Zim809b4612021-04-19 10:39:45 +0100363 void SetName(std::string name) {
Zimf2b47b42020-09-16 14:54:06 +0100364 std::lock_guard<std::recursive_mutex> guard(*lock_);
Zim809b4612021-04-19 10:39:45 +0100365 name_ = std::move(name);
Zimf2b47b42020-09-16 14:54:06 +0100366 }
367
Zim329ba2c2020-09-16 14:23:26 +0100368 bool HasRedactedCache() const {
369 std::lock_guard<std::recursive_mutex> guard(*lock_);
370 return has_redacted_cache_;
371 }
372
373 void SetRedactedCache(bool state) {
374 std::lock_guard<std::recursive_mutex> guard(*lock_);
375 has_redacted_cache_ = state;
376 }
377
Narayan Kamathaef84a12020-01-02 15:20:13 +0000378 inline void AddDirHandle(dirhandle* d) {
379 std::lock_guard<std::recursive_mutex> guard(*lock_);
380
381 dirhandles_.emplace_back(std::unique_ptr<dirhandle>(d));
382 }
383
384 void DestroyDirHandle(dirhandle* d) {
385 std::lock_guard<std::recursive_mutex> guard(*lock_);
386
387 auto comp = [d](const std::unique_ptr<dirhandle>& ptr) { return ptr.get() == d; };
388 auto it = std::find_if(dirhandles_.begin(), dirhandles_.end(), comp);
389 CHECK(it != dirhandles_.end());
390 dirhandles_.erase(it);
391 }
392
393 // Deletes the tree of nodes rooted at |tree|.
394 static void DeleteTree(node* tree);
395
396 // Looks up an absolute path rooted at |root|, or nullptr if no such path
397 // through the hierarchy exists.
398 static const node* LookupAbsolutePath(const node* root, const std::string& absolute_path);
399
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000400 // Looks up for the node with the given ino rooted at |root|, or nullptr if no such node exists.
401 static const node* LookupInode(const node* root, ino_t ino);
402
Narayan Kamathaef84a12020-01-02 15:20:13 +0000403 private:
Zimded1ab92021-01-15 10:36:17 +0000404 node(node* parent, const std::string& name, const std::string& io_path,
Zimd37b9772021-10-13 19:43:37 +0100405 const bool transforms_complete, const int transforms, const int transforms_reason,
406 std::recursive_mutex* lock, ino_t ino, NodeTracker* tracker)
Narayan Kamath568f17a2020-02-19 13:45:29 +0000407 : name_(name),
Zimbb7c3762020-09-23 13:50:08 +0100408 io_path_(io_path),
409 transforms_complete_(transforms_complete),
410 transforms_(transforms),
Zim801d9852021-01-26 18:30:53 +0000411 transforms_reason_(transforms_reason),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000412 refcount_(0),
413 parent_(nullptr),
Zim329ba2c2020-09-16 14:23:26 +0100414 has_redacted_cache_(false),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000415 deleted_(false),
416 lock_(lock),
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000417 ino_(ino),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000418 tracker_(tracker) {
419 tracker_->NodeCreated(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000420 Acquire();
421 // This is a special case for the root node. All other nodes will have a
422 // non-null parent.
423 if (parent != nullptr) {
424 AddToParent(parent);
425 }
426 }
427
Narayan Kamatheca34252020-02-11 13:08:37 +0000428 // Acquires a reference to a node. This maps to the "lookup count" specified
429 // by the FUSE documentation and must only happen under the circumstances
430 // documented in libfuse/include/fuse_lowlevel.h.
431 inline void Acquire() {
432 std::lock_guard<std::recursive_mutex> guard(*lock_);
433 refcount_++;
434 }
435
Narayan Kamathaef84a12020-01-02 15:20:13 +0000436 // Adds this node to a specified parent.
437 void AddToParent(node* parent) {
438 std::lock_guard<std::recursive_mutex> guard(*lock_);
439 // This method assumes this node is currently unparented.
440 CHECK(parent_ == nullptr);
441 // Check that the new parent isn't nullptr either.
442 CHECK(parent != nullptr);
443
444 parent_ = parent;
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100445 parent_->children_.insert(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000446
447 // TODO(narayan, zezeozue): It's unclear why we need to call Acquire on the
448 // parent node when we're adding a child to it.
449 parent_->Acquire();
450 }
451
452 // Removes this node from its current parent, and set its parent to nullptr.
453 void RemoveFromParent() {
454 std::lock_guard<std::recursive_mutex> guard(*lock_);
455
456 if (parent_ != nullptr) {
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100457 auto it = parent_->children_.find(this);
458 CHECK(it != parent_->children_.end());
459 parent_->children_.erase(it);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000460
Narayan Kamathaef84a12020-01-02 15:20:13 +0000461 parent_->Release(1);
462 parent_ = nullptr;
463 }
464 }
465
Zim53c2d702020-09-23 12:18:27 +0100466 // Finds *all* non-deleted nodes matching |name| and runs the function |callback| on each
467 // node until |callback| returns true.
468 // When |callback| returns true, the matched node is returned
469 node* ForChild(const std::string& name, const std::function<bool(node*)>& callback) const {
470 std::lock_guard<std::recursive_mutex> guard(*lock_);
471
472 // lower_bound will give us the first child with strcasecmp(child->name, name) >=0.
473 // For more context see comment on the NodeCompare struct.
474 auto start = children_.lower_bound(std::make_pair(name, 0));
475 // upper_bound will give us the first child with strcasecmp(child->name, name) > 0
476 auto end =
477 children_.upper_bound(std::make_pair(name, std::numeric_limits<uintptr_t>::max()));
478
479 // Make a copy of the matches because calling callback might modify the list which will
480 // cause issues while iterating over them.
481 std::vector<node*> children(start, end);
482
483 for (node* child : children) {
484 if (!child->deleted_ && callback(child)) {
485 return child;
486 }
487 }
488
489 return nullptr;
490 }
491
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100492 // A custom heterogeneous comparator used for set of this node's children_ to speed up child
493 // node by name lookups.
494 //
495 // This comparator treats node* as pair (node->name_, node): two nodes* are first
496 // compared by their name using case-insenstive comparison function. If their names are equal,
497 // then pointers are compared as integers.
498 //
499 // See LookupChildByName function to see how this comparator is used.
500 //
501 // Note that it's important to first compare by name_, since it will make all nodes with same
502 // name (compared using strcasecmp) together, which allows LookupChildByName function to find
503 // range of the candidate nodes by issuing two binary searches.
504 struct NodeCompare {
505 using is_transparent = void;
506
507 bool operator()(const node* lhs, const node* rhs) const {
508 int cmp = strcasecmp(lhs->name_.c_str(), rhs->name_.c_str());
509 if (cmp != 0) {
510 return cmp < 0;
511 }
512 return reinterpret_cast<uintptr_t>(lhs) < reinterpret_cast<uintptr_t>(rhs);
513 }
514
515 bool operator()(const node* lhs, const std::pair<std::string, uintptr_t>& rhs) const {
516 int cmp = strcasecmp(lhs->name_.c_str(), rhs.first.c_str());
517 if (cmp != 0) {
518 return cmp < 0;
519 }
520 return reinterpret_cast<uintptr_t>(lhs) < rhs.second;
521 }
522
523 bool operator()(const std::pair<std::string, uintptr_t>& lhs, const node* rhs) const {
524 int cmp = strcasecmp(lhs.first.c_str(), rhs->name_.c_str());
525 if (cmp != 0) {
526 return cmp < 0;
527 }
528 return lhs.second < reinterpret_cast<uintptr_t>(rhs);
529 }
530 };
531
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +0000532 // A helper function to recursively construct the absolute path of a given node.
533 // If |safe| is true, builds a PII safe path instead
534 void BuildPathForNodeRecursive(bool safe, const node* node, std::stringstream* path) const;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000535
536 // The name of this node. Non-const because it can change during renames.
537 std::string name_;
Zimbb7c3762020-09-23 13:50:08 +0100538 // Filesystem path that will be used for IO (if it is non-empty) instead of node->BuildPath
539 const std::string io_path_;
540 // Whether any transforms required on |io_path_| are complete.
541 // If false, might need to call a node transform function with |transforms| below
542 std::atomic_bool transforms_complete_;
Zim801d9852021-01-26 18:30:53 +0000543 // Opaque flags that determines the 'required' transforms to perform on node
544 // before IO. These flags should not be interpreted in native but should be passed to the
545 // MediaProvider as part of a transform function and if successful, |transforms_complete_|
546 // should be set to true
Zimbb7c3762020-09-23 13:50:08 +0100547 const int transforms_;
Zim801d9852021-01-26 18:30:53 +0000548 // Opaque value indicating the reason why transforms are required.
549 // This value should not be interpreted in native but should be passed to the MediaProvider
550 // as part of a transform function
551 const int transforms_reason_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000552 // The reference count for this node. Guarded by |lock_|.
553 uint32_t refcount_;
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100554 // Set of children of this node. All of them contain a back reference
Narayan Kamathaef84a12020-01-02 15:20:13 +0000555 // to their parent. Guarded by |lock_|.
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100556 std::set<node*, NodeCompare> children_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000557 // Containing directory for this node. Guarded by |lock_|.
558 node* parent_;
559 // List of file handles associated with this node. Guarded by |lock_|.
560 std::vector<std::unique_ptr<handle>> handles_;
561 // List of directory handles associated with this node. Guarded by |lock_|.
562 std::vector<std::unique_ptr<dirhandle>> dirhandles_;
Zim329ba2c2020-09-16 14:23:26 +0100563 bool has_redacted_cache_;
Zim329ba2c2020-09-16 14:23:26 +0100564 bool deleted_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000565 std::recursive_mutex* lock_;
Biswarup Pal93f4ec12021-02-15 13:39:36 +0000566 // Inode number of the file represented by this node.
567 const ino_t ino_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000568
Narayan Kamath568f17a2020-02-19 13:45:29 +0000569 NodeTracker* const tracker_;
570
Narayan Kamathaef84a12020-01-02 15:20:13 +0000571 ~node() {
572 RemoveFromParent();
573
574 handles_.clear();
575 dirhandles_.clear();
Narayan Kamath568f17a2020-02-19 13:45:29 +0000576
577 tracker_->NodeDeleted(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000578 }
579
580 friend class ::NodeTest;
581};
582
583} // namespace fuse
584} // namespace mediaprovider
585
586#endif // MEDIA_PROVIDER_JNI_MODE_INL_H_