Add snprintf for sysfs buffer writing

This commit is contained in:
Mark
2020-01-27 12:59:02 +02:00
parent c28da05558
commit bfe2999b8a
7 changed files with 314 additions and 1063 deletions
+2 -1
View File
@@ -62,7 +62,8 @@ OBJS+=$(O)/sys/debug.o \
$(O)/sys/vfs/sysfs.o \
$(O)/sys/vfs/ext2/ext2.o \
$(O)/sys/vfs/ext2/block.o \
$(O)/sys/vfs/ext2/node.o
$(O)/sys/vfs/ext2/node.o \
$(O)/sys/snprintf.o
USB_ENABLE?=1
ifeq ($(USB_ENABLE),1)
+21
View File
@@ -1,6 +1,27 @@
#pragma once
#include "sys/types.h"
#define sysfs_buf_puts(buf, lim, s) \
{ \
if (lim > 0) { \
size_t l = MIN(strlen(s), (lim) - 1); \
strncpy(buf, s, l); \
buf += l; \
*buf = 0; \
lim -= l; \
} \
}
#define sysfs_buf_printf(buf, lim, fmt, ...) \
{ \
int res = snprintf(buf, lim, fmt, ##__VA_ARGS__); \
if (res >= (int) lim) { \
lim = 0; \
} else { \
buf += res; \
lim -= res; \
} \
}
typedef int (*cfg_read_func_t)(void *ctx, char *buf, size_t lim);
typedef int (*cfg_write_func_t)(void *ctx, const char *value);
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include <stdarg.h>
#include "sys/types.h"
int snprintf(char *buf, size_t lim, const char *fmt, ...);
int vsnprintf(char *buf, size_t lim, const char *fmt, va_list args);
File diff suppressed because it is too large Load Diff
+9 -29
View File
@@ -3,6 +3,7 @@
#include "sys/amd64/mm/pool.h"
#include "sys/amd64/cpu.h"
#include "sys/fs/sysfs.h"
#include "sys/snprintf.h"
#include "sys/signum.h"
#include "sys/string.h"
#include "sys/assert.h"
@@ -172,48 +173,27 @@ void sched_add(struct thread *t) {
}
static int sched_cpu_queue_getter(void *ctx, char *buf, size_t lim) {
// TODO: FUCKING SNPRINTF
for (size_t i = 0; i < sched_ncpus; ++i) {
*buf++ = 'c';
*buf++ = 'p';
*buf++ = 'u';
*buf++ = '0' + i;
*buf++ = ':';
*buf++ = ' ';
sysfs_buf_printf(buf, lim, "cpu%u: ", i);
for (struct thread *thr = sched_queue_heads[i]; thr; thr = thr->next) {
if (thr->flags & THREAD_KERNEL) {
*buf++ = '[';
sysfs_buf_puts(buf, lim, "[");
}
if (thr->name[0]) {
strcat(buf, thr->name);
buf += strlen(buf);
sysfs_buf_puts(buf, lim, thr->name);
} else {
*buf++ = '-';
sysfs_buf_puts(buf, lim, "---");
}
if (thr->flags & THREAD_KERNEL) {
*buf++ = ']';
sysfs_buf_puts(buf, lim, "]");
}
*buf++ = ' ';
*buf++ = '(';
debug_ds(thr->pid, buf, 1, 1);
buf += strlen(buf);
*buf++ = ')';
sysfs_buf_printf(buf, lim, " (%d)", (int) thr->pid);
if (thr->next) {
*buf++ = ',';
*buf++ = ' ';
sysfs_buf_puts(buf, lim, ", ");
}
}
*buf++ = '\n';
sysfs_buf_puts(buf, lim, "\n");
}
*buf = 0;
return 0;
}
+261
View File
@@ -0,0 +1,261 @@
// TODO: merge snprintf and debug.c
#include "sys/snprintf.h"
#include "sys/string.h"
union printfv {
int value_int;
unsigned int value_uint;
long value_long;
uint32_t value_uint32;
uint64_t value_uint64;
uintptr_t value_ptr;
const char *value_str;
};
static const char *s_print_xs_set0 = "0123456789abcdef";
static const char *s_print_xs_set1 = "0123456789ABCDEF";
static int vsnprintf_ds(int64_t x, char *res, int s, int sz) {
if (!x) {
res[0] = '0';
res[1] = 0;
return 1;
}
int c;
uint64_t v;
if (sz) {
if (s && x < 0) {
v = (uint64_t) -x;
} else {
s = 0;
v = (uint64_t) x;
}
} else {
if (s && ((int32_t) x) < 0) {
v = (uint64_t) -((int32_t) x);
} else {
s = 0;
v = (uint64_t) x;
}
}
c = 0;
while (v) {
res[c++] = '0' + v % 10;
v /= 10;
}
if (s) {
res[c++] = '-';
}
res[c] = 0;
for (int i = 0, j = c - 1; i < j; ++i, --j) {
res[i] ^= res[j];
res[j] ^= res[i];
res[i] ^= res[j];
}
return c;
}
static int vsnprintf_xs(uint64_t v, char *res, const char *set) {
if (!v) {
res[0] = '0';
res[1] = 0;
return 1;
}
int c = 0;
while (v) {
res[c++] = set[v & 0xF];
v >>= 4;
}
res[c] = 0;
for (int i = 0, j = c - 1; i < j; ++i, --j) {
res[i] ^= res[j];
res[j] ^= res[i];
res[i] ^= res[j];
}
return c;
}
int snprintf(char *buf, size_t len, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int res = vsnprintf(buf, len, fmt, args);
va_end(args);
return res;
}
int vsnprintf(char *buf, size_t len, const char *fmt, va_list args) {
union printfv val;
char cbuf[64];
size_t p = 0;
// padn > 0:
// --------vvvvv
// padn < 0:
// vvvv----------
int padn;
char padc;
int pads;
int clen;
char c;
#define __putc(ch) \
if (p == len - 1) { \
goto __end; \
} else { \
buf[p++] = ch; \
}
#define __puts(s, l) \
if (padn >= 0) { \
if ((int) l < padn) { \
size_t padd = padn - l; \
if (p + padd < len + 1) { \
memset(buf + p, padc, padd); \
p += padd; \
} else { \
memset(buf + p, padc, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
} \
if (p + l < len + 1) { \
strncpy(buf + p, s, l); \
p += l; \
} else { \
strncpy(buf + p, s, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
} else { \
padn = -padn; \
if (p + l < len + 1) { \
strncpy(buf + p, s, l); \
p += l; \
} else { \
strncpy(buf + p, s, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
if ((int) l < padn) { \
size_t padd = padn - l; \
if (p + padd < len + 1) { \
memset(buf + p, padc, padd); \
p += padd; \
} else { \
memset(buf + p, padc, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
} \
}
while ((c = *fmt)) {
switch (c) {
case '%':
c = *++fmt;
padn = 0;
padc = ' ';
pads = 1;
if (c == '0') {
padc = c;
c = *++fmt;
}
if (c == '-') {
pads = -1;
c = *++fmt;
}
while (c >= '0' && c <= '9') {
padn *= 10;
padn += c - '0';
c = *++fmt;
}
padn *= pads;
switch (c) {
case 'l':
// Not supported
return -1;
case 's':
if ((val.value_str = va_arg(args, const char *))) {
__puts(val.value_str, strlen(val.value_str));
} else {
__puts("(null)", 6);
}
break;
case 'p':
val.value_ptr = va_arg(args, uintptr_t);
__putc('0');
__putc('x');
padn = sizeof(uintptr_t) * 2;
padc = '0';
clen = vsnprintf_xs(val.value_ptr, cbuf, s_print_xs_set0);
__puts(cbuf, clen);
break;
case 'i':
case 'd':
val.value_int = va_arg(args, int);
clen = vsnprintf_ds(val.value_int, cbuf, 1, 1);
__puts(cbuf, clen);
break;
case 'u':
val.value_uint = va_arg(args, unsigned int);
clen = vsnprintf_ds(val.value_uint, cbuf, 0, 1);
__puts(cbuf, clen);
break;
case 'x':
val.value_uint32 = va_arg(args, uint32_t);
clen = vsnprintf_xs(val.value_uint32, cbuf, s_print_xs_set0);
__puts(cbuf, clen);
break;
case 'X':
val.value_uint32 = va_arg(args, uint32_t);
clen = vsnprintf_xs(val.value_uint32, cbuf, s_print_xs_set1);
__puts(cbuf, clen);
break;
case 'c':
val.value_int = va_arg(args, int);
__putc(val.value_int);
break;
default:
__putc('%');
__putc(c);
break;
}
break;
default:
__putc(c);
break;
}
++fmt;
}
#undef __puts
#undef __putc
__end:
buf[p] = 0;
return p;
}
+15 -19
View File
@@ -1,6 +1,7 @@
#include "sys/amd64/cpu.h"
#include "sys/fs/sysfs.h"
#include "sys/fs/ofile.h"
#include "sys/snprintf.h"
#include "sys/fs/node.h"
#include "sys/assert.h"
#include "sys/string.h"
@@ -118,14 +119,14 @@ static ssize_t sysfs_vnode_read(struct ofile *fd, void *buf, size_t count) {
int sysfs_config_getter(void *ctx, char *buf, size_t lim) {
kdebug("Read config value: buffer size %u, actual value length %u\n", lim, strlen(ctx));
strncpy(buf, ctx, lim);
buf[lim - 1] = 0;
sysfs_buf_puts(buf, lim, ctx);
sysfs_buf_puts(buf, lim, "\n");
return 0;
}
int sysfs_config_int64_getter(void *ctx, char *buf, size_t lim) {
debug_ds(*(int64_t *) ctx, buf, 1, 1);
// TODO: long format for snprintf
sysfs_buf_printf(buf, lim, "%d\n", *(int *) ctx);
return 0;
}
@@ -161,10 +162,11 @@ static int proc_property_getter(void *ctx, char *buf, size_t lim) {
switch (prop) {
case PROC_PROP_PID:
debug_ds(thr->pid, buf, 0, 0);
sysfs_buf_printf(buf, lim, "%d\n", (int) thr->pid);
break;
case PROC_PROP_NAME:
strcpy(buf, thr->name);
sysfs_buf_puts(buf, lim, thr->name);
sysfs_buf_puts(buf, lim, "\n");
break;
}
@@ -172,8 +174,6 @@ static int proc_property_getter(void *ctx, char *buf, size_t lim) {
}
static int system_uptime_getter(void *ctx, char *buf, size_t lim) {
// TODO: snprintf to print days
// (Don't think the OS will run more than a day, but still)
char *p = buf;
uint64_t t = system_time / 1000000000ULL;
int days = (t / 86400),
@@ -181,23 +181,19 @@ static int system_uptime_getter(void *ctx, char *buf, size_t lim) {
minutes = (t / 60) % 60,
seconds = t % 60;
*p++ = ('0' + (hours / 10));
*p++ = ('0' + (hours % 10));
*p++ = ':';
*p++ = ('0' + (minutes / 10));
*p++ = ('0' + (minutes % 10));
*p++ = ':';
*p++ = ('0' + (seconds / 10));
*p++ = ('0' + (seconds % 10));
*p = 0;
sysfs_buf_printf(buf, lim, "%u day", days);
if (days != 1) {
sysfs_buf_puts(buf, lim, "s");
}
sysfs_buf_printf(buf, lim, ", %02u:%02u:%02u\n", hours, minutes, seconds);
return 0;
}
void sysfs_populate(void) {
sysfs_add_config_endpoint("version", sizeof(KERNEL_VERSION_STR), KERNEL_VERSION_STR, sysfs_config_getter, NULL);
sysfs_add_config_endpoint("version", sizeof(KERNEL_VERSION_STR) + 1, KERNEL_VERSION_STR, sysfs_config_getter, NULL);
sysfs_add_config_endpoint("uptime", 16, NULL, system_uptime_getter, NULL);
sysfs_add_config_endpoint("uptime", 32, NULL, system_uptime_getter, NULL);
sysfs_add_config_endpoint("self.pid", 16, (void *) PROC_PROP_PID, proc_property_getter, NULL);
sysfs_add_config_endpoint("self.name", 128, (void *) PROC_PROP_NAME, proc_property_getter, NULL);