}
}
+/// Why --show-config needs a real filesystem, for the diagnostics below.
+static const char *const show_config_root_reason =
+ "--show-config ROOT_PATH needs the filesystem bees would run on, "
+ "not a configuration file: the merged configuration depends on it "
+ "(${ROOT}, ${UUID}, ${LABEL} and ${FS_BYTES} interpolation, the local "
+ "configuration filename, and limits checked against the filesystem "
+ "block size). ROOT_PATH must be an existing directory that is the "
+ "root of a mounted btrfs filesystem, readable and searchable by this "
+ "user.";
+
+/// Check the cheap, explainable requirements on a --show-config
+/// ROOT_PATH before opening it, so a wrong argument gets a message
+/// naming the requirement instead of a bare errno from deep inside
+/// context setup. Returns false after logging if the path cannot
+/// qualify.
+static
+bool
+check_show_config_root(const string &path)
+{
+ struct stat st;
+ if (stat(path.c_str(), &st)) {
+ BEESLOGERR("--show-config: cannot access '" << path << "': " << strerror(errno));
+ BEESLOGERR(show_config_root_reason);
+ return false;
+ }
+ if (!S_ISDIR(st.st_mode)) {
+ BEESLOGERR("--show-config: '" << path << "' is not a directory");
+ BEESLOGERR(show_config_root_reason);
+ return false;
+ }
+ if (access(path.c_str(), R_OK | X_OK)) {
+ BEESLOGERR("--show-config: cannot read directory '" << path << "': " << strerror(errno)
+ << " (uid " << getuid() << " needs read and search permission on the filesystem root)");
+ BEESLOGERR(show_config_root_reason);
+ return false;
+ }
+ struct statfs sfs;
+ if (statfs(path.c_str(), &sfs) == 0 && sfs.f_type != BTRFS_SUPER_MAGIC) {
+ BEESLOGERR("--show-config: '" << path << "' is not on a btrfs filesystem");
+ BEESLOGERR(show_config_root_reason);
+ return false;
+ }
+ return true;
+}
+
static
int
bees_main(int argc, char *argv[])
return EXIT_FAILURE;
}
root_path = show_config_root_path;
+ if (!check_show_config_root(root_path)) {
+ return EXIT_FAILURE;
+ }
} else if (optind + 1 == argc) {
root_path = argv[optind++];
} else {
BEESTRACE("context constructed");
// Set root path and open root FD
- bc->set_root_path(root_path);
+ if (show_merged_config) {
+ // The remaining checks (btrfs, subvol id 5, FS_INFO) happen
+ // inside set_root_path; translate a failure into the same
+ // requirement statement as the pre-checks above.
+ try {
+ bc->set_root_path(root_path);
+ } catch (const exception &e) {
+ BEESLOGERR("--show-config: '" << root_path << "' is not usable as ROOT_PATH: " << e.what());
+ BEESLOGERR(show_config_root_reason);
+ return EXIT_FAILURE;
+ }
+ } else {
+ bc->set_root_path(root_path);
+ }
// Set configuration
bc->set_config(bconfig);