diff --git a/src/tools/rados/rados.cc b/src/tools/rados/rados.cc index ccd8988e56f..caed62bd4ad 100644 --- a/src/tools/rados/rados.cc +++ b/src/tools/rados/rados.cc @@ -93,11 +93,11 @@ void usage(ostream& out) " load-gen [options] generate load on the cluster\n" " listomapkeys list the keys in the object map\n" " listomapvals list the keys and vals in the object map \n" -" getomapval show the value for the specified key\n" +" getomapval [file] show the value for the specified key\n" " in the object's object map\n" " setomapval \n" " rmomapkey \n" -" getomapheader \n" +" getomapheader [file]\n" " setomapheader \n" " tmap-to-omap convert tmap keys/values to omap\n" " listwatchers list the watchers of this object\n" @@ -155,8 +155,6 @@ void usage(ostream& out) " --snap name\n" " select given snap name for (read) IO\n" " -i infile\n" -" -o outfile\n" -" specify input or output file (for certain commands)\n" " --create\n" " create the pool or directory that was specified\n" " -N namespace\n" @@ -189,6 +187,31 @@ static void usage_exit() exit(1); } + +static int dump_data(std::string const &filename, bufferlist const &data) +{ + int fd; + if (filename == "-") { + fd = 1; + } else { + fd = TEMP_FAILURE_RETRY(::open(filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644)); + if (fd < 0) { + int err = errno; + cerr << "failed to open file: " << cpp_strerror(err) << std::endl; + return -err; + } + } + + int r = data.write_fd(fd); + + if (fd != 1) { + VOID_TEMP_FAILURE_RETRY(::close(fd)); + } + + return r; +} + + static int do_get(IoCtx& io_ctx, const char *objname, const char *outfile, unsigned op_size) { string oid(objname); @@ -1669,6 +1692,10 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, usage_exit(); string oid(nargs[1]); + string outfile; + if (nargs.size() >= 3) { + outfile = nargs[2]; + } bufferlist header; ret = io_ctx.omap_get_header(oid, &header); @@ -1677,9 +1704,14 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, << ": " << cpp_strerror(ret) << std::endl; goto out; } else { - cout << "header (" << header.length() << " bytes) :\n"; - header.hexdump(cout); - cout << std::endl; + if (!outfile.empty()) { + cerr << "Writing to " << outfile << std::endl; + dump_data(outfile, header); + } else { + cout << "header (" << header.length() << " bytes) :\n"; + header.hexdump(cout); + cout << std::endl; + } ret = 0; } } else if (strcmp(nargs[0], "setomapheader") == 0) { @@ -1730,6 +1762,11 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, set keys; keys.insert(key); + std::string outfile; + if (nargs.size() >= 4) { + outfile = nargs[3]; + } + map values; ret = io_ctx.omap_get_vals_by_keys(oid, keys, &values); if (ret < 0) { @@ -1742,8 +1779,14 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, if (values.size() && values.begin()->first == key) { cout << " (length " << values.begin()->second.length() << ") : "; - values.begin()->second.hexdump(cout); - cout << std::endl; + if (!outfile.empty()) { + cerr << "Writing to " << outfile << std::endl; + dump_data(outfile, values.begin()->second); + } else { + values.begin()->second.hexdump(cout); + cout << std::endl; + } + ret = 0; } else { cout << "No such key: " << pool_name << "/" << oid << "/" << key << std::endl;