Advertisement
Guest User

readdir_test.cc

a guest
Jan 26th, 2018
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.99 KB | None | 0 0
  1. #include <chrono>
  2. #include <cerrno>
  3. #include <cstring>
  4. #include <ctime>
  5. #include <iostream>
  6. #include <map>
  7. #include <string>
  8. #include <thread>
  9. #include <vector>
  10. #include <utility>
  11.  
  12. #include <signal.h>
  13. #include <unistd.h>
  14. #include <sys/stat.h>
  15.  
  16. #include <fuse3/fuse.h>
  17.  
  18. // The things we do for decent logging...
  19. #define LOG(level, msg) {\
  20.     std::time_t __now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());\
  21.     char tsstr[100];\
  22.     std::strftime(tsstr, sizeof(tsstr), "%a %b %d %T", std::localtime(&__now));\
  23.     std::cerr << tsstr << "|" << level << "|" << __FILE__ << ":" << __LINE__ \
  24.               << "|" << msg << std::endl; }
  25. #define ERROR(msg)  LOG("ERROR", msg)
  26. #define DEBUG(msg)  LOG("DEBUG", msg)
  27.  
  28.  
  29. /******************************************************************************
  30.  * Hardcoded file system data for testing purposes
  31.  *****************************************************************************/
  32. typedef std::tuple<mode_t, uid_t, gid_t, off64_t, time_t, time_t, time_t> EntryAttrs;
  33.  
  34. std::map<std::string, EntryAttrs> fs_data =
  35. {
  36.     std::pair<std::string, EntryAttrs>{".",         std::make_tuple(16893, 1000, 1000, 0, 1497357835, 1497357835, 1497357835)},
  37.     std::pair<std::string, EntryAttrs>{"..",        std::make_tuple(16893, 1000, 1000, 0, 1497357835, 1497357835, 1497357835)},
  38.     std::pair<std::string, EntryAttrs>{"0001.bin",  std::make_tuple(33188, 1000, 1000, 168593714, 1513688527, 1496839609, 1496839608)},
  39.     std::pair<std::string, EntryAttrs>{"0002.bin",  std::make_tuple(33188, 1000, 1000, 22593382637, 1513688527, 1496857810, 1496857765)},
  40.     std::pair<std::string, EntryAttrs>{"0003.bin",  std::make_tuple(33188, 1000, 0, 0, 1513688528, 1511787445, 1496859394)},
  41.     std::pair<std::string, EntryAttrs>{"0004.bin",  std::make_tuple(33188, 1000, 0, 4204, 1513688528, 1510043263, 1496859394)},
  42.     std::pair<std::string, EntryAttrs>{"0005.bin",  std::make_tuple(33188, 1000, 1000, 473253720, 1513688528, 1497007653, 1497007652)},
  43.     std::pair<std::string, EntryAttrs>{"0006.bin",  std::make_tuple(33188, 1000, 0, 77563049, 1513688528, 1497017377, 1497007822)},
  44.     std::pair<std::string, EntryAttrs>{"0007.bin",  std::make_tuple(33188, 1000, 1000, 22593382637, 1513688528, 1497351617, 1497351587)},
  45.     std::pair<std::string, EntryAttrs>{"0008.bin",  std::make_tuple(33204, 1000, 1000, 15, 1516107258, 1516107258, 1497357863)},
  46.     std::pair<std::string, EntryAttrs>{"0009.bin",  std::make_tuple(33204, 1000, 1000, 1, 1516107258, 1516107258, 1497357863)},
  47.     std::pair<std::string, EntryAttrs>{"0010.bin",  std::make_tuple(33204, 1000, 1000, 536870912, 1516201822, 1497357867, 1497357865)},
  48.     std::pair<std::string, EntryAttrs>{"0011.bin",  std::make_tuple(33204, 1000, 1000, 549, 1516107859, 1497357867, 1497357867)},
  49.     std::pair<std::string, EntryAttrs>{"0012.bin",  std::make_tuple(33204, 1000, 1000, 22593382637, 1516201816, 1497357956, 1497357871)},
  50.     std::pair<std::string, EntryAttrs>{"0013.bin",  std::make_tuple(33204, 1000, 1000, 1046, 1516109117, 1497357981, 1497357981)},
  51.     std::pair<std::string, EntryAttrs>{"0014.bin",  std::make_tuple(33204, 1000, 1000, 68157440, 1516107747, 1516107741, 1497357983)},
  52.     std::pair<std::string, EntryAttrs>{"0015.bin",  std::make_tuple(33204, 1000, 1000, 6892667, 1516109116, 1497357992, 1497357992)},
  53.     std::pair<std::string, EntryAttrs>{"0016.bin",  std::make_tuple(33204, 1000, 1000, 6892667, 1497357992, 1497357992, 1497357992)},
  54.     std::pair<std::string, EntryAttrs>{"0017.bin",  std::make_tuple(33204, 1000, 1000, 1046, 1513688532, 1497357993, 1497357993)},
  55.     std::pair<std::string, EntryAttrs>{"0018.bin",  std::make_tuple(33204, 1000, 1000, 202375168, 1513688532, 1497358008, 1497358007)},
  56.     std::pair<std::string, EntryAttrs>{"0019.bin",  std::make_tuple(33204, 1000, 1000, 536870912, 1516107330, 1497358016, 1497358013)},
  57.     std::pair<std::string, EntryAttrs>{"0020.bin",  std::make_tuple(33204, 1000, 1000, 268435456, 1516107336, 1497358020, 1497358019)},
  58.     std::pair<std::string, EntryAttrs>{"0021.bin",  std::make_tuple(33204, 1000, 1000, 8144, 1516107593, 1497358031, 1497358030)},
  59.     std::pair<std::string, EntryAttrs>{"0022.bin",  std::make_tuple(33204, 1000, 1000, 4775, 1516107734, 1497358046, 1497358046)},
  60.     std::pair<std::string, EntryAttrs>{"0023.bin",  std::make_tuple(33204, 1000, 1000, 481, 1516107371, 1497358047, 1497358047)},
  61.     std::pair<std::string, EntryAttrs>{"0024.bin",  std::make_tuple(33204, 1000, 1000, 526201714, 1497358048, 1497358049, 1497358048)},
  62.     std::pair<std::string, EntryAttrs>{"0025.bin",  std::make_tuple(33204, 1000, 1000, 4725659, 1516108145, 1497358050, 1497358049)},
  63.     std::pair<std::string, EntryAttrs>{"0026.bin",  std::make_tuple(33204, 1000, 1000, 4461205, 1516108145, 1497358050, 1497358050)},
  64.     std::pair<std::string, EntryAttrs>{"0027.bin",  std::make_tuple(33204, 1000, 1000, 4670395, 1516108145, 1497358050, 1497358050)},
  65.     std::pair<std::string, EntryAttrs>{"0028.bin",  std::make_tuple(33204, 1000, 1000, 4627799, 1516108145, 1497358050, 1497358050)},
  66.     std::pair<std::string, EntryAttrs>{"0029.bin",  std::make_tuple(33204, 1000, 1000, 4588549, 1516108145, 1497358050, 1497358050)},
  67.     std::pair<std::string, EntryAttrs>{"0030.bin",  std::make_tuple(33204, 1000, 1000, 4586073, 1516108145, 1497358050, 1497358050)},
  68.     std::pair<std::string, EntryAttrs>{"0031.bin",  std::make_tuple(33204, 1000, 1000, 4537877, 1516108145, 1497358050, 1497358050)},
  69.     std::pair<std::string, EntryAttrs>{"0032.bin",  std::make_tuple(33204, 1000, 1000, 4481762, 1516108145, 1497358050, 1497358050)},
  70.     std::pair<std::string, EntryAttrs>{"0033.bin",  std::make_tuple(33204, 1000, 1000, 4529771, 1516108145, 1497358050, 1497358050)},
  71.     std::pair<std::string, EntryAttrs>{"0034.bin",  std::make_tuple(33204, 1000, 1000, 4715336, 1516108145, 1497358050, 1497358050)},
  72.     std::pair<std::string, EntryAttrs>{"0035.bin",  std::make_tuple(33204, 1000, 1000, 4696289, 1516108145, 1497358050, 1497358050)},
  73.     std::pair<std::string, EntryAttrs>{"0036.bin",  std::make_tuple(33204, 1000, 1000, 4528268, 1516108145, 1497358050, 1497358050)},
  74.     std::pair<std::string, EntryAttrs>{"0037.bin",  std::make_tuple(33204, 1000, 1000, 4539782, 1516108145, 1497358050, 1497358050)},
  75.     std::pair<std::string, EntryAttrs>{"0038.bin",  std::make_tuple(33204, 1000, 1000, 4653329, 1516108145, 1497358050, 1497358050)},
  76.     std::pair<std::string, EntryAttrs>{"0039.bin",  std::make_tuple(33204, 1000, 1000, 4521595, 1516108145, 1497358050, 1497358050)},
  77.     std::pair<std::string, EntryAttrs>{"0040.bin",  std::make_tuple(33204, 1000, 1000, 4660637, 1516108145, 1497358050, 1497358050)},
  78.     std::pair<std::string, EntryAttrs>{"0041.bin",  std::make_tuple(33204, 1000, 1000, 4581008, 1516108145, 1497358050, 1497358050)},
  79.     std::pair<std::string, EntryAttrs>{"0042.bin",  std::make_tuple(33204, 1000, 1000, 4578016, 1516108145, 1497358050, 1497358050)},
  80.     std::pair<std::string, EntryAttrs>{"0043.bin",  std::make_tuple(33204, 1000, 1000, 4753460, 1516108145, 1497358050, 1497358050)},
  81.     std::pair<std::string, EntryAttrs>{"0044.bin",  std::make_tuple(33204, 1000, 1000, 4559827, 1516108145, 1497358050, 1497358050)},
  82.     std::pair<std::string, EntryAttrs>{"0045.bin",  std::make_tuple(33204, 1000, 1000, 4586278, 1516108145, 1497358050, 1497358050)},
  83.     std::pair<std::string, EntryAttrs>{"0046.bin",  std::make_tuple(33204, 1000, 1000, 4622489, 1516108145, 1497358050, 1497358050)},
  84.     std::pair<std::string, EntryAttrs>{"0047.bin",  std::make_tuple(33204, 1000, 1000, 4392706, 1516108145, 1497358051, 1497358050)},
  85.     std::pair<std::string, EntryAttrs>{"0048.bin",  std::make_tuple(33204, 1000, 1000, 4592057, 1516108145, 1497358051, 1497358051)},
  86.     std::pair<std::string, EntryAttrs>{"0049.bin",  std::make_tuple(33204, 1000, 1000, 4692335, 1516108145, 1497358051, 1497358051)},
  87.     std::pair<std::string, EntryAttrs>{"0050.bin",  std::make_tuple(33204, 1000, 1000, 4641344, 1516108145, 1497358051, 1497358051)},
  88.     std::pair<std::string, EntryAttrs>{"0051.bin",  std::make_tuple(33204, 1000, 1000, 4519803, 1516108145, 1497358051, 1497358051)},
  89.     std::pair<std::string, EntryAttrs>{"0052.bin",  std::make_tuple(33204, 1000, 1000, 4580694, 1516108145, 1497358051, 1497358051)},
  90.     std::pair<std::string, EntryAttrs>{"0053.bin",  std::make_tuple(33204, 1000, 1000, 4562114, 1516108145, 1497358051, 1497358051)},
  91.     std::pair<std::string, EntryAttrs>{"0054.bin",  std::make_tuple(33204, 1000, 1000, 4537820, 1516108145, 1497358051, 1497358051)},
  92.     std::pair<std::string, EntryAttrs>{"0055.bin",  std::make_tuple(33204, 1000, 1000, 4523996, 1516108145, 1497358051, 1497358051)},
  93.     std::pair<std::string, EntryAttrs>{"0056.bin",  std::make_tuple(33204, 1000, 1000, 4680014, 1516108145, 1497358051, 1497358051)},
  94.     std::pair<std::string, EntryAttrs>{"0057.bin",  std::make_tuple(33204, 1000, 1000, 4496418, 1516108145, 1497358051, 1497358051)},
  95.     std::pair<std::string, EntryAttrs>{"0058.bin",  std::make_tuple(33204, 1000, 1000, 4804784, 1516108145, 1497358051, 1497358051)},
  96.     std::pair<std::string, EntryAttrs>{"0059.bin",  std::make_tuple(33204, 1000, 1000, 4510851, 1516108145, 1497358051, 1497358051)},
  97.     std::pair<std::string, EntryAttrs>{"0060.bin",  std::make_tuple(33204, 1000, 1000, 4651723, 1516108145, 1497358051, 1497358051)},
  98.     std::pair<std::string, EntryAttrs>{"0061.bin",  std::make_tuple(33204, 1000, 1000, 4582348, 1516108145, 1497358051, 1497358051)},
  99.     std::pair<std::string, EntryAttrs>{"0062.bin",  std::make_tuple(33204, 1000, 1000, 4556271, 1516108145, 1497358051, 1497358051)},
  100.     std::pair<std::string, EntryAttrs>{"0063.bin",  std::make_tuple(33204, 1000, 1000, 4416323, 1516108145, 1497358051, 1497358051)},
  101.     std::pair<std::string, EntryAttrs>{"0064.bin",  std::make_tuple(33204, 1000, 1000, 4584588, 1516108145, 1497358051, 1497358051)},
  102.     std::pair<std::string, EntryAttrs>{"0065.bin",  std::make_tuple(33204, 1000, 1000, 4617515, 1516108145, 1497358051, 1497358051)},
  103.     std::pair<std::string, EntryAttrs>{"0066.bin",  std::make_tuple(33204, 1000, 1000, 4738641, 1516108145, 1497358052, 1497358051)},
  104.     std::pair<std::string, EntryAttrs>{"0067.bin",  std::make_tuple(33204, 1000, 1000, 4521443, 1516108145, 1497358052, 1497358052)},
  105.     std::pair<std::string, EntryAttrs>{"0068.bin",  std::make_tuple(33204, 1000, 1000, 4857734, 1516108145, 1497358052, 1497358052)},
  106.     std::pair<std::string, EntryAttrs>{"0069.bin",  std::make_tuple(33204, 1000, 1000, 4653949, 1516108145, 1497358052, 1497358052)},
  107.     std::pair<std::string, EntryAttrs>{"0070.bin",  std::make_tuple(33204, 1000, 1000, 4709419, 1516108145, 1497358052, 1497358052)},
  108.     std::pair<std::string, EntryAttrs>{"0071.bin",  std::make_tuple(33204, 1000, 1000, 4390969, 1516108145, 1497358052, 1497358052)},
  109.     std::pair<std::string, EntryAttrs>{"0072.bin",  std::make_tuple(33204, 1000, 1000, 4444072, 1516108145, 1497358052, 1497358052)},
  110.     std::pair<std::string, EntryAttrs>{"0073.bin",  std::make_tuple(33204, 1000, 1000, 4320725, 1516108145, 1497358052, 1497358052)},
  111.     std::pair<std::string, EntryAttrs>{"0074.bin",  std::make_tuple(33204, 1000, 1000, 4819829, 1516108145, 1497358052, 1497358052)},
  112.     std::pair<std::string, EntryAttrs>{"0075.bin",  std::make_tuple(33204, 1000, 1000, 4686232, 1516108145, 1497358052, 1497358052)},
  113.     std::pair<std::string, EntryAttrs>{"0076.bin",  std::make_tuple(33204, 1000, 1000, 4749938, 1516108145, 1497358052, 1497358052)},
  114.     std::pair<std::string, EntryAttrs>{"0077.bin",  std::make_tuple(33204, 1000, 1000, 4694213, 1516108145, 1497358052, 1497358052)},
  115.     std::pair<std::string, EntryAttrs>{"0078.bin",  std::make_tuple(33204, 1000, 1000, 4698242, 1516108145, 1497358052, 1497358052)},
  116.     std::pair<std::string, EntryAttrs>{"0079.bin",  std::make_tuple(33204, 1000, 1000, 4794803, 1516108145, 1497358052, 1497358052)},
  117.     std::pair<std::string, EntryAttrs>{"0080.bin",  std::make_tuple(33204, 1000, 1000, 4606039, 1516108145, 1497358052, 1497358052)},
  118.     std::pair<std::string, EntryAttrs>{"0081.bin",  std::make_tuple(33204, 1000, 1000, 4399879, 1516108145, 1497358052, 1497358052)},
  119.     std::pair<std::string, EntryAttrs>{"0082.bin",  std::make_tuple(33204, 1000, 1000, 4816006, 1516108145, 1497358052, 1497358052)},
  120.     std::pair<std::string, EntryAttrs>{"0083.bin",  std::make_tuple(33204, 1000, 1000, 4663708, 1516108145, 1497358052, 1497358052)},
  121.     std::pair<std::string, EntryAttrs>{"0084.bin",  std::make_tuple(33204, 1000, 1000, 4879173, 1516108145, 1497358052, 1497358052)},
  122.     std::pair<std::string, EntryAttrs>{"0085.bin",  std::make_tuple(33204, 1000, 1000, 4871831, 1516108145, 1497358052, 1497358052)},
  123.     std::pair<std::string, EntryAttrs>{"0086.bin",  std::make_tuple(33204, 1000, 1000, 4563574, 1516108145, 1497358052, 1497358052)},
  124.     std::pair<std::string, EntryAttrs>{"0087.bin",  std::make_tuple(33204, 1000, 1000, 4847954, 1516108145, 1497358052, 1497358052)},
  125.     std::pair<std::string, EntryAttrs>{"0088.bin",  std::make_tuple(33204, 1000, 1000, 4878237, 1516108145, 1497358052, 1497358052)},
  126.     std::pair<std::string, EntryAttrs>{"0089.bin",  std::make_tuple(33204, 1000, 1000, 4812806, 1516108145, 1497358052, 1497358052)},
  127.     std::pair<std::string, EntryAttrs>{"0090.bin",  std::make_tuple(33204, 1000, 1000, 4701756, 1516108145, 1497358052, 1497358052)},
  128.     std::pair<std::string, EntryAttrs>{"0091.bin",  std::make_tuple(33204, 1000, 1000, 4418793, 1516108145, 1497358052, 1497358052)},
  129.     std::pair<std::string, EntryAttrs>{"0092.bin",  std::make_tuple(33204, 1000, 1000, 4860231, 1516108145, 1497358052, 1497358052)},
  130.     std::pair<std::string, EntryAttrs>{"0093.bin",  std::make_tuple(33204, 1000, 1000, 4404407, 1516108145, 1497358052, 1497358052)},
  131.     std::pair<std::string, EntryAttrs>{"0094.bin",  std::make_tuple(33204, 1000, 1000, 4356939, 1516108145, 1497358052, 1497358052)},
  132.     std::pair<std::string, EntryAttrs>{"0095.bin",  std::make_tuple(33204, 1000, 1000, 4517704, 1516108145, 1497358052, 1497358052)},
  133.     std::pair<std::string, EntryAttrs>{"0096.bin",  std::make_tuple(33204, 1000, 1000, 4411777, 1516108145, 1497358052, 1497358052)},
  134.     std::pair<std::string, EntryAttrs>{"0097.bin",  std::make_tuple(33204, 1000, 1000, 4597873, 1516108145, 1497358052, 1497358052)},
  135.     std::pair<std::string, EntryAttrs>{"0098.bin",  std::make_tuple(33204, 1000, 1000, 4458429, 1516108145, 1497358052, 1497358052)},
  136.     std::pair<std::string, EntryAttrs>{"0099.bin",  std::make_tuple(33204, 1000, 1000, 4776084, 1516108145, 1497358052, 1497358052)},
  137.     std::pair<std::string, EntryAttrs>{"0100.bin",  std::make_tuple(33204, 1000, 1000, 4762316, 1516108145, 1497358053, 1497358053)},
  138. };
  139.  
  140.  
  141.  
  142. // Globals
  143. const std::string mountpoint("/mnt/readdir");
  144. const uint32_t BLK_SIZE = 512;
  145.  
  146. struct fuse_args*       p_fuseArgv = nullptr;
  147. struct fuse*            p_fuseInstance = nullptr;
  148. struct fuse_loop_config loop_config;
  149. struct fuse_operations  operations;
  150. std::thread*            p_fuseEventThread = nullptr;
  151. struct sigaction        exit_act;
  152. std::vector<std::pair<std::string, struct stat>> readdir_cache;
  153.  
  154. // FUSE operation functions
  155. void* test_init(struct fuse_conn_info* info, fuse_config* config)
  156. {
  157.     // Disable ATOMIC_O_TRUNC, which is enabled by default
  158.     info->want &= (~FUSE_CAP_ATOMIC_O_TRUNC);
  159.  
  160.     // Enable FUSE_CAP_READDIRPLUS to get better performance with readdir on
  161.     // large directories
  162.     info->want |= FUSE_CAP_READDIRPLUS;
  163.     info->want |= FUSE_CAP_READDIRPLUS_AUTO;
  164.    
  165.     // Disable FUSE_CAP_AUTO_INVAL_DATA because it checks file attributes after
  166.     // each read request which slows things way down...
  167.     info->want &= (~FUSE_CAP_AUTO_INVAL_DATA);
  168.    
  169.     // Make sure asynchronous reads are enabled
  170.     info->want |= FUSE_CAP_ASYNC_READ;
  171.    
  172.     // None of these really seem to do anything... but we can dream
  173.     info->max_read      = 0; // no limit but the kernel will limit anyway
  174.     info->max_readahead = 1073741824; // 1GB
  175.     info->max_write     = 1073741824; // 1GB
  176.    
  177.     // Set attr timeout to 3600 seconds (60m/1hr) to effectively enable
  178.     // attribute caching.
  179.     config->attr_timeout = 3600;
  180.  
  181.     DEBUG("FS (FUSE) Initialized.");
  182.  
  183.     return nullptr;
  184. }
  185.  
  186. // Helper function
  187. inline void __populate_stat_buf(
  188.     struct stat& stat_buf,
  189.     std::pair<const std::string, EntryAttrs>& entry)
  190. {
  191.     stat_buf.st_mode  = (mode_t)  std::get<0>(entry.second);
  192.     stat_buf.st_uid   = (uid_t)   std::get<1>(entry.second);
  193.     stat_buf.st_gid   = (gid_t)   std::get<2>(entry.second);
  194.     stat_buf.st_size  = (off64_t) std::get<3>(entry.second);
  195.     stat_buf.st_ctime = (time_t)  std::get<4>(entry.second);
  196.     stat_buf.st_atime = (time_t)  std::get<5>(entry.second);
  197.     stat_buf.st_mtime = (time_t)  std::get<6>(entry.second);
  198.     stat_buf.st_blksize = BLK_SIZE;
  199.     stat_buf.st_blocks = (stat_buf.st_size / stat_buf.st_blksize);
  200.    
  201.     return;
  202. }
  203.  
  204. int test_getattr(
  205.     const char* path,
  206.     struct stat* ss,
  207.     struct fuse_file_info* /* info */)
  208. {
  209.     DEBUG("GETATTR: " << path);
  210.    
  211.     std::string path_str(path);
  212.     if (path_str == "/")
  213.     {
  214.         path_str = ".";
  215.     }
  216.     else
  217.     {
  218.         // Strip on leading slash
  219.         path_str = path_str.substr(1);
  220.     }
  221.    
  222.     // Find the directory entry
  223.     auto iter = fs_data.find(path_str);
  224.     if (iter == fs_data.end())
  225.     {
  226.         DEBUG("GETATTR: returning ENOENT");
  227.         return -ENOENT;
  228.     }
  229.    
  230.     // Populate the stat buffer
  231.     __populate_stat_buf(*ss, *iter);
  232.    
  233.     return 0;
  234. }
  235.  
  236. int test_readdir(
  237.     const char* path,
  238.     void* buf,
  239.     fuse_fill_dir_t filler,
  240.     off_t offset,
  241.     struct fuse_file_info* /* info */,
  242.     fuse_readdir_flags flags)
  243. {
  244.     DEBUG("READDIR (offset: " << offset << " flags: " << flags << "): " << path);
  245.    
  246.     bool readdir_plus = (flags & FUSE_READDIR_PLUS);
  247.    
  248.     if (offset == 0)
  249.     {    
  250.         struct stat stat_buf;
  251.         std::memset(&stat_buf, 0, sizeof(struct stat));
  252.        
  253.         // Iterate over the directory contents
  254.         for (auto& iter : fs_data)
  255.         {
  256.             __populate_stat_buf(stat_buf, iter);
  257.            
  258.             if (iter.first == "." || iter.first == "..")
  259.             {
  260.                 stat_buf.st_ino = 17; // must be nonzero for these entries to appear
  261.             }
  262.            
  263.             // If readdir plus populate the cache otherwise just call filler
  264.             if (readdir_plus)
  265.             {
  266.                 readdir_cache.emplace_back(iter.first, stat_buf);
  267.             }
  268.             else
  269.             {
  270.                 // "regular" readdir
  271.                 filler(buf, iter.first.c_str(), &stat_buf, 0, (fuse_fill_dir_flags)0);
  272.             }
  273.         }
  274.        
  275.         if (! readdir_plus)
  276.         {
  277.             return 0;
  278.         }
  279.     }
  280.    
  281.     // readdir plus fill in entries
  282.     for (off_t offset_idx = offset; offset_idx < readdir_cache.size(); ++offset_idx)
  283.     {
  284.         if (filler(buf, readdir_cache[offset_idx].first.c_str(),
  285.                    &readdir_cache[offset_idx].second, offset_idx + 1,
  286.                    FUSE_FILL_DIR_PLUS))
  287.         {
  288.             break;
  289.         }
  290.     }
  291.    
  292.     // Clear readdir cache
  293.     if (offset == readdir_cache.size())
  294.     {
  295.         DEBUG("freeing readdir cache");
  296.         readdir_cache.clear();
  297.     }
  298.    
  299.     return 0;
  300. }
  301.  
  302. void run()
  303. {
  304.     if (p_fuseInstance == nullptr)
  305.     {
  306.         ERROR("FUSE instance pointer is null");
  307.         return;
  308.     }
  309.    
  310.     std::memset(&loop_config, 0, sizeof(struct fuse_loop_config));
  311.     loop_config.clone_fd = 1;
  312.     loop_config.max_idle_threads = 10;
  313.    
  314.     DEBUG("about to call fuse_loop_mt()");
  315.     fuse_loop_mt(p_fuseInstance, &loop_config);
  316.     DEBUG("fuse_loop_mt() returned");
  317. }
  318.  
  319. void stop(int signum)
  320. {
  321.     DEBUG("handler triggered");
  322.     if (p_fuseInstance != nullptr)
  323.     {
  324.         fuse_exit(p_fuseInstance);
  325.     }
  326. }
  327.  
  328. // g++ -std=c++11 -O3 -o readdir_test readdir_test.cc -lfuse3 -DFUSE_USE_VERSION=32
  329. int main(int argc, char** argv)
  330. {
  331.     std::cout << "Readdir Test FS\n" << std::endl;
  332.    
  333.     // Make sure the mountpoint exists and is a directory
  334.     struct stat stat_buf;
  335.     int rc = stat(mountpoint.c_str(), &stat_buf);
  336.     if (rc != 0)
  337.     {
  338.         ERROR("mountpoint: " << mountpoint <<  " " <<strerror(errno));
  339.         return -1;
  340.     }
  341.     else if (! S_ISDIR(stat_buf.st_mode))
  342.     {    
  343.         ERROR("mountpoint: " << mountpoint <<  " is not a directory");
  344.         return -1;
  345.     }
  346.    
  347.     // Install signal handler
  348.     sigemptyset(&(exit_act.sa_mask));
  349.     exit_act.sa_handler = stop;
  350.     exit_act.sa_flags = 0;
  351.  
  352.     // Act on an interrupt (^C), a quit (^\), and the default kill.
  353.     sigaction(SIGTERM, &exit_act, nullptr);
  354.     sigaction(SIGINT,  &exit_act, nullptr);
  355.     sigaction(SIGQUIT, &exit_act, nullptr);
  356.  
  357.     // Get together the FUSE args
  358.     p_fuseArgv = new struct fuse_args;
  359.     *p_fuseArgv = FUSE_ARGS_INIT(0, NULL);    
  360.  
  361.     // Fake the name of the binary, just as a typical argv.
  362.     if ((rc = fuse_opt_add_arg(p_fuseArgv, argv[0])) < 0)
  363.     {
  364.         ERROR("unable to add fuse arg: " << rc);
  365.         return -2;
  366.     }
  367.  
  368.     if ((rc = fuse_opt_add_arg(p_fuseArgv, "-oallow_other")) < 0)
  369.     {
  370.         ERROR("unable to add fuse arg: " << rc);
  371.         return -2;
  372.     }
  373.  
  374.     if ((rc = fuse_opt_add_arg(p_fuseArgv, "-onosuid,noexec,nodev")) < 0)
  375.     {
  376.         ERROR("unable to add fuse arg: " << rc);
  377.         return -2;
  378.     }
  379.  
  380.     if ((rc = fuse_opt_add_arg(p_fuseArgv, "-odefault_permissions")) < 0)
  381.     {
  382.         ERROR("unable to add fuse arg: " << rc);
  383.         return -2;
  384.     }
  385.  
  386.     if ((rc = fuse_opt_add_arg(p_fuseArgv, "--")) < 0)
  387.     {
  388.         ERROR("unable to add fuse arg: " << rc);
  389.         return -2;
  390.     }
  391.    
  392.     // Install operation function pointers
  393.     std::memset(&operations, 0, sizeof(struct fuse_operations));
  394.     operations.init    = test_init;
  395.     operations.getattr = test_getattr;
  396.     operations.readdir = test_readdir;
  397.    
  398.     // Create the FUSE instance
  399.     p_fuseInstance = fuse_new(p_fuseArgv, &operations, sizeof(operations),
  400.                               nullptr);
  401.     if (p_fuseInstance == nullptr)
  402.     {
  403.         ERROR("unable to create FUSE instance");        
  404.         return -3;
  405.     }
  406.     DEBUG("FUSE instance created");
  407.    
  408.     // Mount
  409.     rc = fuse_mount(p_fuseInstance, mountpoint.c_str());
  410.     if (rc != 0)
  411.     {
  412.         ERROR("unable to mount; fuse_mount() returned: " << rc);
  413.         return -4;
  414.     }
  415.     DEBUG("FUSE mounted");
  416.    
  417.     // Start the event thread
  418.     DEBUG("FUSE thread starting...");
  419.     p_fuseEventThread = new std::thread(run);
  420.     if (p_fuseEventThread == nullptr)
  421.     {
  422.         ERROR("unable to create FUSE even thread");
  423.         return -5;
  424.     }    
  425.     DEBUG("FUSE thread running...");
  426.    
  427.     // Wait for the event thread to terminate
  428.     p_fuseEventThread->join();
  429.     DEBUG("FUSE thread stopping...");
  430.    
  431.     // Clean up
  432.     if (p_fuseInstance != nullptr)
  433.     {
  434.         fuse_unmount(p_fuseInstance);
  435.         fuse_destroy(p_fuseInstance);
  436.     }
  437.     DEBUG("FUSE unmounted and destroyed");    
  438.    
  439.     delete p_fuseArgv;
  440.     delete p_fuseEventThread;
  441.    
  442.     return 0;
  443. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement