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 <sys/uio.h>
43 : #include <fcntl.h>
44 : #include <unistd.h>
45 :
46 : using json = nlohmann::json;
47 :
48 268 : struct pwritev_options {
49 : bool verbose{};
50 : std::string pathname;
51 : std::string data_0, data_1;
52 : ::size_t count;
53 : ::size_t offset;
54 :
55 : REFL_DECL_STRUCT(pwritev_options, REFL_DECL_MEMBER(bool, verbose),
56 : REFL_DECL_MEMBER(std::string, pathname),
57 : REFL_DECL_MEMBER(std::string, data_0),
58 : REFL_DECL_MEMBER(std::string, data_1),
59 : REFL_DECL_MEMBER(::size_t, count),
60 : REFL_DECL_MEMBER(::size_t, offset));
61 : };
62 :
63 : struct pwritev_output {
64 : ::ssize_t retval;
65 : int errnum;
66 :
67 : REFL_DECL_STRUCT(pwritev_output, REFL_DECL_MEMBER(::size_t, retval),
68 : REFL_DECL_MEMBER(int, errnum));
69 : };
70 :
71 : void
72 2 : to_json(json& record, const pwritev_output& out) {
73 2 : record = serialize(out);
74 2 : }
75 :
76 : void
77 2 : pwritev_exec(const pwritev_options& opts) {
78 :
79 2 : auto fd = ::open(opts.pathname.c_str(), O_WRONLY);
80 :
81 2 : if(fd == -1) {
82 0 : if(opts.verbose) {
83 0 : fmt::print(
84 : "pwritev(pathname=\"{}\", buf_0=\"{}\" buf_1=\"{}\" count={}, offset={}) = {}, errno: {} [{}]\n",
85 0 : opts.pathname, opts.data_0, opts.data_1, opts.count,
86 0 : opts.offset, fd, errno, ::strerror(errno));
87 0 : return;
88 : }
89 :
90 0 : json out = pwritev_output{fd, errno};
91 0 : fmt::print("{}\n", out.dump(2));
92 :
93 0 : return;
94 : }
95 :
96 4 : io::buffer buf_0(opts.data_0);
97 4 : io::buffer buf_1(opts.data_1);
98 :
99 2 : struct iovec iov[2];
100 :
101 2 : iov[0].iov_base = buf_0.data();
102 2 : iov[1].iov_base = buf_1.data();
103 :
104 2 : iov[0].iov_len = buf_0.size();
105 2 : iov[1].iov_len = buf_1.size();
106 :
107 2 : int rv = ::pwritev(fd, iov, opts.count, opts.offset);
108 :
109 2 : if(opts.verbose) {
110 0 : fmt::print(
111 : "pwritev(pathname=\"{}\", count={}, offset={}) = {}, errno: {} [{}]\n",
112 0 : opts.pathname, opts.count, opts.offset, rv, errno,
113 0 : ::strerror(errno));
114 0 : return;
115 : }
116 :
117 4 : json out = pwritev_output{rv, errno};
118 4 : fmt::print("{}\n", out.dump(2));
119 : }
120 :
121 : void
122 268 : pwritev_init(CLI::App& app) {
123 :
124 : // Create the option and subcommand objects
125 268 : auto opts = std::make_shared<pwritev_options>();
126 268 : auto* cmd =
127 268 : app.add_subcommand("pwritev", "Execute the pwritev() system call");
128 :
129 : // Add options to cmd, binding them to opts
130 268 : cmd->add_flag("-v,--verbose", opts->verbose,
131 536 : "Produce human writeable output");
132 :
133 536 : cmd->add_option("pathname", opts->pathname, "Directory name")
134 : ->required()
135 536 : ->type_name("");
136 :
137 536 : cmd->add_option("data_0", opts->data_0, "Data 0 to write")
138 : ->required()
139 536 : ->type_name("");
140 :
141 536 : cmd->add_option("data_1", opts->data_1, "Data 1 to write")
142 : ->required()
143 536 : ->type_name("");
144 :
145 536 : cmd->add_option("count", opts->count, "Number of bytes to write")
146 : ->required()
147 536 : ->type_name("");
148 :
149 536 : cmd->add_option("offset", opts->offset, "Offset to read")
150 : ->required()
151 536 : ->type_name("");
152 :
153 1074 : cmd->callback([opts]() { pwritev_exec(*opts); });
154 268 : }
|