Add snprintf for sysfs buffer writing
This commit is contained in:
+2
-1
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user