Line data Source code
1 : /*
2 : Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain
3 : Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany
4 :
5 : This software was partially supported by the
6 : EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).
7 :
8 : This software was partially supported by the
9 : ADA-FS project under the SPPEXA project funded by the DFG.
10 :
11 : This file is part of GekkoFS.
12 :
13 : GekkoFS is free software: you can redistribute it and/or modify
14 : it under the terms of the GNU General Public License as published by
15 : the Free Software Foundation, either version 3 of the License, or
16 : (at your option) any later version.
17 :
18 : GekkoFS is distributed in the hope that it will be useful,
19 : but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : GNU General Public License for more details.
22 :
23 : You should have received a copy of the GNU General Public License
24 : along with GekkoFS. If not, see <https://www.gnu.org/licenses/>.
25 :
26 : SPDX-License-Identifier: GPL-3.0-or-later
27 : */
28 :
29 : /* C++ includes */
30 : #include <CLI/CLI.hpp>
31 : #include <nlohmann/json.hpp>
32 : #include <memory>
33 : #include <fmt/format.h>
34 : #include <commands.hpp>
35 : #include <reflection.hpp>
36 : #include <serialize.hpp>
37 : #include <binary_buffer.hpp>
38 :
39 : /* C includes */
40 : #include <dirent.h>
41 : #include <unistd.h>
42 :
43 : using json = nlohmann::json;
44 :
45 536 : struct readdir_options {
46 : bool verbose{};
47 : std::string pathname;
48 : ::size_t count;
49 :
50 : REFL_DECL_STRUCT(readdir_options, REFL_DECL_MEMBER(bool, verbose),
51 : REFL_DECL_MEMBER(std::string, pathname),
52 : REFL_DECL_MEMBER(::size_t, count));
53 : };
54 :
55 12 : struct readdir_output {
56 : std::vector<struct ::dirent> dirents;
57 : int errnum;
58 :
59 : REFL_DECL_STRUCT(readdir_output,
60 : REFL_DECL_MEMBER(std::vector<struct ::dirent>, dirents),
61 : REFL_DECL_MEMBER(int, errnum));
62 : };
63 :
64 : void
65 12 : to_json(json& record, const readdir_output& out) {
66 12 : record = serialize(out);
67 12 : }
68 :
69 : void
70 12 : readdir_exec(const readdir_options& opts) {
71 :
72 12 : ::DIR* dirp = ::opendir(opts.pathname.c_str());
73 :
74 12 : if(dirp == NULL) {
75 0 : if(opts.verbose) {
76 0 : fmt::print("readdir(pathname=\"{}\") = {}, errno: {} [{}]\n",
77 0 : opts.pathname, "NULL", errno, ::strerror(errno));
78 0 : return;
79 : }
80 :
81 0 : json out = readdir_output{{}, errno};
82 0 : fmt::print("{}\n", out.dump(2));
83 :
84 0 : return;
85 : }
86 :
87 24 : io::buffer buf(opts.count);
88 :
89 24 : std::vector<struct ::dirent> entries;
90 26 : struct ::dirent* entry;
91 :
92 26 : while((entry = ::readdir(dirp)) != NULL) {
93 14 : entries.push_back(*entry);
94 : }
95 :
96 12 : if(opts.verbose) {
97 0 : fmt::print("readdir(pathname=\"{}\") = [\n{}],\nerrno: {} [{}]\n",
98 0 : opts.pathname, fmt::join(entries, ",\n"), errno,
99 0 : ::strerror(errno));
100 0 : return;
101 : }
102 :
103 24 : json out = readdir_output{entries, errno};
104 24 : fmt::print("{}\n", out.dump(2));
105 : }
106 :
107 : void
108 268 : readdir_init(CLI::App& app) {
109 :
110 : // Create the option and subcommand objects
111 268 : auto opts = std::make_shared<readdir_options>();
112 268 : auto* cmd =
113 268 : app.add_subcommand("readdir", "Execute the readdir() system call");
114 :
115 : // Add options to cmd, binding them to opts
116 268 : cmd->add_flag("-v,--verbose", opts->verbose,
117 536 : "Produce human readable output");
118 :
119 536 : cmd->add_option("pathname", opts->pathname, "Directory name")
120 : ->required()
121 536 : ->type_name("");
122 :
123 1084 : cmd->callback([opts]() { readdir_exec(*opts); });
124 268 : }
|