409 lines
12 KiB
Diff
409 lines
12 KiB
Diff
|
|
From 8da6dd20b73068e9d29fc8ed1469ade7b1dc2c12 Mon Sep 17 00:00:00 2001
|
||
|
|
From: haozi007 <liuhao27@huawei.com>
|
||
|
|
Date: Sat, 14 May 2022 09:55:18 +0100
|
||
|
|
Subject: [PATCH 15/16] refactor util_getgrent_r and util_getpwent_r
|
||
|
|
|
||
|
|
Signed-off-by: haozi007 <liuhao27@huawei.com>
|
||
|
|
---
|
||
|
|
src/utils/cutils/utils_pwgr.c | 215 +++++++++++-------------
|
||
|
|
test/cutils/utils_pwgr/passwd_sample | 8 +-
|
||
|
|
test/cutils/utils_pwgr/utils_pwgr_ut.cc | 8 +-
|
||
|
|
3 files changed, 109 insertions(+), 122 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/src/utils/cutils/utils_pwgr.c b/src/utils/cutils/utils_pwgr.c
|
||
|
|
index 17cf017b..f8e4a18e 100644
|
||
|
|
--- a/src/utils/cutils/utils_pwgr.c
|
||
|
|
+++ b/src/utils/cutils/utils_pwgr.c
|
||
|
|
@@ -29,100 +29,82 @@
|
||
|
|
|
||
|
|
static int hold_int(const char delim, bool required, char **src, unsigned int *dst)
|
||
|
|
{
|
||
|
|
- long long res = 0;
|
||
|
|
- char *walker = *src;
|
||
|
|
+ unsigned long long int res = 0;
|
||
|
|
char *err_str = NULL;
|
||
|
|
|
||
|
|
+ // ensure *src not a empty string
|
||
|
|
if (**src == '\0') {
|
||
|
|
ERROR("Empty subject on given entrie is not allowed.");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
- while (*walker != delim) {
|
||
|
|
- if (*walker == '\0') {
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
- ++walker;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (*walker == **src) {
|
||
|
|
- if (required) { // deafult 0 while required full content but integer part is missing
|
||
|
|
- *dst = 0;
|
||
|
|
- *src = walker + 1;
|
||
|
|
- return 0;
|
||
|
|
- }
|
||
|
|
- ERROR("Integer part is missing.");
|
||
|
|
- ++(*src);
|
||
|
|
- return -1;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- res = strtoll(*src, &err_str, 0);
|
||
|
|
- if (err_str == *src) {
|
||
|
|
- ERROR("invalid digits string.");
|
||
|
|
- return -1;
|
||
|
|
- }
|
||
|
|
+ // covert string to long long
|
||
|
|
+ res = strtoull(*src, &err_str, 0);
|
||
|
|
+ // large digit string, return error
|
||
|
|
if (errno == ERANGE) {
|
||
|
|
ERROR("Parse int from string failed.");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
- if (res < 0) {
|
||
|
|
- ERROR("Gid uid shall not be negative.");
|
||
|
|
- return -1;
|
||
|
|
+
|
||
|
|
+ // **src is not a digit
|
||
|
|
+ if (err_str == *src) {
|
||
|
|
+ if (!required) {
|
||
|
|
+ ERROR("Integer part is missing.");
|
||
|
|
+ return -1;
|
||
|
|
+ }
|
||
|
|
+ // if required, just set 0
|
||
|
|
+ *dst = 0;
|
||
|
|
+ } else {
|
||
|
|
+ if (sizeof(void *) > 4 && res > UINT_MAX) { // make sure 64-bit platform behave same as 32-bit
|
||
|
|
+ res = UINT_MAX;
|
||
|
|
+ }
|
||
|
|
+ res = res & UINT_MAX;
|
||
|
|
+ *dst = (uint32_t)res;
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (sizeof(void *) > 4 && res > UINT_MAX) { // make sure 64-bit platform behave same as 32-bit
|
||
|
|
- res = UINT_MAX;
|
||
|
|
+ // normal case
|
||
|
|
+ if (*err_str == delim) {
|
||
|
|
+ err_str++;
|
||
|
|
+ } else if (*err_str != '\0') {
|
||
|
|
+ ERROR("Invalid digit string.");
|
||
|
|
+ return -1;
|
||
|
|
}
|
||
|
|
- res = res & UINT_MAX;
|
||
|
|
- *dst = (uint32_t)res;
|
||
|
|
- *src = err_str + 1; // update src to next valid context in line.
|
||
|
|
|
||
|
|
+ *src = err_str; // update src to next valid context in line.
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
-static int hold_string(const char delim, char **src, char **dst)
|
||
|
|
+static void hold_string(const char delim, char **src, char **dst)
|
||
|
|
{
|
||
|
|
- if (**src == delim) { // if src point to deliminator, content parsing is skiped.
|
||
|
|
- *dst = "";
|
||
|
|
- *src = *src + 1;
|
||
|
|
- return 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (**src == '\0') {
|
||
|
|
- return 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
for (*dst = *src; **src != delim; ++(*src)) {
|
||
|
|
if (**src == '\0') {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+
|
||
|
|
if (**src == delim) {
|
||
|
|
**src = '\0';
|
||
|
|
++(*src);
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int parse_line_pw(const char delim, char *line, struct passwd *result)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
bool required = false;
|
||
|
|
+ char *walker = NULL;
|
||
|
|
|
||
|
|
- ret = hold_string(delim, &line, &result->pw_name);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse name error.");
|
||
|
|
- return ret;
|
||
|
|
+ walker = strpbrk(line, "\n");
|
||
|
|
+ if (walker != NULL) {
|
||
|
|
+ // clear newline char
|
||
|
|
+ *walker = '\0';
|
||
|
|
}
|
||
|
|
|
||
|
|
+ hold_string(delim, &line, &result->pw_name);
|
||
|
|
+
|
||
|
|
required = (result->pw_name[0] == '+' || result->pw_name[0] == '-') ? true : false;
|
||
|
|
|
||
|
|
- ret = hold_string(delim, &line, &result->pw_passwd);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse passwd error.");
|
||
|
|
- return ret;
|
||
|
|
- }
|
||
|
|
+ hold_string(delim, &line, &result->pw_passwd);
|
||
|
|
|
||
|
|
ret = hold_int(delim, required, &line, &result->pw_uid);
|
||
|
|
if (ret != 0) {
|
||
|
|
@@ -130,31 +112,20 @@ static int parse_line_pw(const char delim, char *line, struct passwd *result)
|
||
|
|
ERROR("Parse uid error.");
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
+
|
||
|
|
ret = hold_int(delim, required, &line, &result->pw_gid);
|
||
|
|
if (ret != 0) {
|
||
|
|
// it's ok to not provide gid
|
||
|
|
ERROR("Parse gid error.");
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- ret = hold_string(delim, &line, &result->pw_gecos);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse gecos error.");
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
- ret = hold_string(delim, &line, &result->pw_dir);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse dir error.");
|
||
|
|
- return ret;
|
||
|
|
- }
|
||
|
|
+ hold_string(delim, &line, &result->pw_gecos);
|
||
|
|
|
||
|
|
- ret = hold_string(delim, &line, &result->pw_shell);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse shell error.");
|
||
|
|
- return ret;
|
||
|
|
- }
|
||
|
|
+ hold_string(delim, &line, &result->pw_dir);
|
||
|
|
|
||
|
|
- return ret;
|
||
|
|
+ result->pw_shell = line;
|
||
|
|
+ return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static char **hold_string_list(char **line, char *buf_start, char *buf_end, const char terminator)
|
||
|
|
@@ -172,42 +143,38 @@ static char **hold_string_list(char **line, char *buf_start, char *buf_end, cons
|
||
|
|
walker = result;
|
||
|
|
|
||
|
|
for (; walker < (char **)buf_end; ++walker) {
|
||
|
|
- (void)util_trim_space(*line);
|
||
|
|
- if (hold_string(',', line, walker) != 0) {
|
||
|
|
- ERROR("Parse string list error.");
|
||
|
|
+ if (**line == '\0') {
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
+ (void)util_trim_space(*line);
|
||
|
|
+ hold_string(',', line, walker);
|
||
|
|
+
|
||
|
|
if ((char *)(walker + 2) > buf_end) {
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- if (**line == '\0') {
|
||
|
|
- return result;
|
||
|
|
- }
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
-static int parse_line_gr(const char delim, char *line, size_t buflen, struct group *result)
|
||
|
|
+static int parse_line_gr(const char delim, char *line, char *buffend, struct group *result)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
bool rf = false;
|
||
|
|
char *freebuff = line + 1 + strlen(line);
|
||
|
|
- char *buffend = line + buflen;
|
||
|
|
+ char *walker = NULL;
|
||
|
|
|
||
|
|
- ret = hold_string(delim, &line, &result->gr_name);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse name error.");
|
||
|
|
- return ret;
|
||
|
|
+ walker = strpbrk(line, "\n");
|
||
|
|
+ if (walker != NULL) {
|
||
|
|
+ // clear newline char
|
||
|
|
+ *walker = '\0';
|
||
|
|
}
|
||
|
|
|
||
|
|
- ret = hold_string(delim, &line, &result->gr_passwd);
|
||
|
|
- if (ret != 0) {
|
||
|
|
- ERROR("Parse gecos error.");
|
||
|
|
- return ret;
|
||
|
|
- }
|
||
|
|
+ hold_string(delim, &line, &result->gr_name);
|
||
|
|
+
|
||
|
|
+ hold_string(delim, &line, &result->gr_passwd);
|
||
|
|
+
|
||
|
|
if (result->gr_name[0] == '+' || result->gr_name[0] == '-') {
|
||
|
|
rf = true;
|
||
|
|
}
|
||
|
|
@@ -231,6 +198,7 @@ int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t bu
|
||
|
|
{
|
||
|
|
const char delim = ':';
|
||
|
|
char *buff_end = NULL;
|
||
|
|
+ char *walker = NULL;
|
||
|
|
bool got = false;
|
||
|
|
|
||
|
|
if (stream == NULL || resbuf == NULL || buffer == NULL || result == NULL) {
|
||
|
|
@@ -250,27 +218,36 @@ int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t bu
|
||
|
|
|
||
|
|
__fsetlocking(stream, FSETLOCKING_BYCALLER);
|
||
|
|
|
||
|
|
- if (feof(stream)) {
|
||
|
|
- *result = NULL;
|
||
|
|
- return ENOENT;
|
||
|
|
- }
|
||
|
|
buff_end = buffer + buflen - 1;
|
||
|
|
+ while (1) {
|
||
|
|
+ *buff_end = '\xff';
|
||
|
|
+ walker = fgets(buffer, buflen, stream);
|
||
|
|
+ // if get NULL string
|
||
|
|
+ if (walker == NULL) {
|
||
|
|
+ *result = NULL;
|
||
|
|
+ // reach end of file, return error
|
||
|
|
+ if (feof(stream)) {
|
||
|
|
+ return ENOENT;
|
||
|
|
+ }
|
||
|
|
+ // overflow buffer
|
||
|
|
+ return ERANGE;
|
||
|
|
+ }
|
||
|
|
+ // just overflow last char in buffer
|
||
|
|
+ if (*buff_end != '\xff') {
|
||
|
|
+ *result = NULL;
|
||
|
|
+ return ERANGE;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
- while ((*buff_end = '\xff') && fgets(buffer, buflen, stream) != NULL) {
|
||
|
|
(void)util_trim_space(buffer);
|
||
|
|
- if (buffer[0] == '\0' || buffer[0] == '#' || strlen(buffer) < 1) {
|
||
|
|
+ // skip comment line and empty line
|
||
|
|
+ if (walker[0] == '#' || walker[0] == '\0') {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (parse_line_pw(delim, buffer, resbuf) == 0) {
|
||
|
|
+ if (parse_line_pw(delim, walker, resbuf) == 0) {
|
||
|
|
got = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- if (*buff_end != '\xff') {
|
||
|
|
- *result = NULL;
|
||
|
|
- return ERANGE;
|
||
|
|
- }
|
||
|
|
}
|
||
|
|
if (!got) {
|
||
|
|
*result = NULL;
|
||
|
|
@@ -286,6 +263,7 @@ int util_getgrent_r(FILE *stream, struct group *resbuf, char *buffer, size_t buf
|
||
|
|
{
|
||
|
|
const char delim = ':';
|
||
|
|
char *buff_end = NULL;
|
||
|
|
+ char *walker = NULL;
|
||
|
|
bool got = false;
|
||
|
|
|
||
|
|
if (stream == NULL || resbuf == NULL || buffer == NULL || result == NULL) {
|
||
|
|
@@ -305,27 +283,36 @@ int util_getgrent_r(FILE *stream, struct group *resbuf, char *buffer, size_t buf
|
||
|
|
|
||
|
|
__fsetlocking(stream, FSETLOCKING_BYCALLER);
|
||
|
|
|
||
|
|
- if (feof(stream)) {
|
||
|
|
- *result = NULL;
|
||
|
|
- return ENOENT;
|
||
|
|
- }
|
||
|
|
buff_end = buffer + buflen - 1;
|
||
|
|
+ while (1) {
|
||
|
|
+ *buff_end = '\xff';
|
||
|
|
+ walker = fgets(buffer, buflen, stream);
|
||
|
|
+ // if get NULL string
|
||
|
|
+ if (walker == NULL) {
|
||
|
|
+ *result = NULL;
|
||
|
|
+ // reach end of file, return error
|
||
|
|
+ if (feof(stream)) {
|
||
|
|
+ return ENOENT;
|
||
|
|
+ }
|
||
|
|
+ // overflow buffer
|
||
|
|
+ return ERANGE;
|
||
|
|
+ }
|
||
|
|
+ // just overflow last char in buffer
|
||
|
|
+ if (*buff_end != '\xff') {
|
||
|
|
+ *result = NULL;
|
||
|
|
+ return ERANGE;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
- while ((*buff_end = '\xff') && fgets(buffer, buflen, stream) != NULL) {
|
||
|
|
- (void)util_trim_space(buffer);
|
||
|
|
- if (buffer[0] == '\0' || buffer[0] == '#' || strlen(buffer) < 1) {
|
||
|
|
+ (void)util_trim_space(walker);
|
||
|
|
+ // skip comment line and empty line
|
||
|
|
+ if (walker[0] == '#' || walker[0] == '\0') {
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (parse_line_gr(delim, buffer, buflen, resbuf) == 0) {
|
||
|
|
+ if (parse_line_gr(delim, walker, buff_end, resbuf) == 0) {
|
||
|
|
got = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- if (*buff_end != '\xff') {
|
||
|
|
- *result = NULL;
|
||
|
|
- return ERANGE;
|
||
|
|
- }
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!got) {
|
||
|
|
diff --git a/test/cutils/utils_pwgr/passwd_sample b/test/cutils/utils_pwgr/passwd_sample
|
||
|
|
index 995dea3a..cdb1890d 100644
|
||
|
|
--- a/test/cutils/utils_pwgr/passwd_sample
|
||
|
|
+++ b/test/cutils/utils_pwgr/passwd_sample
|
||
|
|
@@ -1,13 +1,13 @@
|
||
|
|
root:x:b:0:
|
||
|
|
root:x:0:0:root:/root:/bin/bash
|
||
|
|
-bin:x:1:1:bin:/bin:/sbin/nologin
|
||
|
|
-bin:x:-1:1:bin:/bin:/sbin/nologin
|
||
|
|
+abin:x:1:1:bin:/bin:/sbin/nologin
|
||
|
|
+bbin:x:-1:1:bin:/bin:/sbin/nologin
|
||
|
|
uidonly:x:1::bin:/bin:/sbin/nologin
|
||
|
|
::::1:1:bin:/bin:/sbin/nologin
|
||
|
|
root:x:
|
||
|
|
|
||
|
|
#npt:*:66:77::/etc/ntp:/sbin/nologin
|
||
|
|
-npt:*:66:77::/etc/ntp:/sbin/nologin
|
||
|
|
-npt:*:66:77::/etc/ntp:/sbin/nologin:some:extra:context:added
|
||
|
|
+anpt:*:66:77::/etc/ntp:/sbin/nologin
|
||
|
|
+bnpt:*:66:77::/etc/ntp:/sbin/nologin:some:extra:context:added
|
||
|
|
+npt:*::::/etc/ntp:/sbin/nologin
|
||
|
|
-npt:*::::/etc/ntp:/sbin/nologin
|
||
|
|
\ No newline at end of file
|
||
|
|
diff --git a/test/cutils/utils_pwgr/utils_pwgr_ut.cc b/test/cutils/utils_pwgr/utils_pwgr_ut.cc
|
||
|
|
index d856270d..1f3dab9e 100644
|
||
|
|
--- a/test/cutils/utils_pwgr/utils_pwgr_ut.cc
|
||
|
|
+++ b/test/cutils/utils_pwgr/utils_pwgr_ut.cc
|
||
|
|
@@ -32,10 +32,10 @@ TEST(utils_pwgr, test_getpwent_r)
|
||
|
|
|
||
|
|
std::vector<std::tuple<std::string, std::string, int, int, std::string, std::string, std::string>> testcase = {
|
||
|
|
std::make_tuple("root", "x", 0, 0, "root", "/root", "/bin/bash"),
|
||
|
|
- std::make_tuple("bin", "x", 1, 1, "bin", "/bin", "/sbin/nologin"),
|
||
|
|
- std::make_tuple("uidonly", "x", 1, 0, "bin", "/bin", "/sbin/nologin"),
|
||
|
|
- std::make_tuple("npt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"),
|
||
|
|
- std::make_tuple("npt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"),
|
||
|
|
+ std::make_tuple("abin", "x", 1, 1, "bin", "/bin", "/sbin/nologin"),
|
||
|
|
+ std::make_tuple("bbin", "x", 4294967295, 1, "bin", "/bin", "/sbin/nologin"),
|
||
|
|
+ std::make_tuple("anpt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"),
|
||
|
|
+ std::make_tuple("bnpt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin:some:extra:context:added"),
|
||
|
|
std::make_tuple("+npt", "*", 0, 0, "", "/etc/ntp", "/sbin/nologin"),
|
||
|
|
std::make_tuple("-npt", "*", 0, 0, "", "/etc/ntp", "/sbin/nologin")
|
||
|
|
};
|
||
|
|
--
|
||
|
|
2.20.1
|
||
|
|
|