1 #pragma once
2 
3 #include <sys/mount.h>
4 
5 #include <filesystem>
6 #include <string>
7 
8 namespace estoraged
9 {
10 
11 /** @class FilesystemInterface
12  *  @brief Interface to the filesystem operations that eStoraged needs.
13  *  @details This class is used to mock out the filesystem operations.
14  */
15 class FilesystemInterface
16 {
17   public:
18     virtual ~FilesystemInterface() = default;
19 
20     /** @brief Runs the mkfs command to create the filesystem.
21      *  @details Used for mocking purposes.
22      *
23      *  @param[in] logicalVolume - name of the mapped LUKS device.
24      *
25      *  @returns 0 on success, nonzero on failure.
26      */
27     virtual int runMkfs(const std::string& logicalVolume) = 0;
28 
29     /** @brief Wrapper around mount().
30      *  @details Used for mocking purposes.
31      *
32      *  @param[in] source - device where the filesystem is located.
33      *  @param[in] target - path to where the filesystem should be mounted.
34      *  @param[in] filesystemType - (e.g. "ext4").
35      *  @param[in] mountflags - flags bit mask (see mount() documentation).
36      *  @param[in] data - options for specific filesystem type, can be NULL
37      *    (see mount() documentation).
38      *
39      *  @returns On success, zero is returned.  On error, -1 is returned, and
40      *    errno is set to indicate the error.
41      */
42     virtual int doMount(const char* source, const char* target,
43                         const char* filesystemtype, unsigned long mountflags,
44                         const void* data) = 0;
45 
46     /** @brief Wrapper around umount().
47      *  @details Used for mocking purposes.
48      *
49      *  @param[in] target - path location where the filesystem is mounted.
50      *
51      *  @returns On success, zero is returned.  On error, -1 is returned, and
52      *    errno is set to indicate the error.
53      */
54     virtual int doUnmount(const char* target) = 0;
55 
56     /** @brief Wrapper around std::filesystem::create_directory.
57      *  @details Used for mocking purposes.
58      *
59      *  @param[in] p - path to directory that should be created.
60      *
61      *  @returns true on success, false otherwise.
62      */
63     virtual bool createDirectory(const std::filesystem::path& p) = 0;
64 
65     /** @brief Wrapper around std::filesystem::remove.
66      *  @details Used for mocking purposes.
67      *
68      *  @param[in] p - path to directory that should be removed.
69      *
70      *  @returns true on success, false otherwise.
71      */
72     virtual bool removeDirectory(const std::filesystem::path& p) = 0;
73 
74     /** @brief Wrapper around std::filesystem::is_directory
75      *
76      *  @param[in] p - path to directory that we want to query.
77      *
78      *  @returns true if the path exists and represents a directory.
79      */
80     virtual bool directoryExists(const std::filesystem::path& p) = 0;
81 };
82 
83 /** @class Filesystem
84  *  @brief Implements FilesystemInterface
85  */
86 class Filesystem : public FilesystemInterface
87 {
88   public:
89     ~Filesystem() = default;
90 
91     int runMkfs(const std::string& logicalVolume) override
92     {
93         std::string mkfsCommand("mkfs.ext4 /dev/mapper/" + logicalVolume);
94         return system(mkfsCommand.c_str());
95     }
96 
97     int doMount(const char* source, const char* target,
98                 const char* filesystemtype, unsigned long mountflags,
99                 const void* data) override
100     {
101         return mount(source, target, filesystemtype, mountflags, data);
102     }
103 
104     int doUnmount(const char* target) override
105     {
106         return umount(target);
107     }
108 
109     bool createDirectory(const std::filesystem::path& p) override
110     {
111         return std::filesystem::create_directory(p);
112     }
113 
114     bool removeDirectory(const std::filesystem::path& p) override
115     {
116         return std::filesystem::remove(p);
117     }
118 
119     bool directoryExists(const std::filesystem::path& p) override
120     {
121         return std::filesystem::is_directory(std::filesystem::status(p));
122     }
123 };
124 } // namespace estoraged
125