Extract string writing/buffer handling into some callback

This commit is contained in:
Benny Baumann 2021-10-20 20:19:00 +02:00 committed by BenBE
parent 9dc964bb42
commit 550100327b
3 changed files with 119 additions and 129 deletions

View File

@ -10,7 +10,45 @@ in the source distribution for its full text.
#include "XUtils.h" #include "XUtils.h"
static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t bufsize) { typedef struct StrBuf_state {
char *buf;
size_t size;
size_t pos;
} StrBuf_state;
typedef bool (*StrBuf_putc_t)(StrBuf_state* p, char c);
static bool StrBuf_putc_count(StrBuf_state* p, ATTR_UNUSED char c) {
p->pos++;
return true;
}
static bool StrBuf_putc_write(StrBuf_state* p, char c) {
if (p->pos >= p->size)
return false;
p->buf[p->pos] = c;
p->pos++;
return true;
}
static bool StrBuf_putsn(StrBuf_state* p, StrBuf_putc_t w, const char* s, size_t count) {
while (count--)
if (!w(p, *s++))
return false;
return true;
}
static bool StrBuf_putsz(StrBuf_state* p, StrBuf_putc_t w, const char* s) {
while (*s)
if (!w(p, *s++))
return false;
return true;
}
static bool CGroup_filterName_internal(const char *cgroup, StrBuf_state* s, StrBuf_putc_t w) {
const char* str_slice_suffix = ".slice"; const char* str_slice_suffix = ".slice";
const char* str_system_slice = "system.slice"; const char* str_system_slice = "system.slice";
const char* str_user_slice = "user.slice"; const char* str_user_slice = "user.slice";
@ -22,21 +60,19 @@ static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t buf
const char* str_nspawn_scope_prefix = "machine-"; const char* str_nspawn_scope_prefix = "machine-";
const char* str_nspawn_monitor_label = "/supervisor"; const char* str_nspawn_monitor_label = "/supervisor";
const char* str_nspawn_payload_label = "/payload";
const char* str_service_suffix = ".service"; const char* str_service_suffix = ".service";
const char* str_scope_suffix = ".scope"; const char* str_scope_suffix = ".scope";
while(*cgroup) { while (*cgroup) {
if ('/' == *cgroup) { if ('/' == *cgroup) {
while ('/' == *cgroup) while ('/' == *cgroup)
cgroup++; cgroup++;
if (!bufsize) if (!w(s, '/'))
return false; return false;
*buf++ = '/';
bufsize--;
continue; continue;
} }
@ -44,54 +80,30 @@ static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t buf
const char* nextSlash = strchrnul(labelStart, '/'); const char* nextSlash = strchrnul(labelStart, '/');
const size_t labelLen = nextSlash - labelStart; const size_t labelLen = nextSlash - labelStart;
if (String_startsWith(cgroup, str_system_slice)) { if (labelLen == strlen(str_system_slice) && String_startsWith(cgroup, str_system_slice)) {
cgroup += strlen(str_system_slice); cgroup = nextSlash;
if (*cgroup && *cgroup != '/') if (!StrBuf_putsz(s, w, "[S]"))
goto handle_default;
if (bufsize < 3)
return false; return false;
*buf++ = '[';
*buf++ = 'S';
*buf++ = ']';
bufsize -= 3;
continue; continue;
} }
if (String_startsWith(cgroup, str_machine_slice)) { if (labelLen == strlen(str_machine_slice) && String_startsWith(cgroup, str_machine_slice)) {
cgroup += strlen(str_machine_slice); cgroup = nextSlash;
if (*cgroup && *cgroup != '/') if (!StrBuf_putsz(s, w, "[M]"))
goto handle_default;
if (bufsize < 3)
return false; return false;
*buf++ = '[';
*buf++ = 'M';
*buf++ = ']';
bufsize -= 3;
continue; continue;
} }
if (String_startsWith(cgroup, str_user_slice)) { if (labelLen == strlen(str_user_slice) && String_startsWith(cgroup, str_user_slice)) {
cgroup += strlen(str_user_slice); cgroup = nextSlash;
if (*cgroup && *cgroup != '/') if (!StrBuf_putsz(s, w, "[U]"))
goto handle_default;
if (bufsize < 3)
return false; return false;
*buf++ = '[';
*buf++ = 'U';
*buf++ = ']';
bufsize -= 3;
if (!String_startsWith(cgroup, str_user_slice_prefix)) if (!String_startsWith(cgroup, str_user_slice_prefix))
continue; continue;
@ -103,39 +115,32 @@ static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t buf
const size_t sliceNameLen = sliceSpec - (cgroup + strlen(str_user_slice_prefix)); const size_t sliceNameLen = sliceSpec - (cgroup + strlen(str_user_slice_prefix));
if (bufsize < sliceNameLen + 1) s->pos--;
if (!w(s, ':'))
return false; return false;
buf[-1] = ':'; if (!StrBuf_putsn(s, w, cgroup + strlen(str_user_slice_prefix), sliceNameLen))
return false;
if (!w(s, ']'))
return false;
cgroup += strlen(str_user_slice_prefix);
while(cgroup < sliceSpec) {
*buf++ = *cgroup++;
bufsize--;
}
cgroup = userSliceSlash; cgroup = userSliceSlash;
*buf++ = ']';
bufsize--;
continue; continue;
} }
if (labelLen > strlen(str_slice_suffix) && String_startsWith(nextSlash - strlen(str_slice_suffix), str_slice_suffix)) { if (labelLen > strlen(str_slice_suffix) && String_startsWith(nextSlash - strlen(str_slice_suffix), str_slice_suffix)) {
const size_t sliceNameLen = labelLen - strlen(str_slice_suffix); const size_t sliceNameLen = labelLen - strlen(str_slice_suffix);
if (bufsize < 2 + sliceNameLen)
if (!w(s, '['))
return false; return false;
*buf++ = '['; if (!StrBuf_putsn(s, w, cgroup, sliceNameLen))
bufsize--; return false;
for(size_t i = sliceNameLen; i; i--) { if (!w(s, ']'))
*buf++ = *cgroup++; return false;
bufsize--;
}
*buf++ = ']';
bufsize--;
cgroup = nextSlash; cgroup = nextSlash;
@ -144,48 +149,34 @@ static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t buf
if (String_startsWith(cgroup, str_lxc_payload_prefix)) { if (String_startsWith(cgroup, str_lxc_payload_prefix)) {
const size_t cgroupNameLen = labelLen - strlen(str_lxc_payload_prefix); const size_t cgroupNameLen = labelLen - strlen(str_lxc_payload_prefix);
if (bufsize < 6 + cgroupNameLen)
if (!StrBuf_putsz(s, w, "[lxc:"))
return false; return false;
*buf++ = '['; if (!StrBuf_putsn(s, w, cgroup + strlen(str_lxc_payload_prefix), cgroupNameLen))
*buf++ = 'l'; return false;
*buf++ = 'x';
*buf++ = 'c';
*buf++ = ':';
bufsize -= 5;
cgroup += strlen(str_lxc_payload_prefix); if (!w(s, ']'))
while(cgroup < nextSlash) { return false;
*buf++ = *cgroup++;
bufsize--;
}
*buf++ = ']'; cgroup = nextSlash;
bufsize--;
continue; continue;
} }
if (String_startsWith(cgroup, str_lxc_monitor_prefix)) { if (String_startsWith(cgroup, str_lxc_monitor_prefix)) {
const size_t cgroupNameLen = labelLen - strlen(str_lxc_monitor_prefix); const size_t cgroupNameLen = labelLen - strlen(str_lxc_monitor_prefix);
if (bufsize < 6 + cgroupNameLen)
if (!StrBuf_putsz(s, w, "[LXC:"))
return false; return false;
*buf++ = '['; if (!StrBuf_putsn(s, w, cgroup + strlen(str_lxc_monitor_prefix), cgroupNameLen))
*buf++ = 'L'; return false;
*buf++ = 'X';
*buf++ = 'C';
*buf++ = ':';
bufsize -= 5;
cgroup += strlen(str_lxc_monitor_prefix); if (!w(s, ']'))
while(cgroup < nextSlash) { return false;
*buf++ = *cgroup++;
bufsize--;
}
*buf++ = ']'; cgroup = nextSlash;
bufsize--;
continue; continue;
} }
@ -202,14 +193,9 @@ static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t buf
continue; continue;
} }
if (bufsize < serviceNameLen) if (!StrBuf_putsn(s, w, cgroup, serviceNameLen))
return false; return false;
for(size_t i = serviceNameLen; i; i--) {
*buf++ = *cgroup++;
bufsize--;
}
cgroup = nextSlash; cgroup = nextSlash;
continue; continue;
@ -220,66 +206,70 @@ static bool CGroup_filterName_internal(const char *cgroup, char* buf, size_t buf
if (String_startsWith(cgroup, str_nspawn_scope_prefix)) { if (String_startsWith(cgroup, str_nspawn_scope_prefix)) {
const size_t machineScopeNameLen = scopeNameLen - strlen(str_nspawn_scope_prefix); const size_t machineScopeNameLen = scopeNameLen - strlen(str_nspawn_scope_prefix);
if (bufsize < 6 + machineScopeNameLen)
return false;
const bool is_monitor = String_startsWith(nextSlash, str_nspawn_monitor_label); const bool is_monitor = String_startsWith(nextSlash, str_nspawn_monitor_label);
*buf++ = '['; if (!StrBuf_putsz(s, w, is_monitor ? "[SNC:" : "[snc:"))
*buf++ = is_monitor ? 'S' : 's'; return false;
*buf++ = is_monitor ? 'N' : 'n';
*buf++ = is_monitor ? 'C' : 'c';
*buf++ = ':';
bufsize -= 5;
cgroup += strlen(str_nspawn_scope_prefix); if (!StrBuf_putsn(s, w, cgroup + strlen(str_nspawn_scope_prefix), machineScopeNameLen))
for(size_t i = machineScopeNameLen; i; i--) { return false;
*buf++ = *cgroup++;
bufsize--;
}
*buf++ = ']'; if (!w(s, ']'))
bufsize--; return false;
cgroup = nextSlash; cgroup = nextSlash;
if (String_startsWith(nextSlash, str_nspawn_monitor_label))
cgroup += strlen(str_nspawn_monitor_label);
else if (String_startsWith(nextSlash, str_nspawn_payload_label))
cgroup += strlen(str_nspawn_payload_label);
continue; continue;
} }
if (bufsize < 1 + scopeNameLen) if (!w(s, '!'))
return false; return false;
*buf++ = '!'; if (!StrBuf_putsn(s, w, cgroup, scopeNameLen))
bufsize--; return false;
for(size_t i = scopeNameLen; i; i--) {
*buf++ = *cgroup++;
bufsize--;
}
cgroup = nextSlash; cgroup = nextSlash;
continue; continue;
} }
handle_default:
// Default behavior: Copy the full label // Default behavior: Copy the full label
cgroup = labelStart; cgroup = labelStart;
if (bufsize < (size_t)(nextSlash - cgroup)) if (!StrBuf_putsn(s, w, cgroup, labelLen))
return false; return false;
while(cgroup < nextSlash) { cgroup = nextSlash;
*buf++ = *cgroup++;
bufsize--;
}
} }
return true; return true;
} }
bool CGroup_filterName(const char *cgroup, char* buf, size_t bufsize) { char* CGroup_filterName(const char *cgroup) {
memset(buf, 0, bufsize); StrBuf_state s = {
.buf = NULL,
.size = 0,
.pos = 0,
};
return CGroup_filterName_internal(cgroup, buf, bufsize - 1); if (!CGroup_filterName_internal(cgroup, &s, StrBuf_putc_count)) {
return NULL;
}
s.buf = xCalloc(s.pos + 1, sizeof(char));
s.size = s.pos;
s.pos = 0;
if (!CGroup_filterName_internal(cgroup, &s, StrBuf_putc_write)) {
free(s.buf);
return NULL;
}
s.buf[s.size] = '\0';
return s.buf;
} }

View File

@ -11,6 +11,6 @@ in the source distribution for its full text.
#include <stddef.h> #include <stddef.h>
bool CGroup_filterName(const char *cgroup, char* buf, size_t bufsize); char* CGroup_filterName(const char *cgroup);
#endif /* HEADER_CGroupUtils */ #endif /* HEADER_CGroupUtils */

View File

@ -905,14 +905,14 @@ static void LinuxProcessList_readCGroupFile(LinuxProcess* process, openat_arg_t
if (!changed) if (!changed)
return; return;
char* cgroup_short = xCalloc(strlen(process->cgroup) + 1, 1); char* cgroup_short = CGroup_filterName(process->cgroup);
if (CGroup_filterName(process->cgroup, cgroup_short, strlen(process->cgroup) + 1)) { if (cgroup_short) {
free_and_xStrdup(&process->cgroup_short, cgroup_short); free_and_xStrdup(&process->cgroup_short, cgroup_short);
free(cgroup_short);
} else { } else {
free(process->cgroup_short); free(process->cgroup_short);
process->cgroup_short = NULL; process->cgroup_short = NULL;
} }
free(cgroup_short);
} }
#ifdef HAVE_VSERVER #ifdef HAVE_VSERVER