xref: /openbmc/estoraged/include/filesystemInterface.hpp (revision 530ce1e82b9cc606a19fc99cb8d31e1410f401f2)
1 #pragma once
2 
3 #include <sys/mount.h>
4 
5 #include <filesystem>
6 #include <initializer_list>
7 #include <numeric>
8 #include <string>
9 
10 namespace estoraged
11 {
12 
13 /** @class FilesystemInterface
14  *  @brief Interface to the filesystem operations that eStoraged needs.
15  *  @details This class is used to mock out the filesystem operations.
16  */
17 class FilesystemInterface
18 {
19   public:
20     virtual ~FilesystemInterface() = default;
21 
22     FilesystemInterface() = default;
23     FilesystemInterface(const FilesystemInterface&) = delete;
24     FilesystemInterface& operator=(const FilesystemInterface&) = delete;
25 
26     FilesystemInterface(FilesystemInterface&&) = delete;
27     FilesystemInterface& operator=(FilesystemInterface&&) = delete;
28 
29     /** @brief Runs the mkfs command to create the filesystem.
30      *  @details Used for mocking purposes.
31      *
32      *  @param[in] logicalVolumePath - path to the mapped LUKS device.
33      *
34      *  @returns 0 on success, nonzero on failure.
35      */
36     virtual int runMkfs(const std::string& logicalVolumePath,
37                         std::initializer_list<std::string> options = {}) = 0;
38 
39     /** @brief Wrapper around mount().
40      *  @details Used for mocking purposes.
41      *
42      *  @param[in] source - device where the filesystem is located.
43      *  @param[in] target - path to where the filesystem should be mounted.
44      *  @param[in] filesystemType - (e.g. "ext4").
45      *  @param[in] mountflags - flags bit mask (see mount() documentation).
46      *  @param[in] data - options for specific filesystem type, can be NULL
47      *    (see mount() documentation).
48      *
49      *  @returns On success, zero is returned.  On error, -1 is returned, and
50      *    errno is set to indicate the error.
51      */
52     virtual int doMount(const char* source, const char* target,
53                         const char* filesystemtype, unsigned long mountflags,
54                         const void* data) = 0;
55 
56     /** @brief Wrapper around umount().
57      *  @details Used for mocking purposes.
58      *
59      *  @param[in] target - path location where the filesystem is mounted.
60      *
61      *  @returns On success, zero is returned.  On error, -1 is returned, and
62      *    errno is set to indicate the error.
63      */
64     virtual int doUnmount(const char* target) = 0;
65 
66     /** @brief Wrapper around std::filesystem::create_directory.
67      *  @details Used for mocking purposes.
68      *
69      *  @param[in] p - path to directory that should be created.
70      *
71      *  @returns true on success, false otherwise.
72      */
73     virtual bool createDirectory(const std::filesystem::path& p) = 0;
74 
75     /** @brief Wrapper around std::filesystem::remove.
76      *  @details Used for mocking purposes.
77      *
78      *  @param[in] p - path to directory that should be removed.
79      *
80      *  @returns true on success, false otherwise.
81      */
82     virtual bool removeDirectory(const std::filesystem::path& p) = 0;
83 
84     /** @brief Wrapper around std::filesystem::is_directory
85      *
86      *  @param[in] p - path to directory that we want to query.
87      *
88      *  @returns true if the path exists and represents a directory.
89      */
90     virtual bool directoryExists(const std::filesystem::path& p) = 0;
91 
92     /** @brief Wrapper around fsck.
93      *  @details Used for mocking purposes.
94      *
95      *  @param[in] logicalVolumePath - path to device with filesystem
96      *  @param[in] options - Other options to pass into fsck
97      *
98      *  @returns 0 on success, nonzero on failure.
99      */
100     virtual int runFsck(const std::string& logicalVolumePath,
101                         const std::string& options) = 0;
102 };
103 
104 /** @class Filesystem
105  *  @brief Implements FilesystemInterface
106  */
107 class Filesystem : public FilesystemInterface
108 {
109   public:
110     ~Filesystem() override = default;
111     Filesystem() = default;
112     Filesystem(const Filesystem&) = delete;
113     Filesystem& operator=(const Filesystem&) = delete;
114 
115     Filesystem(Filesystem&&) = delete;
116     Filesystem& operator=(Filesystem&&) = delete;
117 
runMkfs(const std::string & logicalVolumePath,std::initializer_list<std::string> options)118     int runMkfs(const std::string& logicalVolumePath,
119                 std::initializer_list<std::string> options) override
120     {
121         std::string mkfsCommand("mkfs.ext4 ");
122         mkfsCommand.reserve(
123             mkfsCommand.size() + logicalVolumePath.size() + options.size() +
124             std::accumulate(options.begin(), options.end(), 0,
125                             [](size_t sum, const std::string& s) {
126                                 return sum + s.size();
127                             }));
128 
129         for (const std::string& s : options)
130         {
131             mkfsCommand.append(s);
132             mkfsCommand.push_back(' ');
133         }
134 
135         mkfsCommand.append(logicalVolumePath);
136 
137         // calling 'system' uses a command processor //NOLINTNEXTLINE
138         return system(mkfsCommand.c_str());
139     }
140 
doMount(const char * source,const char * target,const char * filesystemtype,unsigned long mountflags,const void * data)141     int doMount(const char* source, const char* target,
142                 const char* filesystemtype, unsigned long mountflags,
143                 const void* data) override
144     {
145         return mount(source, target, filesystemtype, mountflags, data);
146     }
147 
doUnmount(const char * target)148     int doUnmount(const char* target) override
149     {
150         return umount(target);
151     }
152 
createDirectory(const std::filesystem::path & p)153     bool createDirectory(const std::filesystem::path& p) override
154     {
155         return std::filesystem::create_directory(p);
156     }
157 
removeDirectory(const std::filesystem::path & p)158     bool removeDirectory(const std::filesystem::path& p) override
159     {
160         return std::filesystem::remove(p);
161     }
162 
directoryExists(const std::filesystem::path & p)163     bool directoryExists(const std::filesystem::path& p) override
164     {
165         return std::filesystem::is_directory(std::filesystem::status(p));
166     }
167 
runFsck(const std::string & logicalVolumePath,const std::string & options)168     int runFsck(const std::string& logicalVolumePath,
169                 const std::string& options) override
170     {
171         std::string fsckCommand("fsck " + logicalVolumePath + " " + options);
172         // calling 'system' uses a command processor //NOLINTNEXTLINE
173         return system(fsckCommand.c_str());
174     }
175 };
176 } // namespace estoraged
177