}
}
-static void ValidateDirectoryExists(const std::string &Path) {
- if (!Path.empty() && !IsDirectory(Path)) {
- Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str());
+static void ValidateDirectoryExists(const std::string &Path,
+ bool CreateDirectory) {
+ if (Path.empty()) {
+ Printf("ERROR: Provided directory path is an empty string\n");
exit(1);
}
+
+ if (IsDirectory(Path))
+ return;
+
+ if (CreateDirectory) {
+ if (!MkDirRecursive(Path)) {
+ Printf("ERROR: Failed to create directory \"%s\"\n", Path.c_str());
+ exit(1);
+ }
+ return;
+ }
+
+ Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str());
+ exit(1);
}
std::string CloneArgsWithoutX(const Vector<std::string> &Args,
std::string OutputCorpusDir = (*Inputs)[0];
if (!IsFile(OutputCorpusDir)) {
Options.OutputCorpus = OutputCorpusDir;
- ValidateDirectoryExists(Options.OutputCorpus);
+ ValidateDirectoryExists(Options.OutputCorpus, Flags.create_missing_dirs);
}
}
Options.ReportSlowUnits = Flags.report_slow_units;
if (!IsSeparator(ArtifactPathDir[ArtifactPathDir.length() - 1])) {
ArtifactPathDir = DirName(ArtifactPathDir);
}
- ValidateDirectoryExists(ArtifactPathDir);
+ ValidateDirectoryExists(ArtifactPathDir, Flags.create_missing_dirs);
}
if (Flags.exact_artifact_path) {
Options.ExactArtifactPath = Flags.exact_artifact_path;
- ValidateDirectoryExists(DirName(Options.ExactArtifactPath));
+ ValidateDirectoryExists(DirName(Options.ExactArtifactPath),
+ Flags.create_missing_dirs);
}
Vector<Unit> Dictionary;
if (Flags.dict)
Options.DataFlowTrace = Flags.data_flow_trace;
if (Flags.features_dir) {
Options.FeaturesDir = Flags.features_dir;
- ValidateDirectoryExists(Options.FeaturesDir);
+ ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs);
}
if (Flags.collect_data_flow)
Options.CollectDataFlow = Flags.collect_data_flow;
FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace")
FUZZER_FLAG_STRING(collect_data_flow,
"Experimental: collect the data flow trace")
+
+FUZZER_FLAG_INT(create_missing_dirs, 0, "Automatically attempt to create "
+ "directories for arguments that would normally expect them to already "
+ "exist (i.e. artifact_prefix, exact_artifact_path, features_dir, corpus)")
fflush(OutputFile);
}
+static bool MkDirRecursiveInner(const std::string &Leaf) {
+ // Prevent chance of potential infinite recursion
+ if (Leaf == ".")
+ return true;
+
+ const std::string &Dir = DirName(Leaf);
+
+ if (IsDirectory(Dir)) {
+ MkDir(Leaf);
+ return IsDirectory(Leaf);
+ }
+
+ bool ret = MkDirRecursiveInner(Dir);
+ if (!ret) {
+ // Give up early if a previous MkDir failed
+ return ret;
+ }
+
+ MkDir(Leaf);
+ return IsDirectory(Leaf);
+}
+
+bool MkDirRecursive(const std::string &Dir) {
+ if (Dir.empty())
+ return false;
+
+ if (IsDirectory(Dir))
+ return true;
+
+ return MkDirRecursiveInner(Dir);
+}
+
void RmDirRecursive(const std::string &Dir) {
IterateDirRecursive(
Dir, [](const std::string &Path) {},
void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
Vector<std::string> *V, bool TopDir);
+bool MkDirRecursive(const std::string &Dir);
void RmDirRecursive(const std::string &Dir);
// Iterate files and dirs inside Dir, recursively.
LONG: INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 8192 bytes
RUN: rm -rf %t/SUB1
+# Verify error message prints to console when directory does not exist
RUN: rm -rf %t.dir && mkdir -p %t.dir
RUN: not %run %t-SimpleTest -artifact_prefix=%t.dir/NONEXISTENT_DIR/ 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR_RGX
RUN: not %run %t-SimpleTest -artifact_prefix=%t.dir/NONEXISTENT_DIR/myprefix 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR_RGX
RUN: not %run %t-SimpleTest %t.dir/NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR_RGX
RUN: not %run %t-SimpleTest -exact_artifact_path=%t.dir/NONEXISTENT_DIR/myprefix 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR_RGX
NONEXISTENT_DIR_RGX: ERROR: The required directory "{{.*/NONEXISTENT_DIR/?}}" does not exist
+
+# Verify error message prints to console when given directory is an empty
+# string
+RUN: not %run %t-SimpleTest "" 2>&1 | FileCheck %s --check-prefix=INVALID_DIR_RGX
+INVALID_DIR_RGX: ERROR: Provided directory path is an empty string
+
+# Verify error message prints to console when directory creation fails
+# For platforms without functioning chmod (i.e. Windows), use a forbidden
+# character in the directory name.
+RUN: rm -rf %t.dir && mkdir -p %t.dir/access_restricted && (chmod u-w %t.dir/access_restricted || true)
+RUN: not %run %t-SimpleTest -create_missing_dirs=1 %t.dir/access_restricted/?corpus? 2>&1 | FileCheck %s --check-prefix=DIR_CREATION_FAILURE
+DIR_CREATION_FAILURE: ERROR: Failed to create directory "{{.*/access_restricted/\?corpus\?}}"
+
+# Verify directories and sub-directories are created when -create_missing_dirs=1
+RUN: not %run %t-SimpleTest -create_missing_dirs=1 -artifact_prefix=%t.dir/subdira/./././artifacts/ -features_dir=%t.dir/subdirb/../dummy_dir/././../subdirb/features/ %t.dir/subdirc/corpus
+RUN: test -e %t.dir/subdira/artifacts/
+RUN: test -e %t.dir/subdirb/features/
+RUN: test -e %t.dir/subdirc/corpus/
+RUN: test -e %t.dir/dummy_dir
+
+# Verify directories and sub-directories are created for exact_artifact_path
+# when -create_missing_dirs=1
+RUN: not %run %t-SimpleTest -create_missing_dirs=1 -exact_artifact_path=%t.dir/subdird/exact_artifacts/abc
+RUN: test -e %t.dir/subdird/exact_artifacts/abc
+
+# Verify directories and sub-directories are created for artifact_prefix when
+# it's referring to a file name prefix and -create_missing_dirs=1
+RUN: not %run %t-SimpleTest -create_missing_dirs=1 -artifact_prefix=%t.dir/subdire/myprefix
+RUN: test -e %t.dir/subdire/ && not test -e %t.dir/subdire/myprefix
+
+# Verify directories are created when referring to relative paths and
+# -create_missing_dirs=1
+RUN: cd %t.dir && not %run %t-SimpleTest -create_missing_dirs=1 -artifact_prefix=cwd_artifacts/ -features_dir=cwd_features/subdirtest/ ./cwd_corpus
+RUN: test -e %t.dir/cwd_artifacts/
+RUN: test -e %t.dir/cwd_features/subdirtest/
+RUN: test -e %t.dir/cwd_corpus/