library: correct 'vectorized' string logic, <PIDS> api

The commit referenced below addressed (some) anomalies
surrounding 'strv' pointers. However, there remained a
couple quirks involving a potential NULL return value.

Any NULL values returned from the old library readproc
guys would cause no real harm for newlib. But they did
produce the misleading "[ duplicate ENUM_ID ]" result.

The following all represent potential NULL results and
suggest shortcomings in testing of that earlier patch.

. kernel threads do not have cgroup, cmdline & environ
. even if present environ could require root to access

So, this patch reverts a portion of the earlier commit
and ensures when some vectored string is not available
a traditional dash ('-') is the 'strv' returned value.

[ and we'll also correct one typo in the header file ]

Reference(s):
. eliminated a final potential NULL, <PIDS> api
commit 09503dc597

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2019-04-25 00:00:00 -05:00 committed by Craig Small
parent 30e27d48e9
commit a9bfb186eb
4 changed files with 43 additions and 27 deletions

View File

@ -94,25 +94,6 @@ struct pids_info {
// ___ Results 'Set' Support |||||||||||||||||||||||||||||||||||||||||||||||||| // ___ Results 'Set' Support ||||||||||||||||||||||||||||||||||||||||||||||||||
static char** pids_vectorize_this (const char* src) {
#define pSZ (sizeof(char*))
char *cpy, **vec;
size_t adj, tot;
tot = strlen(src) + 1; // prep for our vectors
if (tot < 1 || tot >= INT_MAX) tot = INT_MAX-1; // integer overflow?
adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1)); // calc alignment bytes
cpy = calloc(1, tot + adj + (2 * pSZ)); // get new larger buffer
if (!cpy) return NULL; // oops, looks like ENOMEM
snprintf(cpy, tot, "%s", src); // duplicate their string
vec = (char**)(cpy + tot + adj); // prep pointer to pointers
*vec = cpy; // point 1st vector to string
*(vec+1) = NULL; // null ptr 'list' delimit
return vec; // ==> free(*vec) to dealloc
#undef pSZ
} // end: pids_vectorize_this
#define setNAME(e) set_pids_ ## e #define setNAME(e) set_pids_ ## e
#define setDECL(e) static void setNAME(e) \ #define setDECL(e) static void setNAME(e) \
(struct pids_info *I, struct pids_result *R, proc_t *P) (struct pids_info *I, struct pids_result *R, proc_t *P)
@ -136,7 +117,7 @@ static char** pids_vectorize_this (const char* src) {
some sort of hint that they duplicated this char ** item ... */ some sort of hint that they duplicated this char ** item ... */
#define VEC_set(e,x) setDECL(e) { \ #define VEC_set(e,x) setDECL(e) { \
if (NULL != P-> x) { R->result.strv = P-> x; P-> x = NULL; } \ if (NULL != P-> x) { R->result.strv = P-> x; P-> x = NULL; } \
else { R->result.strv = pids_vectorize_this("[ duplicate " STRINGIFY(e) " ]"); \ else { R->result.strv = vectorize_this_str("[ duplicate " STRINGIFY(e) " ]"); \
if (!R->result.str) I->seterr = 1; } } if (!R->result.str) I->seterr = 1; } }

View File

@ -132,7 +132,7 @@ enum pids_item {
PIDS_TICS_USER, // ull_int stat: utime PIDS_TICS_USER, // ull_int stat: utime
PIDS_TICS_USER_C, // ull_int stat: utime + cutime PIDS_TICS_USER_C, // ull_int stat: utime + cutime
PIDS_TIME_ALL, // ull_int [ derived from (utime + stime) / hertz ] PIDS_TIME_ALL, // ull_int [ derived from (utime + stime) / hertz ]
PIDS_TIME_ELAPSED, // ull_int [ derived from /proc/uptime - (starttime / hertz) } PIDS_TIME_ELAPSED, // ull_int [ derived from /proc/uptime - (starttime / hertz) ]
PIDS_TIME_START, // ull_int stat: starttime PIDS_TIME_START, // ull_int stat: starttime
PIDS_TTY, // s_int stat: tty_nr PIDS_TTY, // s_int stat: tty_nr
PIDS_TTY_NAME, // str [ derived from TTY ] PIDS_TTY_NAME, // str [ derived from TTY ]

View File

@ -835,6 +835,34 @@ static int read_unvectored(char *restrict const dst, unsigned sz, const char* wh
} }
char** vectorize_this_str (const char* src) {
#define pSZ (sizeof(char*))
char *cpy, **vec;
size_t adj, tot;
tot = strlen(src) + 1; // prep for our vectors
if (tot < 1 || tot >= INT_MAX) tot = INT_MAX-1; // integer overflow?
adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1)); // calc alignment bytes
cpy = calloc(1, tot + adj + (2 * pSZ)); // get new larger buffer
if (!cpy) return NULL; // oops, looks like ENOMEM
snprintf(cpy, tot, "%s", src); // duplicate their string
vec = (char**)(cpy + tot + adj); // prep pointer to pointers
*vec = cpy; // point 1st vector to string
*(vec+1) = NULL; // null ptr 'list' delimit
return vec; // ==> free(*vec) to dealloc
#undef pSZ
}
// This littl' guy just serves those true vectorized fields
// ( when a /proc source field didn't exist )
static int vectorize_dash_rc (char*** vec) {
if (!(*vec = vectorize_this_str("-")))
return 1;
return 0;
}
// This routine reads a 'cgroup' for the designated proc_t and // This routine reads a 'cgroup' for the designated proc_t and
// guarantees the caller a valid proc_t.cgroup pointer. // guarantees the caller a valid proc_t.cgroup pointer.
static int fill_cgroup_cvt (const char* directory, proc_t *restrict p) { static int fill_cgroup_cvt (const char* directory, proc_t *restrict p) {
@ -1094,17 +1122,20 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
} }
if (flags & PROC_FILLENV) // read /proc/#/environ if (flags & PROC_FILLENV) // read /proc/#/environ
p->environ_v = file2strvec(path, "environ"); if (!(p->environ_v = file2strvec(path, "environ")))
rc += vectorize_dash_rc(&p->environ_v);
if (flags & PROC_EDITENVRCVT) if (flags & PROC_EDITENVRCVT)
rc += fill_environ_cvt(path, p); rc += fill_environ_cvt(path, p);
if (flags & PROC_FILLARG) // read /proc/#/cmdline if (flags & PROC_FILLARG) // read /proc/#/cmdline
p->cmdline_v = file2strvec(path, "cmdline"); if (!(p->cmdline_v = file2strvec(path, "cmdline")))
rc += vectorize_dash_rc(&p->cmdline_v);
if (flags & PROC_EDITCMDLCVT) if (flags & PROC_EDITCMDLCVT)
rc += fill_cmdline_cvt(path, p); rc += fill_cmdline_cvt(path, p);
if ((flags & PROC_FILLCGROUP)) // read /proc/#/cgroup if ((flags & PROC_FILLCGROUP)) // read /proc/#/cgroup
p->cgroup_v = file2strvec(path, "cgroup"); if (!(p->cgroup_v = file2strvec(path, "cgroup")))
rc += vectorize_dash_rc(&p->cgroup_v);
if (flags & PROC_EDITCGRPCVT) if (flags & PROC_EDITCGRPCVT)
rc += fill_cgroup_cvt(path, p); rc += fill_cgroup_cvt(path, p);
@ -1202,17 +1233,20 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric
if (!IS_THREAD(t)) { if (!IS_THREAD(t)) {
#endif #endif
if (flags & PROC_FILLARG) // read /proc/#/task/#/cmdline if (flags & PROC_FILLARG) // read /proc/#/task/#/cmdline
t->cmdline_v = file2strvec(path, "cmdline"); if (!(t->cmdline_v = file2strvec(path, "cmdline")))
rc += vectorize_dash_rc(&t->cmdline_v);
if (flags & PROC_EDITCMDLCVT) if (flags & PROC_EDITCMDLCVT)
rc += fill_cmdline_cvt(path, t); rc += fill_cmdline_cvt(path, t);
if (flags & PROC_FILLENV) // read /proc/#/task/#/environ if (flags & PROC_FILLENV) // read /proc/#/task/#/environ
t->environ_v = file2strvec(path, "environ"); if (!(t->environ_v = file2strvec(path, "environ")))
rc += vectorize_dash_rc(&t->environ_v);
if (flags & PROC_EDITENVRCVT) if (flags & PROC_EDITENVRCVT)
rc += fill_environ_cvt(path, t); rc += fill_environ_cvt(path, t);
if ((flags & PROC_FILLCGROUP)) // read /proc/#/task/#/cgroup if ((flags & PROC_FILLCGROUP)) // read /proc/#/task/#/cgroup
t->cgroup_v = file2strvec(path, "cgroup"); if (!(t->cgroup_v = file2strvec(path, "cgroup")))
rc += vectorize_dash_rc(&t->cgroup_v);
if (flags & PROC_EDITCGRPCVT) if (flags & PROC_EDITCGRPCVT)
rc += fill_cgroup_cvt(path, t); rc += fill_cgroup_cvt(path, t);

View File

@ -260,5 +260,6 @@ proc_t* readproc(PROCTAB *__restrict const PT, proc_t *__restrict p);
proc_t* readeither(PROCTAB *__restrict const PT, proc_t *__restrict x); proc_t* readeither(PROCTAB *__restrict const PT, proc_t *__restrict x);
int look_up_our_self(proc_t *p); int look_up_our_self(proc_t *p);
void closeproc(PROCTAB* PT); void closeproc(PROCTAB* PT);
char** vectorize_this_str(const char* src);
#endif #endif