This is an automated email from the ASF dual-hosted git repository.
dragon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 31e5344 runroot verify command
31e5344 is described below
commit 31e5344cc53dc95003f47296db9fab901968407a
Author: Xavier Chi <[email protected]>
AuthorDate: Fri Mar 30 16:58:25 2018 -0500
runroot verify command
---
cmd/traffic_layout/engine.cc | 346 ++++++++++++++++++++++++-----------
cmd/traffic_layout/engine.h | 10 +-
cmd/traffic_layout/file_system.h | 4 +-
cmd/traffic_layout/traffic_layout.cc | 19 +-
lib/ts/runroot.cc | 18 +-
lib/ts/runroot.h | 4 +-
6 files changed, 272 insertions(+), 129 deletions(-)
diff --git a/cmd/traffic_layout/engine.cc b/cmd/traffic_layout/engine.cc
index 1ee3595..d9765a8 100644
--- a/cmd/traffic_layout/engine.cc
+++ b/cmd/traffic_layout/engine.cc
@@ -31,14 +31,16 @@
#include "ts/I_Version.h"
#include "ts/ink_file.h"
#include "records/I_RecCore.h"
+#include "ts/ink_config.h"
#include "engine.h"
#include "file_system.h"
+#include "ts/runroot.h"
#include <fstream>
#include <iostream>
-#include <system_error>
#include <ftw.h>
+#include <pwd.h>
std::string directory_check = "";
@@ -94,64 +96,94 @@ check_run_path(const std::string &arg, const bool forceflag)
}
}
-// return true if the path is good to delete
-static bool
-check_delete_path(const std::string &arg, const bool forceflag)
-{
- if (arg.empty()) {
- return false;
- }
-
- std::ifstream check_file(arg);
- if (check_file) {
- return true;
- }
- return false;
-}
-
// handle the path of the engine during parsing
static std::string
-path_handler(std::string &path)
+path_handler(const std::string &path, bool run_flag, const std::string
&command)
{
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) == nullptr) {
ink_fatal("unexcepted failure from getcwd() code=%d", errno);
}
- // no path passed in, use cwd
- if (path.empty()) {
- return cwd;
+
+ if (run_flag) {
+ // no path passed in, use cwd
+ if (path.empty()) {
+ return cwd;
+ }
+ if (path[0] == '/') {
+ return path;
+ } else {
+ return Layout::relative_to(cwd, path);
+ }
}
- // absolute path
- if (path[0] == '/') {
- return path;
- } else {
- return Layout::relative_to(cwd, path);
- ;
+
+ // for other commands
+ // 1. passed in path
+ if (!path.empty()) {
+ std::string cmdpath;
+ if (path[0] == '/') {
+ cmdpath = check_path(path);
+ } else {
+ cmdpath = check_path(Layout::relative_to(cwd, path));
+ }
+ if (!cmdpath.empty()) {
+ return cmdpath;
+ }
+ }
+
+ // 2. check Environment variable
+ char *env_val = getenv("TS_RUNROOT");
+ if (env_val != nullptr) {
+ std::string envpath = check_path(env_val);
+ if (!envpath.empty()) {
+ return envpath;
+ }
+ }
+
+ // 3. find cwd or parent path of cwd to check
+ std::string cwdpath = check_parent_path(cwd);
+ if (!cwdpath.empty()) {
+ return cwdpath;
}
+
+ // 4. installed executable
+ char RealBinPath[PATH_MAX] = {0};
+ if (!command.empty() && realpath(command.c_str(), RealBinPath) != nullptr) {
+ std::string bindir = RealBinPath;
+ bindir = bindir.substr(0, bindir.find_last_of("/")); //
getting the bin dir not executable path
+ bindir = check_parent_path(bindir);
+ if (!bindir.empty()) {
+ return bindir;
+ }
+ }
+
+ return path;
}
// the help message for traffic_layout runroot
void
-RunrootEngine::runroot_help_message(const bool runflag, const bool cleanflag)
+RunrootEngine::runroot_help_message(const bool runflag, const bool cleanflag,
const bool verifyflag, const bool fixflag)
{
if (runflag) {
- std::cout << "\ninit Usage: traffic_layout init ([switch]) --path
/path/to/sandbox\n"
- "Note : if no path provided, please set Environment variable
$TS_RUNROOT\n"
- << std::endl;
+ std::cout << "\ninit Usage: traffic_layout init ([switch]) (--path
/path/to/sandbox)\n" << std::endl;
std::cout << "Sub-switches:\n"
- "--path Specify the path of the runroot (the path
should be the next argument)\n"
+ "--path Specify the path of the runroot to create (the
path should be the next argument)\n"
"--force Force to create ts_runroot even directory
already exists\n"
"--absolute Produce absolute path in the yaml file\n"
"--run-root(=/path) Using specified TS_RUNROOT as sandbox\n"
<< std::endl;
}
if (cleanflag) {
- std::cout << "\nremove Usage: traffic_layout remove ([switch]) --path
/path/to/sandbox\n"
- "Note : if no path provided, please set Environment variable
$TS_RUNROOT\n"
+ std::cout << "\nremove Usage: traffic_layout remove ([switch]) (--path
/path/to/sandbox)\n" << std::endl;
+ std::cout << "Sub-switches:\n"
+ "--path specify the path of the runroot to remove (the
path should be the next argument)\n"
+ "--force force to remove ts_runroot even with other
unknown files\n"
<< std::endl;
+ }
+ if (verifyflag) {
+ std::cout << "\nverify Usage: traffic_layout verify (--path
/path/to/sandbox)\n" << std::endl;
std::cout << "Sub-switches:\n"
- "--path specify the path of the runroot (the path
should be the next argument)\n"
- "--force force to remove ts_runroot even with other
unknown files\n"
+ "--path specify the path of the runroot to verify (the
path should be the next argument)\n"
<< std::endl;
}
return;
@@ -184,14 +216,28 @@ RunrootEngine::runroot_parse()
if (argument.substr(0, RUNROOT_WORD_LENGTH) == "--run-root") {
continue;
}
- // set init flag & sandbox path
+ // set init flag
if (argument == "init") {
run_flag = true;
+ command_num++;
continue;
}
- // set remove flag & sandbox path
+ // set remove flag
if (argument == "remove") {
clean_flag = true;
+ command_num++;
+ continue;
+ }
+ // set verify flag
+ if (argument == "verify") {
+ verify_flag = true;
+ command_num++;
+ continue;
+ }
+ // set fix flag
+ if (argument == "--fix") {
+ fix_flag = true;
+ command_num++;
continue;
}
if (argument == "--path") {
@@ -214,7 +260,7 @@ RunrootEngine::sanity_check()
{
// check output help or not
if (help_flag) {
- runroot_help_message(run_flag, clean_flag);
+ runroot_help_message(run_flag, clean_flag, verify_flag, fix_flag);
exit(0);
}
if (version_flag) {
@@ -224,53 +270,27 @@ RunrootEngine::sanity_check()
ink_fputln(stdout, appVersionInfo.FullVersionInfoStr);
exit(0);
}
- if (run_flag && clean_flag) {
- ink_fatal("Cannot run and clean in the same time");
+ if (command_num > 1) {
+ ink_fatal("Cannot run multiple command at the same time");
}
- if (!run_flag && !clean_flag) {
+ if (command_num < 1) {
ink_fatal("No command specified");
}
if ((force_flag && !run_flag) && (force_flag && !clean_flag)) {
ink_fatal("Nothing to force");
}
- path = path_handler(path);
+ path = path_handler(path, run_flag, _argv[0]);
- if (run_flag) {
- if (!check_run_path(path, force_flag)) {
- ink_fatal("Invalid path to create: %s", path.c_str());
- }
- }
- if (clean_flag) {
- if (!check_delete_path(path, force_flag)) {
- ink_fatal("Invalid path to remove: %s", path.c_str());
- }
- }
-}
-// for cleanning the parent of bin / cwd
-// return the path if we can clean the bin / cwd
-const static std::string
-clean_parent(const std::string &bin_path)
-{
- char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) == nullptr) {
- ink_fatal("unexcepted failure from getcwd() code=%d", errno);
- }
-
- char resolved_binpath[PATH_MAX];
- if (realpath(bin_path.c_str(), resolved_binpath) == nullptr) { // bin path
- ink_fatal("unexcepted failure from realpath() code=%d", errno);
+ if (path.empty()) {
+ ink_fatal("Path not valild (runroot_path.yml not found)");
}
- std::string RealBinPath = resolved_binpath;
- std::vector<std::string> TwoPath = {cwd, RealBinPath};
- for (auto it : TwoPath) {
- std::string path = check_parent_path(it);
- if (path.size() != 0) {
- return path;
+ if (run_flag) {
+ if (!check_run_path(path, force_flag)) {
+ ink_fatal("Failed to create runroot with path '%s'", path.c_str());
}
}
- return "";
}
// the function for removing the runroot
@@ -286,54 +306,42 @@ RunrootEngine::clean_runroot()
std::string cur_working_dir = cwd;
if (force_flag) {
- std::ifstream check_file(Layout::relative_to(clean_root,
"runroot_path.yml"));
- if (!check_file.good()) {
- ink_fatal("invalid path to clean (no runroot_path.yml file found)");
- }
// the force clean
if (!check_force()) {
std::cout << "Force remove terminated" << std::endl;
exit(0);
}
std::cout << "Forcing removing runroot ..." << std::endl;
- if (cur_working_dir == path) {
+ if (cur_working_dir == clean_root) {
// if cwd is the runroot, keep the directory and remove everything
insides
remove_inside_directory(clean_root);
} else {
if (!remove_directory(clean_root)) {
- ink_warning("Failed force removing runroot: %s - %s",
clean_root.c_str(), strerror(errno));
+ ink_warning("Failed force removing runroot '%s' - %s",
clean_root.c_str(), strerror(errno));
}
}
} else {
- // if we can find the yaml, then clean it
- std::ifstream check_file(Layout::relative_to(clean_root,
"runroot_path.yml"));
- if (check_file.good() || !clean_parent(_argv[0]).empty()) {
- if (!clean_parent(_argv[0]).empty()) {
- clean_root = clean_parent(_argv[0]);
- }
- // handle the map and deleting of each directories specified in the yml
file
- std::string yaml_file = Layout::relative_to(clean_root,
"runroot_path.yml");
- std::unordered_map<std::string, std::string> map =
runroot_map(yaml_file, clean_root);
- map.erase("prefix");
- map.erase("exec_prefix");
- append_slash(clean_root);
- for (auto it : map) {
- std::string dir = it.second;
- append_slash(dir);
- std::string later_dir = dir.substr(clean_root.size());
- dir = Layout::relative_to(clean_root,
later_dir.substr(0, later_dir.find_first_of("/")));
- remove_directory(dir);
- }
- // coverity issue need check on value
- if (yaml_file.size()) {
- remove(yaml_file.c_str());
- }
- if (cur_working_dir != path) {
- // if the runroot is empty, remove it
- remove(clean_root.c_str());
- }
- } else {
- ink_fatal("runroot_path.yml not found - invalid path to clean");
+ // handle the map and deleting of each directories specified in the yml
file
+ std::unordered_map<std::string, std::string> map = runroot_map(clean_root);
+ map.erase("prefix");
+ map.erase("exec_prefix");
+ append_slash(clean_root);
+ for (auto it : map) {
+ std::string dir = it.second;
+ append_slash(dir);
+ std::string later_dir = dir.substr(clean_root.size());
+ dir = Layout::relative_to(clean_root,
later_dir.substr(0, later_dir.find_first_of("/")));
+ remove_directory(dir);
+ }
+
+ std::string yaml_file = Layout::relative_to(clean_root,
"runroot_path.yml");
+ // remove yml file
+ if (yaml_file.size()) {
+ remove(yaml_file.c_str());
+ }
+ if (cur_working_dir != clean_root) {
+ // if the runroot is empty, remove it
+ remove(clean_root.c_str());
}
}
}
@@ -437,7 +445,7 @@ RunrootEngine::copy_runroot(const std::string
&original_root, const std::string
}
if (!copy_directory(old_path, new_path)) {
- ink_warning("Copy failed for %s - %s", it.first.c_str(),
strerror(errno));
+ ink_warning("Copy failed for '%s' - %s", it.first.c_str(),
strerror(errno));
}
}
@@ -449,3 +457,123 @@ RunrootEngine::copy_runroot(const std::string
&original_root, const std::string
path_map["prefix"] = ".";
}
}
+
+// return an array containing gid and uid of provided user
+static std::pair<int, int>
+get_giduid(const char *user)
+{
+ passwd *pwd;
+ if (*user == '#') {
+ // Numeric user notation.
+ uid_t uid = (uid_t)atoi(&user[1]);
+ pwd = getpwuid(uid);
+ } else {
+ pwd = getpwnam(user);
+ }
+ if (!pwd) {
+ // null ptr
+ ink_fatal("missing password database entry for '%s'", user);
+ }
+ std::pair<int, int> giduid = {int(pwd->pw_gid), int(pwd->pw_uid)};
+ return giduid;
+}
+
+static void
+output_read_permission(const std::string &permission)
+{
+ if (permission[0] == '1') {
+ std::cout << "\tRead Permission: \033[1;32mPASSED\033[0m" << std::endl;
+ } else {
+ std::cout << "\tRead Permission: \033[1;31mFAILED\033[0m" << std::endl;
+ }
+}
+
+static void
+output_write_permission(const std::string &permission)
+{
+ if (permission[1] == '1') {
+ std::cout << "\tWrite Permission: \033[1;32mPASSED\033[0m" << std::endl;
+ } else {
+ std::cout << "\tWrite Permission: \033[1;31mFAILED\033[0m" << std::endl;
+ }
+}
+
+static void
+output_execute_permission(const std::string &permission)
+{
+ if (permission[2] == '1') {
+ std::cout << "\tExecute Permission: \033[1;32mPASSED\033[0m" << std::endl;
+ } else {
+ std::cout << "\tExecute Permission: \033[1;31mFAILED\033[0m" << std::endl;
+ }
+}
+
+void
+RunrootEngine::verify_runroot()
+{
+ std::pair<int, int> giduid = get_giduid(TS_PKGSYSUSER);
+
+ int gid = giduid.first;
+ int uid = giduid.second;
+
+ std::cout << "trafficserver user: " << TS_PKGSYSUSER << std::endl <<
std::endl;
+
+ if (int(getuid()) != uid) {
+ if (getuid() != 0) {
+ ink_error("In order to test as user '%s', root privileges are
required.\nPlease run with sudo.", TS_PKGSYSUSER);
+ exit(70);
+ }
+ if (setregid(gid, gid) != 0) {
+ ink_fatal("failed to set group ID '%d' - %s", gid, strerror(errno));
+ }
+ if (setreuid(uid, uid) != 0) {
+ ink_fatal("failed to set user ID '%d' - %s", uid, strerror(errno));
+ }
+ }
+
+ std::unordered_map<std::string, std::string> path_map = runroot_map(path);
+ std::unordered_map<std::string, std::string> permission_map;
+
+ // set up permission map for all permissions
+ for (auto it : path_map) {
+ std::string name = it.first;
+ std::string value = it.second;
+
+ if (name == "prefix" || name == "exec_prefix")
+ continue;
+
+ permission_map[name] = "000"; // default rwx all 0
+
+ if (!access(value.c_str(), R_OK)) {
+ permission_map[name][0] = '1';
+ }
+ if (!access(value.c_str(), W_OK)) {
+ permission_map[name][1] = '1';
+ }
+ if (!access(value.c_str(), X_OK)) {
+ permission_map[name][2] = '1';
+ }
+ }
+
+ // display pass or fail for permission required
+ for (auto it : permission_map) {
+ std::string name = it.first;
+ std::string permission = it.second;
+ std::cout << name << ": \x1b[1m" + path_map[name] + "\x1b[0m" << std::endl;
+
+ // check for read permission
+ if (name == "includedir" || name == "mandir" || name == "sysconfdir" ||
name == "datadir") {
+ output_read_permission(permission);
+ }
+ // check for write permission
+ if (name == "localstatedir" || name == "logdir" || name == "runtimedir" ||
name == "cachedir") {
+ output_read_permission(permission);
+ output_write_permission(permission);
+ }
+ // check for execute permission
+ if (name == "bindir" || name == "sbindir" || name == "libdir" || name ==
"libexecdir") {
+ output_read_permission(permission);
+ output_execute_permission(permission);
+ }
+ }
+}
diff --git a/cmd/traffic_layout/engine.h b/cmd/traffic_layout/engine.h
index 4f16bd8..112f906 100644
--- a/cmd/traffic_layout/engine.h
+++ b/cmd/traffic_layout/engine.h
@@ -43,12 +43,15 @@ struct RunrootEngine {
// the function of creating runroot
void create_runroot();
+ // the function of verifying runroot
+ void verify_runroot();
+
// copy the stuff from original_root to ts_runroot
// fill in the global map for yaml file emitting later
void copy_runroot(const std::string &original_root, const std::string
&ts_runroot);
// the help message for runroot
- void runroot_help_message(const bool runflag, const bool cleanflag);
+ void runroot_help_message(const bool runflag, const bool cleanflag, const
bool verifyflag, const bool fixflag);
// the pass in arguments
std::vector<std::string> _argv;
@@ -59,6 +62,11 @@ struct RunrootEngine {
bool clean_flag = false;
bool force_flag = false;
bool abs_flag = false;
+ bool verify_flag = false;
+ bool fix_flag = false;
+ // for parsing
+ int command_num = 0;
+
// the path for create & remove
std::string path;
diff --git a/cmd/traffic_layout/file_system.h b/cmd/traffic_layout/file_system.h
index 985220e..1ed5f61 100644
--- a/cmd/traffic_layout/file_system.h
+++ b/cmd/traffic_layout/file_system.h
@@ -38,9 +38,9 @@ void append_slash(std::string &path);
void remove_slash(std::string &path);
// some checks for directory exist or is it a directory
-bool exists(std::string const &dir);
+bool exists(const std::string &dir);
-bool is_directory(std::string const &directory);
+bool is_directory(const std::string &directory);
// for file system
bool create_directory(const std::string &dir);
diff --git a/cmd/traffic_layout/traffic_layout.cc
b/cmd/traffic_layout/traffic_layout.cc
index 548ca6e..40dab37 100644
--- a/cmd/traffic_layout/traffic_layout.cc
+++ b/cmd/traffic_layout/traffic_layout.cc
@@ -66,6 +66,7 @@ help_usage()
"init Initialize the ts_runroot sandbox\n"
"remove Remove the ts_runroot sandbox\n"
"info Show the layout as default\n"
+ "verify: Verify the ts_runroot paths\n"
<< std::endl;
std::cout << "Switches of runroot:\n"
"--path Specify the path of the runroot\n"
@@ -73,7 +74,7 @@ help_usage()
"--absolute: Produce absolute path in the yaml file\n"
"--run-root(=/path): Using specified TS_RUNROOT as sandbox\n"
<< std::endl;
-
+ printf("Detailed usage and description in traffic_layout.en.rst\n");
printf("General Usage:\n");
usage(argument_descriptions, countof(argument_descriptions), nullptr);
}
@@ -128,7 +129,7 @@ traffic_runroot(int argc, const char **argv)
}
// parse the command line & put into global variable
if (!engine.runroot_parse()) {
- engine.runroot_help_message(true, true);
+ engine.runroot_help_message(true, true, true, true);
return 0;
}
// check sanity of the command about the runroot program
@@ -138,13 +139,15 @@ traffic_runroot(int argc, const char **argv)
runroot_handler(argv);
Layout::create();
- // check to clean the runroot or not
- if (engine.clean_flag) {
- engine.clean_runroot();
- std::cout << "runroot removed" << std::endl;
- } else {
+ // check the command to execute
+ if (engine.run_flag) {
engine.create_runroot();
+ } else if (engine.clean_flag) {
+ engine.clean_runroot();
+ } else if (engine.verify_flag) {
+ engine.verify_runroot();
}
+
return 0;
}
@@ -155,6 +158,8 @@ main(int argc, const char **argv)
{info, "info", "Show the layout"},
{traffic_runroot, "init", "Initialize the ts_runroot sandbox"},
{traffic_runroot, "remove", "Remove the ts_runroot sandbox"},
+ {traffic_runroot, "verify", "verify the ts_runroot paths"},
+ {traffic_runroot, "fix", "fix permmision issue of the ts_runroot"},
};
// with command (info, init, remove)
diff --git a/lib/ts/runroot.cc b/lib/ts/runroot.cc
index f641623..bf05f48 100644
--- a/lib/ts/runroot.cc
+++ b/lib/ts/runroot.cc
@@ -177,30 +177,31 @@ runroot_handler(const char **argv, bool json)
// return a map of all path in runroot_path.yml
std::unordered_map<std::string, std::string>
-runroot_map(std::string &yaml_path, std::string &prefix)
+runroot_map(const std::string &prefix)
{
+ std::string yaml_path = Layout::relative_to(prefix, "runroot_path.yml");
std::ifstream file;
file.open(yaml_path);
if (!file.good()) {
- ink_warning("Bad path, continue with default value");
+ ink_warning("Bad path '%s', continue with default value", prefix.c_str());
return std::unordered_map<std::string, std::string>{};
}
std::ifstream yamlfile(yaml_path);
- std::unordered_map<std::string, std::string> runroot_map;
+ std::unordered_map<std::string, std::string> map;
std::string str;
while (std::getline(yamlfile, str)) {
int pos = str.find(':');
- runroot_map[str.substr(0, pos)] = str.substr(pos + 2);
+ map[str.substr(0, pos)] = str.substr(pos + 2);
}
// change it to absolute path in the map
- for (auto it : runroot_map) {
+ for (auto it : map) {
if (it.second[0] != '/') {
- runroot_map[it.first] = Layout::relative_to(prefix, it.second);
+ map[it.first] = Layout::relative_to(prefix, it.second);
}
}
- return runroot_map;
+ return map;
}
// check for the using of runroot
@@ -217,6 +218,5 @@ check_runroot()
if ((len + 1) > PATH_NAME_MAX) {
ink_fatal("runroot path is too big: %d, max %d\n", len, PATH_NAME_MAX - 1);
}
- std::string yaml_path = Layout::relative_to(using_runroot,
"runroot_path.yml");
- return runroot_map(yaml_path, using_runroot);
+ return runroot_map(using_runroot);
}
diff --git a/lib/ts/runroot.h b/lib/ts/runroot.h
index f6c2795..23a1aa5 100644
--- a/lib/ts/runroot.h
+++ b/lib/ts/runroot.h
@@ -29,12 +29,14 @@
#include <string>
#include <unordered_map>
+std::string check_path(const std::string &path);
+
std::string check_parent_path(const std::string &path);
void runroot_handler(const char **argv, bool json = false);
// get runroot map from yaml path and prefix
-std::unordered_map<std::string, std::string> runroot_map(std::string
&yaml_path, std::string &prefix);
+std::unordered_map<std::string, std::string> runroot_map(const std::string
&prefix);
// help check runroot for layout
std::unordered_map<std::string, std::string> check_runroot();
--
To stop receiving notification emails like this one, please contact
[email protected].