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 <sys/types.h>
41 : #include <sys/stat.h>
42 : #include <fcntl.h>
43 : #include <unistd.h>
44 :
45 : using json = nlohmann::json;
46 :
47 536 : struct lseek_options {
48 : bool verbose{};
49 : std::string pathname;
50 : ::off_t offset;
51 : int whence;
52 :
53 : REFL_DECL_STRUCT(lseek_options, REFL_DECL_MEMBER(bool, verbose),
54 : REFL_DECL_MEMBER(std::string, pathname),
55 : REFL_DECL_MEMBER(::off_t, offset),
56 : REFL_DECL_MEMBER(int, whence));
57 : };
58 :
59 : struct lseek_output {
60 : ::off_t retval;
61 : int errnum;
62 :
63 : REFL_DECL_STRUCT(lseek_output, REFL_DECL_MEMBER(::off_t, retval),
64 : REFL_DECL_MEMBER(int, errnum));
65 : };
66 :
67 : void
68 11 : to_json(json& record, const lseek_output& out) {
69 11 : record = serialize(out);
70 11 : }
71 :
72 : std::string
73 0 : whence2str(int whence) {
74 0 : switch(whence) {
75 0 : case SEEK_SET:
76 0 : return "SEEK_SET";
77 0 : case SEEK_CUR:
78 0 : return "SEEK_CUR";
79 0 : case SEEK_END:
80 0 : return "SEEK_END";
81 0 : default:
82 0 : return "UNKNOWN";
83 : }
84 : return "UNKNOWN";
85 : }
86 :
87 : void
88 11 : lseek_exec(const lseek_options& opts) {
89 :
90 11 : int fd = ::open(opts.pathname.c_str(), O_RDONLY);
91 :
92 11 : if(fd == -1) {
93 0 : if(opts.verbose) {
94 0 : fmt::print("open(pathname=\"{}\") = {}, errno: {} [{}]\n",
95 0 : opts.pathname, fd, errno, ::strerror(errno));
96 0 : return;
97 : }
98 :
99 0 : json out = lseek_output{fd, errno};
100 0 : fmt::print("{}\n", out.dump(2));
101 :
102 0 : return;
103 : }
104 :
105 11 : int rv = ::lseek(fd, opts.offset, opts.whence);
106 :
107 11 : if(opts.verbose) {
108 0 : fmt::print(
109 : "lseek(pathname=\"{}\", offset='{}', whence='{}') = {}, errno: {} [{}]\n",
110 0 : opts.pathname, opts.offset, whence2str(opts.whence), rv, errno,
111 0 : ::strerror(errno));
112 0 : return;
113 : }
114 :
115 11 : json out = lseek_output{rv, errno};
116 22 : fmt::print("{}\n", out.dump(2));
117 : }
118 :
119 : void
120 268 : lseek_init(CLI::App& app) {
121 :
122 : // Create the option and subcommand objects
123 268 : auto opts = std::make_shared<lseek_options>();
124 268 : auto* cmd = app.add_subcommand("lseek", "Execute the lseek() system call");
125 :
126 : // Add options to cmd, binding them to opts
127 268 : cmd->add_flag("-v,--verbose", opts->verbose,
128 536 : "Produce human writeable output");
129 :
130 536 : cmd->add_option("pathname", opts->pathname, "Directory name")
131 : ->required()
132 536 : ->type_name("");
133 :
134 536 : cmd->add_option("offset", opts->offset, "offset used")
135 : ->required()
136 536 : ->type_name("");
137 :
138 536 : cmd->add_option("whence", opts->whence, "Whence the action is done")
139 : ->required()
140 536 : ->type_name("");
141 :
142 1083 : cmd->callback([opts]() { lseek_exec(*opts); });
143 268 : }
|