diff --git a/tools/ldb_cmd.cc b/tools/ldb_cmd.cc
index 9ff9bb0e9..1965c6911 100644
--- a/tools/ldb_cmd.cc
+++ b/tools/ldb_cmd.cc
@@ -1016,8 +1016,8 @@ void DumpManifestFile(Options options, std::string file, bool verbose, bool hex,
/*block_cache_tracer=*/nullptr);
Status s = versions.DumpManifest(options, file, verbose, hex, json);
if (!s.ok()) {
- printf("Error in processing file %s %s\n", file.c_str(),
- s.ToString().c_str());
+ fprintf(stderr, "Error in processing file %s %s\n", file.c_str(),
+ s.ToString().c_str());
}
}
@@ -1066,45 +1066,72 @@ void ManifestDumpCommand::DoCommand() {
if (!path_.empty()) {
manifestfile = path_;
} else {
- bool found = false;
// We need to find the manifest file by searching the directory
// containing the db for files of the form MANIFEST_[0-9]+
- auto CloseDir = [](DIR* p) { closedir(p); };
- std::unique_ptr
d(opendir(db_path_.c_str()),
- CloseDir);
-
- if (d == nullptr) {
- exec_state_ =
- LDBCommandExecuteResult::Failed(db_path_ + " is not a directory");
+ std::vector files;
+ Status s = options_.env->GetChildren(db_path_, &files);
+ if (!s.ok()) {
+ std::string err_msg = s.ToString();
+ err_msg.append(": Failed to list the content of ");
+ err_msg.append(db_path_);
+ exec_state_ = LDBCommandExecuteResult::Failed(err_msg);
return;
}
- struct dirent* entry;
- while ((entry = readdir(d.get())) != nullptr) {
- unsigned int match;
- uint64_t num;
- if (sscanf(entry->d_name, "MANIFEST-%" PRIu64 "%n", &num, &match) &&
- match == strlen(entry->d_name)) {
- if (!found) {
- manifestfile = db_path_ + "/" + std::string(entry->d_name);
- found = true;
- } else {
+ const std::string kManifestNamePrefix = "MANIFEST-";
+ std::string matched_file;
+#ifdef OS_WIN
+ const char kPathDelim = '\\';
+#else
+ const char kPathDelim = '/';
+#endif
+ for (const auto& file_path : files) {
+ // Some Env::GetChildren() return absolute paths. Some directories' path
+ // end with path delim, e.g. '/' or '\\'.
+ size_t pos = file_path.find_last_of(kPathDelim);
+ if (pos == file_path.size() - 1) {
+ continue;
+ }
+ std::string fname;
+ if (pos != std::string::npos) {
+ // Absolute path.
+ fname.assign(file_path, pos + 1, file_path.size() - pos - 1);
+ } else {
+ fname = file_path;
+ }
+ uint64_t file_num = 0;
+ FileType file_type = kLogFile; // Just for initialization
+ if (ParseFileName(fname, &file_num, &file_type) &&
+ file_type == kDescriptorFile) {
+ if (!matched_file.empty()) {
exec_state_ = LDBCommandExecuteResult::Failed(
"Multiple MANIFEST files found; use --path to select one");
return;
+ } else {
+ matched_file.swap(fname);
}
}
}
+ if (matched_file.empty()) {
+ std::string err_msg("No MANIFEST found in ");
+ err_msg.append(db_path_);
+ exec_state_ = LDBCommandExecuteResult::Failed(err_msg);
+ return;
+ }
+ if (db_path_[db_path_.length() - 1] != '/') {
+ db_path_.append("/");
+ }
+ manifestfile = db_path_ + matched_file;
}
if (verbose_) {
- printf("Processing Manifest file %s\n", manifestfile.c_str());
+ fprintf(stdout, "Processing Manifest file %s\n", manifestfile.c_str());
}
DumpManifestFile(options_, manifestfile, verbose_, is_key_hex_, json_);
if (verbose_) {
- printf("Processing Manifest file %s done\n", manifestfile.c_str());
+ fprintf(stdout, "Processing Manifest file %s done\n", manifestfile.c_str());
}
}
@@ -1126,19 +1153,19 @@ void ListColumnFamiliesCommand::DoCommand() {
std::vector column_families;
Status s = DB::ListColumnFamilies(options_, db_path_, &column_families);
if (!s.ok()) {
- printf("Error in processing db %s %s\n", db_path_.c_str(),
- s.ToString().c_str());
+ fprintf(stderr, "Error in processing db %s %s\n", db_path_.c_str(),
+ s.ToString().c_str());
} else {
- printf("Column families in %s: \n{", db_path_.c_str());
+ fprintf(stdout, "Column families in %s: \n{", db_path_.c_str());
bool first = true;
for (auto cf : column_families) {
if (!first) {
- printf(", ");
+ fprintf(stdout, ", ");
}
first = false;
- printf("%s", cf.c_str());
+ fprintf(stdout, "%s", cf.c_str());
}
- printf("}\n");
+ fprintf(stdout, "}\n");
}
}
@@ -2761,7 +2788,7 @@ void CheckPointCommand::DoCommand() {
Status status = Checkpoint::Create(db_, &checkpoint);
status = checkpoint->CreateCheckpoint(checkpoint_dir_);
if (status.ok()) {
- printf("OK\n");
+ fprintf(stdout, "OK\n");
} else {
exec_state_ = LDBCommandExecuteResult::Failed(status.ToString());
}
@@ -2785,7 +2812,7 @@ void RepairCommand::DoCommand() {
options.info_log.reset(new StderrLogger(InfoLogLevel::WARN_LEVEL));
Status status = RepairDB(db_path_, options);
if (status.ok()) {
- printf("OK\n");
+ fprintf(stdout, "OK\n");
} else {
exec_state_ = LDBCommandExecuteResult::Failed(status.ToString());
}
@@ -2865,7 +2892,7 @@ void BackupCommand::DoCommand() {
assert(GetExecuteState().IsFailed());
return;
}
- printf("open db OK\n");
+ fprintf(stdout, "open db OK\n");
Env* custom_env = nullptr;
Env::LoadEnv(backup_env_uri_, &custom_env, &backup_env_guard_);
assert(custom_env != nullptr);
@@ -2876,14 +2903,14 @@ void BackupCommand::DoCommand() {
backup_options.max_background_operations = num_threads_;
status = BackupEngine::Open(custom_env, backup_options, &backup_engine);
if (status.ok()) {
- printf("open backup engine OK\n");
+ fprintf(stdout, "open backup engine OK\n");
} else {
exec_state_ = LDBCommandExecuteResult::Failed(status.ToString());
return;
}
status = backup_engine->CreateNewBackup(db_);
if (status.ok()) {
- printf("create new backup OK\n");
+ fprintf(stdout, "create new backup OK\n");
} else {
exec_state_ = LDBCommandExecuteResult::Failed(status.ToString());
return;
@@ -2921,11 +2948,11 @@ void RestoreCommand::DoCommand() {
}
}
if (status.ok()) {
- printf("open restore engine OK\n");
+ fprintf(stdout, "open restore engine OK\n");
status = restore_engine->RestoreDBFromLatestBackup(db_path_, db_path_);
}
if (status.ok()) {
- printf("restore from backup OK\n");
+ fprintf(stdout, "restore from backup OK\n");
} else {
exec_state_ = LDBCommandExecuteResult::Failed(status.ToString());
}