cmdline: simplify string splitting
This commit is contained in:
parent
7b9178f5d7
commit
f1a6b08962
108
cmdline.cc
108
cmdline.cc
@ -43,6 +43,8 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "caps.h"
|
||||
#include "config.h"
|
||||
@ -293,29 +295,16 @@ uint64_t parseRLimit(int res, const char* optarg, unsigned long mul) {
|
||||
return val;
|
||||
}
|
||||
|
||||
/* findSpecDestination mutates spec (source:dest) to have a null byte instead
|
||||
* of ':' in between source and dest, then returns a pointer to the dest
|
||||
* string. */
|
||||
static char* cmdlineSplitStrByColon(char* spec) {
|
||||
if (spec == NULL) {
|
||||
return NULL;
|
||||
static std::string argByColon(const char* str, size_t pos) {
|
||||
if (!str) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char* dest = spec;
|
||||
while (*dest != ':' && *dest != '\0') {
|
||||
dest++;
|
||||
}
|
||||
|
||||
switch (*dest) {
|
||||
case ':':
|
||||
*dest = '\0';
|
||||
return dest + 1;
|
||||
case '\0':
|
||||
return NULL;
|
||||
default:
|
||||
LOG_F("Impossible condition in cmdlineSplitStrByColon()");
|
||||
return NULL;
|
||||
std::vector<std::string> vec;
|
||||
util::strSplit(str, &vec, ':');
|
||||
if (pos > vec.size()) {
|
||||
return "";
|
||||
}
|
||||
return vec[pos];
|
||||
}
|
||||
|
||||
std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
|
||||
@ -568,66 +557,67 @@ std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
|
||||
nsjconf->envs.push_back(optarg);
|
||||
break;
|
||||
case 'u': {
|
||||
char* i_id = optarg;
|
||||
char* o_id = cmdlineSplitStrByColon(i_id);
|
||||
char* cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count =
|
||||
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
|
||||
if (user::parseId(nsjconf.get(), i_id, o_id, count, false /* is_gid */,
|
||||
false /* is_newidmap */) == false) {
|
||||
std::string i_id = argByColon(optarg, 0);
|
||||
std::string o_id = argByColon(optarg, 1);
|
||||
std::string cnt = argByColon(optarg, 2);
|
||||
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
|
||||
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ false,
|
||||
/* is_newidmap= */ false)) {
|
||||
return nullptr;
|
||||
}
|
||||
} break;
|
||||
case 'g': {
|
||||
char* i_id = optarg;
|
||||
char* o_id = cmdlineSplitStrByColon(i_id);
|
||||
char* cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count =
|
||||
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
|
||||
if (user::parseId(nsjconf.get(), i_id, o_id, count, true /* is_gid */,
|
||||
false /* is_newidmap */) == false) {
|
||||
std::string i_id = argByColon(optarg, 0);
|
||||
std::string o_id = argByColon(optarg, 1);
|
||||
std::string cnt = argByColon(optarg, 2);
|
||||
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
|
||||
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ true,
|
||||
/* is_newidmap= */ false)) {
|
||||
return nullptr;
|
||||
}
|
||||
} break;
|
||||
case 'U': {
|
||||
char* i_id = optarg;
|
||||
char* o_id = cmdlineSplitStrByColon(i_id);
|
||||
char* cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count =
|
||||
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
|
||||
if (user::parseId(nsjconf.get(), i_id, o_id, count, false /* is_gid */,
|
||||
true /* is_newidmap */) == false) {
|
||||
std::string i_id = argByColon(optarg, 0);
|
||||
std::string o_id = argByColon(optarg, 1);
|
||||
std::string cnt = argByColon(optarg, 2);
|
||||
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
|
||||
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ false,
|
||||
/* is_newidmap= */ true)) {
|
||||
return nullptr;
|
||||
}
|
||||
} break;
|
||||
case 'G': {
|
||||
char* i_id = optarg;
|
||||
char* o_id = cmdlineSplitStrByColon(i_id);
|
||||
char* cnt = cmdlineSplitStrByColon(o_id);
|
||||
size_t count =
|
||||
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
|
||||
if (user::parseId(nsjconf.get(), i_id, o_id, count, true /* is_gid */,
|
||||
true /* is_newidmap */) == false) {
|
||||
std::string i_id = argByColon(optarg, 0);
|
||||
std::string o_id = argByColon(optarg, 1);
|
||||
std::string cnt = argByColon(optarg, 2);
|
||||
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
|
||||
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ true,
|
||||
/* is_newidmap= */ true)) {
|
||||
return nullptr;
|
||||
}
|
||||
} break;
|
||||
case 'R': {
|
||||
const char* dst = cmdlineSplitStrByColon(optarg);
|
||||
dst = dst ? dst : optarg;
|
||||
if (!mnt::addMountPtTail(nsjconf.get(), /* src= */ optarg, dst,
|
||||
/* fs_type= */ "",
|
||||
/* options= */ "", MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY,
|
||||
std::string src = argByColon(optarg, 0);
|
||||
std::string dst = argByColon(optarg, 1);
|
||||
if (dst.empty()) {
|
||||
dst = src;
|
||||
}
|
||||
if (!mnt::addMountPtTail(nsjconf.get(), src.c_str(), dst.c_str(),
|
||||
/* fs_type= */ "", /* options= */ "",
|
||||
MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY,
|
||||
/* isDir= */ mnt::NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL,
|
||||
NULL, 0, /* is_symlink= */ false)) {
|
||||
return nullptr;
|
||||
}
|
||||
}; break;
|
||||
case 'B': {
|
||||
const char* dst = cmdlineSplitStrByColon(optarg);
|
||||
dst = dst ? dst : optarg;
|
||||
if (!mnt::addMountPtTail(nsjconf.get(), /* src= */ optarg, dst,
|
||||
/* fs_type= */ "",
|
||||
/* options= */ "", MS_BIND | MS_REC | MS_PRIVATE,
|
||||
std::string src = argByColon(optarg, 0);
|
||||
std::string dst = argByColon(optarg, 1);
|
||||
if (dst.empty()) {
|
||||
dst = src;
|
||||
}
|
||||
if (!mnt::addMountPtTail(nsjconf.get(), src.c_str(), dst.c_str(),
|
||||
/* fs_type= */ "", /* options= */ "", MS_BIND | MS_REC | MS_PRIVATE,
|
||||
/* isDir= */ mnt::NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL,
|
||||
NULL, 0, /* is_symlink= */ false)) {
|
||||
return nullptr;
|
||||
|
12
config.cc
12
config.cc
@ -45,8 +45,6 @@
|
||||
|
||||
namespace config {
|
||||
|
||||
#define VAL_IF_SET_OR_NULL(njc, val) (njc.has_##val() ? njc.val().c_str() : NULL)
|
||||
|
||||
static uint64_t configRLimit(
|
||||
int res, const nsjail::RLimit& rl, const uint64_t val, unsigned long mul = 1UL) {
|
||||
if (rl == nsjail::RLimit::VALUE) {
|
||||
@ -186,16 +184,14 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig&
|
||||
nsjconf->clone_newcgroup = njc.clone_newcgroup();
|
||||
|
||||
for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
|
||||
if (!user::parseId(nsjconf, VAL_IF_SET_OR_NULL(njc.uidmap(i), inside_id),
|
||||
VAL_IF_SET_OR_NULL(njc.uidmap(i), outside_id), njc.uidmap(i).count(),
|
||||
false /* is_gid */, njc.uidmap(i).use_newidmap())) {
|
||||
if (!user::parseId(nsjconf, njc.uidmap(i).inside_id(), njc.uidmap(i).outside_id(),
|
||||
njc.uidmap(i).count(), false /* is_gid */, njc.uidmap(i).use_newidmap())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (ssize_t i = 0; i < njc.gidmap_size(); i++) {
|
||||
if (!user::parseId(nsjconf, VAL_IF_SET_OR_NULL(njc.gidmap(i), inside_id),
|
||||
VAL_IF_SET_OR_NULL(njc.gidmap(i), outside_id), njc.gidmap(i).count(),
|
||||
true /* is_gid */, njc.gidmap(i).use_newidmap())) {
|
||||
if (!user::parseId(nsjconf, njc.gidmap(i).inside_id(), njc.gidmap(i).outside_id(),
|
||||
njc.gidmap(i).count(), true /* is_gid */, njc.gidmap(i).use_newidmap())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
36
user.cc
36
user.cc
@ -265,59 +265,63 @@ bool initNsFromChild(nsjconf_t* nsjconf) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static uid_t parseUid(const char* id) {
|
||||
if (id == NULL || strlen(id) == 0) {
|
||||
static uid_t parseUid(const std::string& id) {
|
||||
if (id.empty()) {
|
||||
return getuid();
|
||||
}
|
||||
struct passwd* pw = getpwnam(id);
|
||||
struct passwd* pw = getpwnam(id.c_str());
|
||||
if (pw != NULL) {
|
||||
return pw->pw_uid;
|
||||
}
|
||||
if (util::isANumber(id)) {
|
||||
return (uid_t)strtoull(id, NULL, 0);
|
||||
if (util::isANumber(id.c_str())) {
|
||||
return (uid_t)strtoull(id.c_str(), NULL, 0);
|
||||
}
|
||||
return (uid_t)-1;
|
||||
}
|
||||
|
||||
static gid_t parseGid(const char* id) {
|
||||
if (id == NULL || strlen(id) == 0) {
|
||||
static gid_t parseGid(const std::string& id) {
|
||||
if (id.empty()) {
|
||||
return getgid();
|
||||
}
|
||||
struct group* gr = getgrnam(id);
|
||||
struct group* gr = getgrnam(id.c_str());
|
||||
if (gr != NULL) {
|
||||
return gr->gr_gid;
|
||||
}
|
||||
if (util::isANumber(id)) {
|
||||
return (gid_t)strtoull(id, NULL, 0);
|
||||
if (util::isANumber(id.c_str())) {
|
||||
return (gid_t)strtoull(id.c_str(), NULL, 0);
|
||||
}
|
||||
return (gid_t)-1;
|
||||
}
|
||||
|
||||
bool parseId(nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt, bool is_gid,
|
||||
bool is_newidmap) {
|
||||
bool parseId(nsjconf_t* nsjconf, const std::string& i_id, const std::string& o_id, size_t cnt,
|
||||
bool is_gid, bool is_newidmap) {
|
||||
if (cnt < 1) {
|
||||
cnt = 1;
|
||||
}
|
||||
|
||||
uid_t inside_id;
|
||||
uid_t outside_id;
|
||||
|
||||
if (is_gid) {
|
||||
inside_id = parseGid(i_id);
|
||||
if (inside_id == (uid_t)-1) {
|
||||
LOG_W("Cannot parse '%s' as GID", i_id);
|
||||
LOG_W("Cannot parse '%s' as GID", i_id.c_str());
|
||||
return false;
|
||||
}
|
||||
outside_id = parseGid(o_id);
|
||||
if (outside_id == (uid_t)-1) {
|
||||
LOG_W("Cannot parse '%s' as GID", o_id);
|
||||
LOG_W("Cannot parse '%s' as GID", o_id.c_str());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
inside_id = parseUid(i_id);
|
||||
if (inside_id == (uid_t)-1) {
|
||||
LOG_W("Cannot parse '%s' as UID", i_id);
|
||||
LOG_W("Cannot parse '%s' as UID", i_id.c_str());
|
||||
return false;
|
||||
}
|
||||
outside_id = parseUid(o_id);
|
||||
if (outside_id == (uid_t)-1) {
|
||||
LOG_W("Cannot parse '%s' as UID", o_id);
|
||||
LOG_W("Cannot parse '%s' as UID", o_id.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
7
user.h
7
user.h
@ -24,15 +24,16 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "nsjail.h"
|
||||
|
||||
namespace user {
|
||||
|
||||
bool initNsFromParent(nsjconf_t* nsjconf, pid_t pid);
|
||||
bool initNsFromChild(nsjconf_t* nsjconf);
|
||||
|
||||
bool parseId(nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt, bool is_gid,
|
||||
bool is_newidmap);
|
||||
bool parseId(nsjconf_t* nsjconf, const std::string& i_id, const std::string& o_id, size_t cnt,
|
||||
bool is_gid, bool is_newidmap);
|
||||
|
||||
} // namespace user
|
||||
|
||||
|
10
util.cc
10
util.cc
@ -40,7 +40,9 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "logs.h"
|
||||
#include "macros.h"
|
||||
@ -279,4 +281,12 @@ const std::string timeToStr(time_t t) {
|
||||
return timestr;
|
||||
}
|
||||
|
||||
void strSplit(const std::string str, std::vector<std::string>* vec, char delim) {
|
||||
std::string word;
|
||||
std::istringstream stream(str);
|
||||
for (std::string word; std::getline(stream, word, delim);) {
|
||||
vec->push_back(word);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
2
util.h
2
util.h
@ -27,6 +27,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "nsjail.h"
|
||||
|
||||
@ -42,6 +43,7 @@ bool isANumber(const char* s);
|
||||
uint64_t rnd64(void);
|
||||
const std::string sigName(int signo);
|
||||
const std::string timeToStr(time_t t);
|
||||
void strSplit(const std::string str, std::vector<std::string>* vec, char delim);
|
||||
|
||||
} // namespace util
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user