1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef IORAP_SRC_INODE2FILENAME_INODE_RESOLVER_H_
16 #define IORAP_SRC_INODE2FILENAME_INODE_RESOLVER_H_
17 
18 #include "common/expected.h"
19 #include "inode2filename/data_source.h"
20 #include "inode2filename/inode.h"
21 #include "inode2filename/system_call.h"
22 
23 #include <rxcpp/rx.hpp>
24 
25 #include <memory>
26 #include <optional>
27 #include <string>
28 #include <vector>
29 namespace iorap::inode2filename {
30 
31 enum class ProcessMode {
32   // Test modes:
33   kInProcessDirect,  // Execute the code directly.
34   kInProcessIpc,     // Execute code via IPC layer using multiple threads.
35   // Shipping mode:
36   kOutOfProcessIpc,  // Execute code via fork+exec with IPC.
37 
38   // Note: in-process system-wide stat(2)/readdir/etc is blocked by selinux.
39   // Attempting to call the test modes will fail with -EPERM.
40   //
41   // Use fork+exec mode in shipping configurations, which spawns inode2filename
42   // as a separate command.
43 };
44 
45 enum class VerifyKind {
46   kNone,
47   kStat,
48 };
49 
50 std::vector<std::string> ToArgs(VerifyKind verify_kind);
51 
52 struct InodeResolverDependencies : public DataSourceDependencies {
53   ProcessMode process_mode = ProcessMode::kInProcessDirect;
54   VerifyKind verify{VerifyKind::kStat};  // Filter out results that aren't up-to-date with stat(2) ?
55 };
56 
57 std::vector<std::string> ToArgs(const InodeResolverDependencies& deps);
58 
59 // Create an rx-observable chain that allows searching for inode->filename mappings given
60 // a set of inode keys.
61 class InodeResolver : public std::enable_shared_from_this<InodeResolver> {
62  public:
63   static std::shared_ptr<InodeResolver> Create(InodeResolverDependencies dependencies,
64                                                std::shared_ptr<DataSource> data_source);  // nonnull
65 
66   // Convenience function for above: Uses DataSource::Create for the data-source.
67   static std::shared_ptr<InodeResolver> Create(InodeResolverDependencies dependencies);
68 
69   // Search the associated data source to map each inode in 'inodes' to a file path.
70   //
71   // Observes DataSource::EmitInodes(), which is unsubscribed from early once all inodes are found.
72   //
73   // Notes:
74   // * Searching does not begin until all 'inodes' are observed to avoid rescanning.
75   // * If the observable is unsubscribed to prior to completion, searching will halt.
76   //
77   // Post-condition: All emitted results are in inodes, and all inodes are in emitted results.
78   rxcpp::observable<InodeResult>
79       FindFilenamesFromInodes(rxcpp::observable<Inode> inodes) const;
80       // TODO: feels like we could turn this into a general helper?
81   // Convenience function for above.
82   virtual rxcpp::observable<InodeResult>
83       FindFilenamesFromInodes(std::vector<Inode> inodes) const;
84 
85   // Enumerate *all* inodes available from the data source, associating it with a filepath.
86   //
87   // Depending on the data source (e.g. diskscan), it can take a very long time for this observable
88   // to complete. The intended use-case is for development/debugging, not for production.
89   //
90   // Observes DataSource::EmitInodes() until it reaches #on_completed.
91   //
92   // Notes:
93   // * If the observable is unsubscribed to prior to completion, searching will halt.
94   virtual rxcpp::observable<InodeResult>
95       EmitAll() const;
96 
97   // Notifies the DataSource to begin recording.
98   // Some DataSources may be continuously refreshing, but only if recording is enabled.
99   // To get the most up-to-date data, toggle recording before reading the inodes out.
100   void StartRecording();  // XX: feels like this should be BPF-specific.
101 
102   // Notifies the DataSource to stop recording.
103   // Some DataSources may be continuously refreshing, but only if recording is enabled.
104   // The snapshot of data returned by e.g. #EmitAll would then not change outside of recording.
105   void StopRecording();
106 
107   virtual ~InodeResolver();
108  private:
109   struct Impl;
110   Impl* impl_;
111 
112  protected:
113   InodeResolver(InodeResolverDependencies dependencies);
114   InodeResolver(InodeResolverDependencies dependencies, std::shared_ptr<DataSource> data_source);
115   InodeResolverDependencies& GetDependencies();
116   const InodeResolverDependencies& GetDependencies() const;
117 };
118 
119 }
120 
121 #endif  // IORAP_SRC_INODE2FILENAME_INODE_RESOLVER_H_
122