Implement tests for writing

Commands like mkdir, rm(dir), write, touch
This commit is contained in:
2026-05-16 04:25:38 +01:00
parent 61b9b22346
commit c93181e606
38 changed files with 1530 additions and 258 deletions
+1
View File
@@ -52,3 +52,4 @@ apps/asciivju
apps/justawindow
runtests
cov_t*.*
*.dirty
+38 -36
View File
@@ -23,12 +23,13 @@ FAT_MOUNT_OPTS="umask=111,dmask=000"
MKFS_EXFAT="sudo mkfs.exfat"
QCOW2_OPTS="compat=v3,compression_type=zlib,encryption=off,extended_l2=off,preallocation=off"
QEMU_IMG_CONVERT_OPTS="-m 4 -f raw -O qcow2 -o $QCOW2_OPTS"
NBD_DEV=/dev/nbd0 # FIXME
SGDISK="sgdisk --align-end --disk-guid=abcdefff-0123-4554-3210-ffeeddccbbaa"
gpt_large.qcow2 () {
local img=$FUNCNAME
qemu-img create -f qcow2 -o $QCOW2_OPTS,cluster_size=2097152 $img 2E > /dev/null
qemu-img create -f qcow2 -o $QCOW2_OPTS,cluster_size=2M $img 2E > /dev/null
sudo qemu-nbd -c $NBD_DEV $img
sleep 1
# This is weird but the sleep above prevents the following error of the
@@ -57,7 +58,7 @@ gpt_partitions_s05k.qcow2 () {
--new=0:0:+1MiB --new=0:0:+1MiB --new=0:0:+1MiB --new=0:0:+1MiB \
--new=0:0:+1MiB $img_raw > /dev/null
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -78,7 +79,7 @@ gpt_partitions_s4k.qcow2 () {
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -109,7 +110,7 @@ jfs.qcow2 () {
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -150,7 +151,7 @@ xfs_lookup_v4.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -191,7 +192,7 @@ xfs_lookup_v5.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -229,7 +230,7 @@ xfs_nrext64.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -268,7 +269,8 @@ xfs_bigtime.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -285,7 +287,7 @@ xfs_borg_bit.qcow2 () {
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -314,7 +316,7 @@ xfs_short_dir_i8.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -355,7 +357,7 @@ xfs_v4_ftype0_s05k_b2k_n8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -396,7 +398,7 @@ xfs_v4_ftype1_s05k_b2k_n8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -411,7 +413,7 @@ xfs_v4_xattr.qcow2 () {
$MKFS_XFS $XFS_MKFS_OPTS -m crc=0,finobt=0,rmapbt=0,reflink=0 \
-d sectsize=512 -n ftype=0 $p1
sudo mount $XFS_MOUNT_OPTS $p1 $TEMP_DIR -o attr2
sudo mount $XFS_MOUNT_OPTS $p1 $TEMP_DIR
sudo chown $USER $TEMP_DIR -R
#
mkdir $TEMP_DIR/sf
@@ -429,12 +431,12 @@ xfs_v4_xattr.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
xfs_v4_btrees_l2.qcow2 () {
echo "[*] This can take about ten minutes"
echo "[*] This may take about ten minutes"
local img=$FUNCNAME
local img_raw=$(basename $img .qcow2).raw
@@ -461,7 +463,7 @@ xfs_v4_btrees_l2.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -506,7 +508,7 @@ xfs_v4_files_s05k_b4k_n8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -549,7 +551,7 @@ xfs_v4_ftype0_s4k_b4k_n8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -597,7 +599,7 @@ xfs_v4_ftype0_s05k_b2k_n8k_xattr.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -631,7 +633,7 @@ xfs_v4_unicode.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -672,7 +674,7 @@ xfs_v5_ftype1_s05k_b2k_n8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -711,7 +713,7 @@ xfs_v5_files_s05k_b4k_n8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -761,7 +763,7 @@ exfat_s05k_c16k_b16k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -844,12 +846,12 @@ exfat_s05k_c8k_b8k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
xfs_samehash_s05k.raw () {
echo "[*] This can take about one hour"
echo "[*] This may take about one hour"
local img=$FUNCNAME
# local img_raw=$(basename $img .qcow2).raw
local img_raw=$img
@@ -884,7 +886,7 @@ xfs_samehash_s05k.raw () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
# qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
# qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
}
ext2_s05k.qcow2 () {
@@ -897,7 +899,7 @@ ext2_s05k.qcow2 () {
local p1="$LOOP_DEV"p1
$MKFS_EXT2 $EXT_MKFS_OPTS -N 1200000 $p1
debugfs -w -R "set_super_value hash_seed $EXT_HASH_SEED" $p1
sudo debugfs -w -R "set_super_value hash_seed $EXT_HASH_SEED" $p1
sudo mount $p1 $TEMP_DIR
sudo chown $USER $TEMP_DIR -R
#
@@ -922,12 +924,12 @@ ext2_s05k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
ext4_s05k.qcow2 () {
echo "[*] This can take about ten minutes"
echo "[*] This may take about fifteen minutes"
local img=$FUNCNAME
local img_raw=$(basename $img .qcow2).raw
@@ -937,7 +939,7 @@ ext4_s05k.qcow2 () {
local p1="$LOOP_DEV"p1
$MKFS_EXT4 $EXT_MKFS_OPTS -N 1200000 $p1
debugfs -w -R "set_super_value hash_seed $EXT_HASH_SEED" $p1
sudo debugfs -w -R "set_super_value hash_seed $EXT_HASH_SEED" $p1
sudo mount $p1 $TEMP_DIR
sudo chown $USER $TEMP_DIR -R
#
@@ -965,7 +967,7 @@ ext4_s05k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -999,7 +1001,7 @@ fat12_s05k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -1036,12 +1038,12 @@ fat16_s05k.qcow2 () {
sudo umount $TEMP_DIR
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
iso9660_s2k_dir_all.qcow2 () {
echo "[*] This can take about thirty minutes"
echo "[*] This may take about thirty minutes"
local img=$FUNCNAME
local img_raw=$(basename $img .qcow2).raw
@@ -1083,7 +1085,7 @@ iso9660_s2k_dir_all.qcow2 () {
mkisofs -J -R -T -V 'KolibriOS' -input-charset 'UTF-8' -quiet $TEMP_DIR > $img_raw
rm $TEMP_DIR/* -rf
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
@@ -1139,7 +1141,7 @@ ext2_extra_isize.qcow2 () {
sudo losetup -d $LOOP_DEV
qemu-img convert -m 2 -O qcow2 -o $QCOW2_OPTS $img_raw $img
qemu-img convert $QEMU_IMG_CONVERT_OPTS $img_raw $img
rm $img_raw
}
+8 -6
View File
@@ -16,14 +16,16 @@
#include <unistd.h>
#include <limits.h>
#include "pci.h"
#include "umka.h"
char pci_path[PATH_MAX] = ".";
char pci_path[UMKA_PATH_MAX] = ".";
__attribute__((stdcall)) uint32_t pci_read(uint32_t bus, uint32_t dev,
uint32_t fun, uint32_t offset,
size_t len) {
char path_colon[PATH_MAX*2];
char path_underscore[PATH_MAX*2];
[[gnu::stdcall]]
uint32_t pci_read(uint32_t bus, uint32_t dev,
uint32_t fun, uint32_t offset,
size_t len) {
char path_colon[UMKA_PATH_MAX*2];
char path_underscore[UMKA_PATH_MAX*2];
uint32_t value = 0;
sprintf(path_colon, "%s/%4.4x:%2.2x:%2.2x.%u/config", pci_path, 0, bus, dev,
fun);
+6 -3
View File
@@ -24,19 +24,22 @@
#define TAP_DEV "/dev/net/tun"
#define UMKA_TAP_NAME "umka%d"
static STDCALL void
[[gnu::stdcall]]
static void
vnet_unload_tap(void) {
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL void
[[gnu::stdcall]]
static void
vnet_reset_tap(void) {
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL int
[[gnu::stdcall]]
static int
vnet_transmit_tap(net_buff_t *buf) {
struct vnet *net;
__asm__ __inline__ __volatile__ (
+2 -2
View File
@@ -3,7 +3,7 @@ ifndef KOLIBRIOS
endif
FASM_EXE ?= fasm
FASM_FLAGS=-dextended_primary_loader=1 -dHOST=$(HOST) -m 2000000 -dlang=en_US
FASM_FLAGS=-dextended_primary_loader=1 -dHOST=$(HOST) -m 1000000 -dlang=en_US
HOST ?= linux
CC ?= gcc
@@ -106,7 +106,7 @@ $(HOST)/thread.o: $(HOST)/thread.c
$(CC) $(CFLAGS_32) -c $< -o $@
$(HOST)/pci.o: $(HOST)/pci.c
$(CC) $(CFLAGS_32) -std=gnu11 -c $< -o $@
$(CC) $(CFLAGS_32) -c $< -o $@
deps/lodepng/lodepng.o: deps/lodepng/lodepng.c deps/lodepng/lodepng.h
$(CC) $(CFLAGS_32) -c $< -o $@ -DLODEPNG_NO_COMPILE_DECODER \
+1 -1
View File
@@ -135,7 +135,7 @@ is_valid_test(const char *name) {
return 0;
}
for (size_t i = 1; i < 4 && name[i]; i++) {
if (name[1] < '0' || name[1] > '9') {
if (name[i] < '0' || name[i] > '9') {
return 0;
}
}
+555 -31
View File
@@ -152,6 +152,37 @@ parse_uint64(struct shell_ctx *ctx, const char *str, uint64_t *res) {
}
}
// change to int?
static uint8_t
parse_nibble(const char c) {
if ((c >= '0') && (c <= '9')) return c - '0';
if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10;
if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10;
return 0xffu;
}
static uint8_t *
parse_hex_string(struct shell_ctx *ctx, const char *s, size_t *blen) {
size_t slen = strlen(s);
if (slen & 1) {
fprintf(ctx->fout, "the length of a hex string must be even\n");
return NULL;
}
*blen = slen/2;
uint8_t *b = malloc(*blen);
for (const char *c = s; *c; c++) {
if ((*c >= '0') && (*c <= '9')) continue;
if ((*c >= 'A') && (*c <= 'F')) continue;
if ((*c >= 'a') && (*c <= 'f')) continue;
fprintf(ctx->fout, "bad hex character: %c\n", *c);
return NULL;
}
for (size_t i = 0; i < *blen; i++) {
b[i] = (parse_nibble(s[2*i]) << 4) + parse_nibble(s[2*i+1]);
}
return b;
}
static struct shell_var *
shell_var_get(struct shell_ctx *ctx, const char *name) {
for (struct shell_var *var = ctx->var; var; var = var->next) {
@@ -301,7 +332,7 @@ print_hash(struct shell_ctx *ctx, uint8_t *x, size_t len) {
fprintf(ctx->fout, "\n");
}
void *host_load_file(const char *fname) {
void *host_load_file(const char *fname, size_t *len) {
FILE *f = fopen(fname, "rb");
if (!f) {
return NULL;
@@ -312,6 +343,9 @@ void *host_load_file(const char *fname) {
void *fdata = malloc(fsize);
fread(fdata, 1, fsize, f);
fclose(f);
if (len) {
*len = fsize;
}
return fdata;
}
@@ -665,7 +699,7 @@ cmd_disk_add(struct shell_ctx *ctx, int argc, char **argv) {
"usage: disk_add <file> <name> [option]...\n"
" <file> absolute or relative path\n"
" <name> disk name, e.g. hd0 or rd\n"
" -c cache size size of disk cache in bytes\n";
" -c cache_size size of disk cache in bytes\n";
if (argc < 3) {
fputs(usage, ctx->fout);
return;
@@ -1211,7 +1245,7 @@ cmd_mouse_move(struct shell_ctx *ctx, int argc, char **argv) {
switch (*ctx->opts.optarg++) {
case '=':
xabs = 1;
__attribute__ ((fallthrough));
[[fallthrough]];
case '+':
xmoving = strtol(ctx->opts.optarg, NULL, 0);
break;
@@ -1227,7 +1261,7 @@ cmd_mouse_move(struct shell_ctx *ctx, int argc, char **argv) {
switch (*ctx->opts.optarg++) {
case '=':
yabs = 1;
__attribute__ ((fallthrough));
[[fallthrough]];
case '+':
ymoving = strtol(ctx->opts.optarg, NULL, 0);
break;
@@ -2091,7 +2125,7 @@ cmd_load_cursor_from_mem(struct shell_ctx *ctx, int argc, char **argv) {
}
int show_pointers = 0;
const char *fname = argv[1];
void *fdata = host_load_file(fname);
void *fdata = host_load_file(fname, NULL);
if (!fdata) {
fprintf(ctx->fout, "[umka] Can't load file: %s\n", fname);
return;
@@ -2538,18 +2572,30 @@ ls_all(struct shell_ctx *ctx, struct f7080s1arg *fX0, enum f70or80 f70or80) {
while (true) {
struct f7080ret r = monitor_cmd_sys_lfn(ctx->monitor, f70or80,
(union f7080arg*)fX0);
print_f70_status(ctx, &r, 1);
assert((r.status == ERROR_SUCCESS && r.count == fX0->size)
|| (r.status == ERROR_END_OF_FILE && r.count < fX0->size));
struct f7080s1info *dir = fX0->buf;
fX0->offset += dir->cnt;
int ok = (r.count <= fX0->size);
ok &= (dir->cnt == r.count);
ok &= (r.status == KOS_ERROR_SUCCESS && r.count == fX0->size)
|| (r.status == KOS_ERROR_END_OF_FILE && r.count < fX0->size);
assert(ok);
if (!ok)
print_f70_status(ctx, &r, 1);
if (r.status == KOS_ERROR_SUCCESS) {
if (r.count != fX0->size) {
fprintf(ctx->fout, "eax == 0 but ebx != files to read\n");
break;
}
if (dir->cnt != r.count) {
fprintf(ctx->fout, "ebx != files read\n");
break;
}
} else if (r.status == KOS_ERROR_END_OF_FILE) {
if (r.count >= fX0->size) {
fprintf(ctx->fout, "eax == 6 but ebx >= files to read\n");
break;
}
if (dir->cnt != r.count) {
fprintf(ctx->fout, "ebx != files read\n");
break;
}
} else {
break;
}
fprintf(ctx->fout, "total = %"PRIi32"\n", dir->total_cnt);
struct bdfe *bdfe = dir->bdfes;
for (size_t i = 0; i < dir->cnt; i++) {
@@ -2694,6 +2740,58 @@ cmd_ls80(struct shell_ctx *ctx, int argc, char **argv) {
cmd_ls(ctx, argc, argv, usage, F80);
}
static void
cmd_mkdir(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80) {
const char *usage = \
"usage: mkdir <path>\n"
" path path/to/file\n";
if (argc != 2) {
fputs(usage, ctx->fout);
return;
}
optparse_init(&ctx->opts, argv);
struct f7080s9arg fX0 = {.sf = 9};
if (f70or80 == F70) {
fX0.u.f70.zero = 0;
fX0.u.f70.path = optparse_arg(&ctx->opts);
} else {
fX0.u.f80.path_encoding = DEFAULT_PATH_ENCODING;
fX0.u.f80.path = optparse_arg(&ctx->opts);
}
struct f7080ret r = monitor_cmd_sys_lfn(ctx->monitor, f70or80,
(union f7080arg*)&fX0);
print_f70_status(ctx, &r, 0);
if (r.status != KOS_ERROR_SUCCESS)
return;
}
static void
cmd_mkdir70(struct shell_ctx *ctx, int argc, char **argv) {
cmd_mkdir(ctx, argc, argv, F70);
}
static void
cmd_mkdir80(struct shell_ctx *ctx, int argc, char **argv) {
cmd_mkdir(ctx, argc, argv, F80);
}
const char *tz;
static void
tz_to_utc() {
tz = getenv("TZ");
setenv("TZ", "UTC", 1);
}
static void
tz_from_utc() {
if (tz) {
setenv("TZ", tz, 1);
} else {
unsetenv("TZ");
}
}
static void
cmd_stat(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80) {
const char *usage = \
@@ -2710,7 +2808,7 @@ cmd_stat(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80) {
bool force_ctime = false, force_mtime = false, force_atime = false;
struct f7080s5arg fX0 = {.sf = 5, .flags = 0};
struct bdfe file;
fX0.buf = &file;
fX0.info = &file;
if (f70or80 == F70) {
fX0.u.f70.zero = 0;
fX0.u.f70.path = optparse_arg(&ctx->opts);
@@ -2731,17 +2829,17 @@ cmd_stat(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80) {
}
int opt;
while ((opt = optparse(&ctx->opts, "cma")) != -1) {
while ((opt = optparse(&ctx->opts, "acm")) != -1) {
switch (opt) {
case 'a':
force_atime = true;
break;
case 'c':
force_ctime = true;
break;
case 'm':
force_mtime = true;
break;
case 'a':
force_atime = true;
break;
default:
fputs(usage, ctx->fout);
return;
@@ -2750,31 +2848,30 @@ cmd_stat(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80) {
time_t time;
struct tm *t;
const char *tz = getenv("TZ");
setenv("TZ", "UTC", 1);
tz_to_utc();
if (!ctx->reproducible || force_atime) {
time = kos_time_to_epoch(&file.atime);
time = kos_bdfe_time_to_epoch(&file.a_datetime);
t = localtime(&time);
fprintf(ctx->fout, "atime: %4.4i.%2.2i.%2.2i %2.2i:%2.2i:%2.2i\n",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
if (!ctx->reproducible || force_mtime) {
time = kos_time_to_epoch(&file.mtime);
time = kos_bdfe_time_to_epoch(&file.m_datetime);
t = localtime(&time);
fprintf(ctx->fout, "mtime: %4.4i.%2.2i.%2.2i %2.2i:%2.2i:%2.2i\n",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
if (!ctx->reproducible || force_ctime) {
time = kos_time_to_epoch(&file.ctime);
time = kos_bdfe_time_to_epoch(&file.c_datetime);
t = localtime(&time);
fprintf(ctx->fout, "ctime: %4.4i.%2.2i.%2.2i %2.2i:%2.2i:%2.2i\n",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
tz_from_utc();
if (tz) setenv("TZ", tz, 1); else unsetenv("TZ");
return;
}
@@ -2872,6 +2969,423 @@ cmd_read80(struct shell_ctx *ctx, int argc, char **argv) {
cmd_read(ctx, argc, argv, F80, usage);
}
static void
cmd_create(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80,
const char *usage) {
(void)ctx;
if (argc < 2) {
fputs(usage, ctx->fout);
return;
}
int opt;
optparse_init(&ctx->opts, argv);
struct f7080s2arg fX0 = {.sf = 2};
struct f7080ret r;
if (f70or80 == F70) {
fX0.u.f70.zero = 0;
fX0.u.f70.path = optparse_arg(&ctx->opts);
} else {
fX0.u.f80.path_encoding = DEFAULT_PATH_ENCODING;
fX0.u.f80.path = optparse_arg(&ctx->opts);
}
const char *src_fname = NULL;
const char *src_hex = NULL;
uint8_t *src_bin = NULL;
size_t src_len = 0;
size_t fsize = 0;
bool length_opt_used = false;
while ((opt = optparse(&ctx->opts, "e:f:h:l:")) != -1) {
switch (opt) {
case 'e':
if (f70or80 == F70) {
fprintf(ctx->fout, "f70 doesn't accept encoding parameter,"
" use f80\n");
return;
}
fX0.u.f80.path_encoding = parse_encoding(ctx->opts.optarg);
if (fX0.u.f80.path_encoding == INVALID_ENCODING) {
fprintf(ctx->fout, "can't parse encoding\n");
return;
}
break;
case 'f':
if (src_fname) {
fprintf(ctx->fout, "you can't specify both -f src_file and"
" -h src_hex\n");
return;
}
src_fname = ctx->opts.optarg;
src_bin = host_load_file(src_fname, &fsize);
if (!length_opt_used) {
fX0.size = fsize;
}
break;
case 'h':
if (src_fname) {
fprintf(ctx->fout, "you can't specify both -f src_file and"
" -h src_hex\n");
return;
}
src_hex = ctx->opts.optarg;
src_bin = parse_hex_string(ctx, src_hex, &src_len);
if (!length_opt_used) {
fX0.size = src_len;
}
break;
case 'l':
if (!parse_uint32(ctx, optparse_arg(&ctx->opts), &fX0.size)) {
fprintf(ctx->fout, "can't parse offset\n");
return;
}
length_opt_used = true;
break;
default:
fputs(usage, ctx->fout);
return;
}
}
fX0.buf = src_bin;
COVERAGE_ON();
umka_sys_lfn(&fX0, &r, f70or80);
COVERAGE_OFF();
print_f70_status(ctx, &r, 1);
free(fX0.buf);
return;
}
static void
cmd_create70(struct shell_ctx *ctx, int argc, char **argv) {
const char *usage = \
"usage: create70 <dst_file> [-l length] [-f src_file]"
" [-h src_hex]\n"
" dst_file path/to/file to write\n"
" -l length in bytes\n"
" -f src_file path/to/file to read\n"
" -h src_hex hex string to read\n";
cmd_create(ctx, argc, argv, F70, usage);
}
static void
cmd_create80(struct shell_ctx *ctx, int argc, char **argv) {
const char *usage = \
"usage: create80 <dst_file> [-l length] [-f src_file]"
" [-h src_hex] [-e cp866|utf8|utf16]\n"
" dst_file path/to/file to write\n"
" -l length in bytes\n"
" -f src_file path/to/file to read\n"
" -h src_hex hex string to read\n"
" -e encoding\n";
cmd_create(ctx, argc, argv, F80, usage);
}
static void
cmd_write(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80,
const char *usage) {
(void)ctx;
if (argc < 3) {
fputs(usage, ctx->fout);
return;
}
int opt;
optparse_init(&ctx->opts, argv);
struct f7080s3arg fX0 = {.sf = 3};
struct f7080ret r;
if (f70or80 == F70) {
fX0.u.f70.zero = 0;
fX0.u.f70.path = optparse_arg(&ctx->opts);
} else {
fX0.u.f80.path_encoding = DEFAULT_PATH_ENCODING;
fX0.u.f80.path = optparse_arg(&ctx->opts);
}
if (!parse_uint64(ctx, optparse_arg(&ctx->opts), &fX0.offset)) {
fprintf(ctx->fout, "can't parse offset\n");
return;
}
const char *src_fname = NULL;
const char *src_hex = NULL;
uint8_t *src_bin = NULL;
size_t src_len = 0;
size_t fsize = 0;
bool length_opt_used = false;
while ((opt = optparse(&ctx->opts, "e:f:h:l:")) != -1) {
switch (opt) {
case 'e':
if (f70or80 == F70) {
fprintf(ctx->fout, "f70 doesn't accept encoding parameter,"
" use f80\n");
return;
}
fX0.u.f80.path_encoding = parse_encoding(ctx->opts.optarg);
if (fX0.u.f80.path_encoding == INVALID_ENCODING) {
fprintf(ctx->fout, "can't parse encoding\n");
return;
}
break;
case 'f':
if (src_fname) {
fprintf(ctx->fout, "you can't specify both -f src_file and"
" -h src_hex\n");
return;
}
src_fname = ctx->opts.optarg;
src_bin = host_load_file(src_fname, &fsize);
if (!length_opt_used) {
fX0.size = fsize;
}
break;
case 'h':
if (src_fname) {
fprintf(ctx->fout, "you can't specify both -f src_file and"
" -h src_hex\n");
return;
}
src_hex = ctx->opts.optarg;
src_bin = parse_hex_string(ctx, src_hex, &src_len);
if (!length_opt_used) {
fX0.size = src_len;
}
break;
case 'l':
if (!parse_uint32(ctx, optparse_arg(&ctx->opts), &fX0.size)) {
fprintf(ctx->fout, "can't parse offset\n");
return;
}
length_opt_used = true;
break;
default:
fputs(usage, ctx->fout);
return;
}
}
fX0.buf = src_bin;
COVERAGE_ON();
umka_sys_lfn(&fX0, &r, f70or80);
COVERAGE_OFF();
print_f70_status(ctx, &r, 1);
free(fX0.buf);
return;
}
static void
cmd_write70(struct shell_ctx *ctx, int argc, char **argv) {
const char *usage = \
"usage: write70 <dst_file> <offset> [-l length] [-f src_file]"
" [-h src_hex]\n"
" dst_file path/to/file to write\n"
" offset in bytes\n"
" -l length in bytes\n"
" -f src_file path/to/file to read\n"
" -h src_hex hex string to read\n";
cmd_write(ctx, argc, argv, F70, usage);
}
static void
cmd_write80(struct shell_ctx *ctx, int argc, char **argv) {
const char *usage = \
"usage: write80 <dst_file> <offset> [-l length] [-f src_file]"
" [-h src_hex] [-e cp866|utf8|utf16]\n"
" dst_file path/to/file to write\n"
" offset in bytes\n"
" -l length in bytes\n"
" -f src_file path/to/file to read\n"
" -h src_hex hex string to read\n"
" -e encoding\n";
cmd_write(ctx, argc, argv, F80, usage);
}
static bool
parse_datetime(struct shell_ctx *ctx, const char *s, struct tm *t) {
if (sscanf(s, "%4d-%2d-%2d_%2d:%2d:%2d", &t->tm_year, &t->tm_mon,
&t->tm_mday, &t->tm_hour, &t->tm_min, &t->tm_sec) != 6) {
fprintf(ctx->fout, "bad date or time format\n");
return false;
}
t->tm_year -= 1900;
t->tm_mon -= 1;
return true;
}
static void
cmd_touch(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80,
const char *usage) {
(void)ctx;
if (argc < 2) {
fputs(usage, ctx->fout);
return;
}
int opt;
optparse_init(&ctx->opts, argv);
struct f7080s6arg fX0;
struct f7080ret r;
if (f70or80 == F70) {
fX0.u.f70.zero = 0;
fX0.u.f70.path = optparse_arg(&ctx->opts);
} else {
fX0.u.f80.path_encoding = DEFAULT_PATH_ENCODING;
fX0.u.f80.path = optparse_arg(&ctx->opts);
}
struct bdfe info;
fX0.info = &info;
fX0.sf = 5; // first read, then rewrite
COVERAGE_ON();
umka_sys_lfn(&fX0, &r, f70or80);
COVERAGE_OFF();
print_f70_status(ctx, &r, 0);
if (r.status != KOS_ERROR_SUCCESS) {
return;
}
struct tm t = {0};
while ((opt = optparse(&ctx->opts, "a:c:hHm:nNrRsS")) != -1) {
switch (opt) {
case 'a':
if (!parse_datetime(ctx, ctx->opts.optarg, &t)) {
return;
}
tz_to_utc();
kos_epoch_to_bdfe_time(mktime(&t), &info.a_datetime);
tz_from_utc();
break;
case 'c':
if (!parse_datetime(ctx, ctx->opts.optarg, &t)) {
return;
}
tz_to_utc();
kos_epoch_to_bdfe_time(mktime(&t), &info.c_datetime);
tz_from_utc();
break;
case 'h':
fX0.info->attr &= ~BDFE_ATTR_HIDDEN;
break;
case 'H':
fX0.info->attr |= BDFE_ATTR_HIDDEN;
break;
case 'm':
if (!parse_datetime(ctx, ctx->opts.optarg, &t)) {
return;
}
tz_to_utc();
kos_epoch_to_bdfe_time(mktime(&t), &info.m_datetime);
tz_from_utc();
break;
case 'n':
fX0.info->attr &= ~BDFE_ATTR_NOT_ARCHIVED;
break;
case 'N':
fX0.info->attr |= BDFE_ATTR_NOT_ARCHIVED;
break;
case 'r':
fX0.info->attr &= ~BDFE_ATTR_READ_ONLY;
break;
case 'R':
fX0.info->attr |= BDFE_ATTR_READ_ONLY;
break;
case 's':
fX0.info->attr &= ~BDFE_ATTR_SYSTEM;
break;
case 'S':
fX0.info->attr |= BDFE_ATTR_SYSTEM;
break;
default:
fputs(usage, ctx->fout);
return;
}
}
fX0.sf = 6;
COVERAGE_ON();
umka_sys_lfn(&fX0, &r, f70or80);
COVERAGE_OFF();
print_f70_status(ctx, &r, 0);
return;
}
static void
cmd_touch70(struct shell_ctx *ctx, int argc, char **argv) {
const char *usage = \
"usage: touch70 <file> [-a atime] [-c ctime] [-m mtime]"
" [-r|-R] [-h|-H] [-s|-S] [-n|-N]\n"
" -a atime access time string*\n"
" -c ctime change time string*\n"
" -a mtime modification time string*\n"
" -r|-R read-only bit reset/set\n"
" -h|-H hidden bit reset/set\n"
" -s|-S system bit reset/set\n"
" -n|-N not archived bit reset/set\n"
"* time format: YYYY-mm-DD_HH:MM:SS\n";
cmd_touch(ctx, argc, argv, F70, usage);
}
static void
cmd_touch80(struct shell_ctx *ctx, int argc, char **argv) {
const char *usage = \
"usage: touch80 [-a atime] [-c ctime] [-m mtime]"
" [-r|-R] [-h|-H] [-s|-S] [-n|-N] [-e cp866|utf8|utf16]\n"
" -a atime access time string*\n"
" -c ctime change time string*\n"
" -a mtime modification time string*\n"
" -r|-R read-only bit reset/set\n"
" -h|-H hidden bit reset/set\n"
" -s|-S system bit reset/set\n"
" -n|-N not archived bit reset/set\n"
" -e encoding\n"
"* time format: YYYY-mm-DD_HH:MM:SS\n";
cmd_touch(ctx, argc, argv, F80, usage);
}
static void
cmd_rm(struct shell_ctx *ctx, int argc, char **argv, enum f70or80 f70or80) {
const char *usage = \
"usage: rm <path>\n"
" path path/to/file\n";
if (argc != 2) {
fputs(usage, ctx->fout);
return;
}
optparse_init(&ctx->opts, argv);
struct f7080s8arg fX0 = {.sf = 8};
if (f70or80 == F70) {
fX0.u.f70.zero = 0;
fX0.u.f70.path = optparse_arg(&ctx->opts);
} else {
fX0.u.f80.path_encoding = DEFAULT_PATH_ENCODING;
fX0.u.f80.path = optparse_arg(&ctx->opts);
}
struct f7080ret r = monitor_cmd_sys_lfn(ctx->monitor, f70or80,
(union f7080arg*)&fX0);
print_f70_status(ctx, &r, 0);
if (r.status != KOS_ERROR_SUCCESS)
return;
}
static void
cmd_rm70(struct shell_ctx *ctx, int argc, char **argv) {
cmd_rm(ctx, argc, argv, F70);
}
static void
cmd_rm80(struct shell_ctx *ctx, int argc, char **argv) {
cmd_rm(ctx, argc, argv, F80);
}
static void
cmd_acpi_preload_table(struct shell_ctx *ctx, int argc, char **argv) {
(void)ctx;
@@ -3949,7 +4463,7 @@ cmd_board_get(struct shell_ctx *ctx, int argc, char **argv) {
switch (opt) {
case 'f':
flush = 1;
__attribute__((fallthrough)); // TODO: use [[fallthrough]]; (C23)
[[fallthrough]];
case 'l':
line = 1;
break;
@@ -4077,7 +4591,10 @@ func_table_t cmd_cmds[] = {
{ "blit_bitmap", cmd_blit_bitmap },
{ "button", cmd_button },
{ "cd", cmd_cd },
{ "set", cmd_set },
{ "check_for_event", cmd_check_for_event },
{ "create70", cmd_create70},
{ "create80", cmd_create80},
{ "csleep", cmd_csleep },
{ "get", cmd_get },
{ "get_key", cmd_get_key },
{ "disk_add", cmd_disk_add },
@@ -4155,6 +4672,9 @@ func_table_t cmd_cmds[] = {
{ "net_ipv4_set_gw", cmd_net_ipv4_set_gw },
{ "net_ipv4_set_subnet", cmd_net_ipv4_set_subnet },
{ "net_listen", cmd_net_listen },
{ "new_sys_thread", cmd_new_sys_thread },
{ "mkdir70", cmd_mkdir70 },
{ "mkdir80", cmd_mkdir80 },
{ "net_open_socket", cmd_net_open_socket },
{ "osloop", cmd_osloop },
{ "pci_get_path", cmd_pci_get_path },
@@ -4166,8 +4686,10 @@ func_table_t cmd_cmds[] = {
{ "ramdisk_init", cmd_ramdisk_init },
{ "read70", cmd_read70 },
{ "read80", cmd_read80 },
{ "rm70", cmd_rm70 },
{ "rm80", cmd_rm80 },
{ "scrot", cmd_scrot },
{ "write_devices_dat", cmd_write_devices_dat },
{ "set", cmd_set },
{ "set_button_style", cmd_set_button_style },
{ "set_cursor", cmd_set_cursor },
{ "set_cwd", cmd_cd },
@@ -4183,18 +4705,20 @@ func_table_t cmd_cmds[] = {
{ "set_system_lang", cmd_set_system_lang },
{ "set_window_caption", cmd_set_window_caption },
{ "set_window_colors", cmd_set_window_colors },
{ "csleep", cmd_csleep },
{ "stat70", cmd_stat70 },
{ "stat80", cmd_stat80 },
{ "touch70", cmd_touch70 },
{ "touch80", cmd_touch80 },
{ "var", cmd_var },
{ "check_for_event", cmd_check_for_event },
{ "wait_for_idle", cmd_wait_for_idle },
{ "wait_for_os_idle", cmd_wait_for_os_idle },
{ "wait_for_window", cmd_wait_for_window },
{ "window_redraw", cmd_window_redraw },
{ "write70", cmd_write70},
{ "write80", cmd_write80},
{ "write_devices_dat", cmd_write_devices_dat },
{ "write_text", cmd_write_text },
{ "switch_to_thread", cmd_switch_to_thread },
{ "new_sys_thread", cmd_new_sys_thread },
{ NULL, NULL },
};
+3 -3
View File
@@ -110,7 +110,7 @@ total = 7
status = 6 end_of_file, count = 7
total = 7
----f .
----- 
----- 
-----
-----
-----
@@ -167,8 +167,8 @@ total = 7
status = 6 end_of_file, count = 7
total = 7
----f .
r-s-f 
--s-f 
r-s-f 
--s-f 
-hs-f
rhs-f
--slf
+35 -6
View File
@@ -3,9 +3,28 @@
/hd0: sector_size=512, capacity=10485760 (5 GiB), num_partitions=1
/hd0/1: fs=ext, start=2048 (1 MiB), length=10481664 (5118 MiB)
/> ls70 /hd0/1/dir_a
status = 0 success, count = 5
status = 6 end_of_file, count = 5
total = 5
-h--f .
-h--f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
/> ls70 /hd0/1/dir_b
status = 0 success, count = 12
status = 6 end_of_file, count = 12
total = 12
-h--f .
-h--f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
----f d0000000003_
----f d0000000004_
----f d0000000005_
----f d0000000006_
----f d0000000007_
----f d0000000008_
----f d0000000009_
/> ls70 /hd0/1/dir_c
status = 0 success, count = 100
total = 102
@@ -109,7 +128,10 @@ total = 102
----f d0000000095_
----f d0000000096_
----f d0000000097_
status = 0 success, count = 2
status = 6 end_of_file, count = 2
total = 102
----f d0000000098_
----f d0000000099_
/> ls70 /hd0/1/dir_d
status = 0 success, count = 100
total = 1002
@@ -1131,7 +1153,10 @@ total = 1002
----f d0000000938_
----f d0000000951_
----f d0000000953_
status = 0 success, count = 2
status = 6 end_of_file, count = 2
total = 1002
----f d0000000994_
----f d0000000996_
/> ls70 /hd0/1/dir_e
status = 0 success, count = 100
total = 10002
@@ -11333,7 +11358,10 @@ total = 10002
----f d0000009825_
----f d0000009830_
----f d0000009842_
status = 0 success, count = 2
status = 6 end_of_file, count = 2
total = 10002
----f d0000009946_
----f d0000009970_
/> ls70 /hd0/1/dir_f
status = 0 success, count = 100
total = 65000
@@ -77635,5 +77663,6 @@ total = 65000
----f d0000016844_
----f d0000064544_
----f d0000064651_
status = 0 success, count = 0
status = 6 end_of_file, count = 0
total = 65000
/> disk_del hd0
+1 -1
View File
@@ -1 +1 @@
10s
20s
+18 -6
View File
@@ -3,13 +3,25 @@
/hd0: sector_size=512, capacity=30720 (15 MiB), num_partitions=1
/hd0/1: fs=ext, start=2048 (1 MiB), length=26624 (13 MiB)
/> ls70 /hd0/1/
status = 0 success, count = 11
status = 6 end_of_file, count = 11
total = 11
-h--f .
-h--f ..
----f lost+found
----f dira
----- file_1985
----- file_2015
----- file_2045
----- file_2085
----- file_2110
----- file_2200
----- file_ctime_crtime
/> stat70 /hd0/1/file_1985 -am
status = 0 success
attr: -----
size: 0
atime: 2001.01.01 00:00:00
mtime: 2001.01.01 00:00:00
atime: 2122.02.07 06:28:15
mtime: 2122.02.07 06:28:15
/> stat70 /hd0/1/file_2015 -am
status = 0 success
attr: -----
@@ -38,13 +50,13 @@ mtime: 2110.12.31 23:59:59
status = 0 success
attr: -----
size: 0
atime: 2137.02.07 06:28:15
mtime: 2137.02.07 06:28:15
atime: 2064.11.23 17:31:43
mtime: 2064.11.23 17:31:43
/> stat70 /hd0/1/file_ctime_crtime -amc
status = 0 success
attr: -----
size: 0
atime: 2024.01.01 12:00:00
mtime: 2024.01.01 12:00:00
ctime: 2010.01.01 00:00:00
ctime: 2020.01.01 00:00:00
/> disk_del hd0
+108
View File
@@ -0,0 +1,108 @@
/> umka_boot
/> disk_add ../../img/ext2_s05k.qcow2 hd0 -c 0
/hd0: sector_size=512, capacity=10485760 (5 GiB), num_partitions=1
/hd0/1: fs=ext, start=2048 (1 MiB), length=10481664 (5118 MiB)
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 5
total = 5
-h--f .
-h--f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
/> mkdir70 /hd0/1/dir_a/one
status = 0 success
/> mkdir70 /hd0/1/dir_a/two
status = 0 success
/> mkdir70 /hd0/1/dir_a/two/three
status = 0 success
/> mkdir70 /hd0/1/dir_a/four/five
status = 5 file_not_found
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 7
total = 7
-h--f .
-h--f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
----f one
----f two
/> ls70 /hd0/1/dir_a/one
status = 6 end_of_file, count = 2
total = 2
-h--f .
-h--f ..
/> ls70 /hd0/1/dir_a/two
status = 6 end_of_file, count = 3
total = 3
-h--f .
-h--f ..
----f three
/> ls70 /hd0/1/dir_a/two/three
status = 6 end_of_file, count = 2
total = 2
-h--f .
-h--f ..
/> ls70 /hd0/1/dir_a/four
status = 5 file_not_found
/> stat70 /hd0/1/dir_a
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/one
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/two
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/two/three
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/four
status = 5 file_not_found
/> rm70 /hd0/1/dir_a
status = 10 access_denied
/> rm70 /hd0/1/dir_a/one
status = 0 success
/> rm70 /hd0/1/dir_a/two
status = 10 access_denied
/> rm70 /hd0/1/dir_a/two/three
status = 0 success
/> rm70 /hd0/1/dir_a/two/three
status = 5 file_not_found
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 6
total = 6
-h--f .
-h--f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
----f two
/> rm70 /hd0/1/dir_a/two
status = 0 success
/> rm70 /hd0/1/dir_a/four
status = 5 file_not_found
/> rm70 /hd0/1/dir_a
status = 10 access_denied
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 5
total = 5
-h--f .
-h--f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
/> ls70 /hd0/1
status = 6 end_of_file, count = 9
total = 9
-h--f .
-h--f ..
----f lost+found
----f dir_a
----f dir_b
----f dir_c
----f dir_d
----f dir_e
----f dir_f
/> disk_del hd0
+29
View File
@@ -0,0 +1,29 @@
umka_boot
disk_add ../../img/ext2_s05k.qcow2 hd0 -c 0
ls70 /hd0/1/dir_a
mkdir70 /hd0/1/dir_a/one
mkdir70 /hd0/1/dir_a/two
mkdir70 /hd0/1/dir_a/two/three
mkdir70 /hd0/1/dir_a/four/five
ls70 /hd0/1/dir_a
ls70 /hd0/1/dir_a/one
ls70 /hd0/1/dir_a/two
ls70 /hd0/1/dir_a/two/three
ls70 /hd0/1/dir_a/four
stat70 /hd0/1/dir_a
stat70 /hd0/1/dir_a/one
stat70 /hd0/1/dir_a/two
stat70 /hd0/1/dir_a/two/three
stat70 /hd0/1/dir_a/four
rm70 /hd0/1/dir_a
rm70 /hd0/1/dir_a/one
rm70 /hd0/1/dir_a/two
rm70 /hd0/1/dir_a/two/three
rm70 /hd0/1/dir_a/two/three
ls70 /hd0/1/dir_a
rm70 /hd0/1/dir_a/two
rm70 /hd0/1/dir_a/four
rm70 /hd0/1/dir_a
ls70 /hd0/1/dir_a
ls70 /hd0/1
disk_del hd0
+3
View File
@@ -0,0 +1,3 @@
syscall:f70,f70s1,f70s9
fs:ext,ext2,write,mkdir
blkdev:s05k
+1
View File
@@ -0,0 +1 @@
5s
+105
View File
@@ -0,0 +1,105 @@
/> umka_boot
/> disk_add ../../img/fat16_s05k.qcow2 hd0 -c 0
/hd0: sector_size=512, capacity=8388608 (4 GiB), num_partitions=1
/hd0/1: fs=fat, start=2048 (1 MiB), length=8384481 (4292854272 B)
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 5
total = 5
----f .
----f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
/> mkdir70 /hd0/1/dir_a/one
status = 0 success
/> mkdir70 /hd0/1/dir_a/two
status = 0 success
/> mkdir70 /hd0/1/dir_a/two/three
status = 0 success
/> mkdir70 /hd0/1/dir_a/four/five
status = 5 file_not_found
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 7
total = 7
----f .
----f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
----f ONE
----f TWO
/> ls70 /hd0/1/dir_a/one
status = 6 end_of_file, count = 2
total = 2
----f .
----f ..
/> ls70 /hd0/1/dir_a/two
status = 6 end_of_file, count = 3
total = 3
----f .
----f ..
----f THREE
/> ls70 /hd0/1/dir_a/two/three
status = 6 end_of_file, count = 2
total = 2
----f .
----f ..
/> ls70 /hd0/1/dir_a/four
status = 5 file_not_found
/> stat70 /hd0/1/dir_a
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/one
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/two
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/two/three
status = 0 success
attr: ----f
/> stat70 /hd0/1/dir_a/four
status = 5 file_not_found
/> rm70 /hd0/1/dir_a
status = 10 access_denied
/> rm70 /hd0/1/dir_a/one
status = 0 success
/> rm70 /hd0/1/dir_a/two
status = 10 access_denied
/> rm70 /hd0/1/dir_a/two/three
status = 0 success
/> rm70 /hd0/1/dir_a/two/three
status = 5 file_not_found
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 6
total = 6
----f .
----f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
----f TWO
/> rm70 /hd0/1/dir_a/two
status = 0 success
/> rm70 /hd0/1/dir_a/four
status = 5 file_not_found
/> rm70 /hd0/1/dir_a
status = 10 access_denied
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 5
total = 5
----f .
----f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
/> ls70 /hd0/1
status = 6 end_of_file, count = 6
total = 6
----f dir_a
----f dir_b
----f dir_c
----f dir_d
----f dir_e
----f dir_f
/> disk_del hd0
+29
View File
@@ -0,0 +1,29 @@
umka_boot
disk_add ../../img/fat16_s05k.qcow2 hd0 -c 0
ls70 /hd0/1/dir_a
mkdir70 /hd0/1/dir_a/one
mkdir70 /hd0/1/dir_a/two
mkdir70 /hd0/1/dir_a/two/three
mkdir70 /hd0/1/dir_a/four/five
ls70 /hd0/1/dir_a
ls70 /hd0/1/dir_a/one
ls70 /hd0/1/dir_a/two
ls70 /hd0/1/dir_a/two/three
ls70 /hd0/1/dir_a/four
stat70 /hd0/1/dir_a
stat70 /hd0/1/dir_a/one
stat70 /hd0/1/dir_a/two
stat70 /hd0/1/dir_a/two/three
stat70 /hd0/1/dir_a/four
rm70 /hd0/1/dir_a
rm70 /hd0/1/dir_a/one
rm70 /hd0/1/dir_a/two
rm70 /hd0/1/dir_a/two/three
rm70 /hd0/1/dir_a/two/three
ls70 /hd0/1/dir_a
rm70 /hd0/1/dir_a/two
rm70 /hd0/1/dir_a/four
rm70 /hd0/1/dir_a
ls70 /hd0/1/dir_a
ls70 /hd0/1
disk_del hd0
+3
View File
@@ -0,0 +1,3 @@
syscall:f70,f70s1,f70s9
fs:fat,rw,mkdir,rm
blkdev:s05k
+1
View File
@@ -0,0 +1 @@
5s
+46
View File
@@ -0,0 +1,46 @@
/> umka_boot
/> disk_add ../../img/fat16_s05k.qcow2 hd0 -c 0
/hd0: sector_size=512, capacity=8388608 (4 GiB), num_partitions=1
/hd0/1: fs=fat, start=2048 (1 MiB), length=8384481 (4292854272 B)
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 5
total = 5
----f .
----f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
/> write70 /hd0/1/dir_a/one.txt 3 -h 00112233
status = 5 file_not_found
/> stat70 /hd0/1/dir_a/one.txt
status = 5 file_not_found
/> read70 /hd0/1/dir_a/one.txt 0 100 -b
status = 5 file_not_found
/> create70 /hd0/1/dir_a/one.txt -h 00112233
status = 0 success, count = 4
/> stat70 /hd0/1/dir_a/one.txt
status = 0 success
attr: -----
size: 4
/> read70 /hd0/1/dir_a/one.txt 0 100 -b
status = 6 end_of_file, count = 4
00112233
/> write70 /hd0/1/dir_a/one.txt 3 -h 00112233
status = 0 success, count = 4
/> stat70 /hd0/1/dir_a/one.txt
status = 0 success
attr: -----
size: 7
/> read70 /hd0/1/dir_a/one.txt 0 100 -b
status = 6 end_of_file, count = 7
00112200112233
/> ls70 /hd0/1/dir_a
status = 6 end_of_file, count = 6
total = 6
----f .
----f ..
----f d0000000000_
----f d0000000001_
----f d0000000002_
----- ONE.TXT
/> disk_del hd0
+14
View File
@@ -0,0 +1,14 @@
umka_boot
disk_add ../../img/fat16_s05k.qcow2 hd0 -c 0
ls70 /hd0/1/dir_a
write70 /hd0/1/dir_a/one.txt 3 -h 00112233
stat70 /hd0/1/dir_a/one.txt
read70 /hd0/1/dir_a/one.txt 0 100 -b
create70 /hd0/1/dir_a/one.txt -h 00112233
stat70 /hd0/1/dir_a/one.txt
read70 /hd0/1/dir_a/one.txt 0 100 -b
write70 /hd0/1/dir_a/one.txt 3 -h 00112233
stat70 /hd0/1/dir_a/one.txt
read70 /hd0/1/dir_a/one.txt 0 100 -b
ls70 /hd0/1/dir_a
disk_del hd0
+3
View File
@@ -0,0 +1,3 @@
syscall:f70,f70s2,f70s3
fs:fat,fat16,rw,create,write
blkdev:s05k
+1
View File
@@ -0,0 +1 @@
10s
+23
View File
@@ -0,0 +1,23 @@
/> umka_boot
/> disk_add ../../img/fat16_s05k.qcow2 hd0 -c 0
/hd0: sector_size=512, capacity=8388608 (4 GiB), num_partitions=1
/hd0/1: fs=fat, start=2048 (1 MiB), length=8384481 (4292854272 B)
/> touch70 /hd0/1/dir_a -H -R -S -a 2001-02-03_04:05:06 -c 2005-06-07_08:09:10 -m 2009-10-11_12:13:14
status = 0 success
status = 0 success
/> stat70 /hd0/1/dir_a -acm
status = 0 success
attr: rhs-f
atime: 2001.02.03 00:00:00
mtime: 2009.10.11 12:13:14
ctime: 2005.06.07 08:09:10
/> touch70 /hd0/1/dir_a -s -c 2025-12-31_23:59:59
status = 0 success
status = 0 success
/> stat70 /hd0/1/dir_a -acm
status = 0 success
attr: rh--f
atime: 2001.02.03 00:00:00
mtime: 2009.10.11 12:13:14
ctime: 2025.12.31 23:59:58
/> disk_del hd0
+7
View File
@@ -0,0 +1,7 @@
umka_boot
disk_add ../../img/fat16_s05k.qcow2 hd0 -c 0
touch70 /hd0/1/dir_a -H -R -S -a 2001-02-03_04:05:06 -c 2005-06-07_08:09:10 -m 2009-10-11_12:13:14
stat70 /hd0/1/dir_a -acm
touch70 /hd0/1/dir_a -s -c 2025-12-31_23:59:59
stat70 /hd0/1/dir_a -acm
disk_del hd0
+3
View File
@@ -0,0 +1,3 @@
syscall:f70,f70s6
fs:fat,fat16,rw,touch
blkdev:s05k
+1
View File
@@ -0,0 +1 @@
10s
+33 -2
View File
@@ -138,7 +138,8 @@ pubsym coverage_begin
pubsym coverage_end
pubsym sha3_256_oneshot, 'hash_oneshot'
pubsym kos_time_to_epoch
pubsym kos_bdfe_time_to_epoch
pubsym kos_epoch_to_bdfe_time
pubsym umka_init, 'umka_init'
pubsym umka_close, 'umka_close'
pubsym umka_boot
@@ -556,7 +557,15 @@ include 'blkdev/rd.inc' ; ramdisk driver
include 'blkdev/disk.inc'
include 'blkdev/disk_cache.inc'
macro call target {
if target eq fsReadCMOS
call _fsReadCMOS
else
call target
end if
}
include 'fs/fs_lfn.inc'
purge call
include 'network/stack.inc'
@@ -575,7 +584,7 @@ proc sha3_256_oneshot c uses ebx esi edi ebp, _ctx, _data, _len
ret
endp
proc kos_time_to_epoch c uses ebx esi edi ebp, _time
proc kos_bdfe_time_to_epoch c uses ebx esi edi ebp, _time
mov esi, [_time]
call fsCalculateTime
xor edx, edx
@@ -584,6 +593,14 @@ proc kos_time_to_epoch c uses ebx esi edi ebp, _time
ret
endp
proc kos_epoch_to_bdfe_time c uses ebx esi edi ebp, _epoch_lo, _time
mov eax, [_epoch_lo]
sub eax, UNIXTIME_TO_KOS_OFFSET
mov edi, [_time]
call fsTime2bdfe
ret
endp
proc umka._.check_alignment
mov eax, HEAP_BASE
and eax, PAGE_SIZE - 1
@@ -943,6 +960,20 @@ proc _pci_read_reg uses ebx esi edi
ret
endp
static_cmos db 0x33, 0, 0x22, 0, 0x11, 0, 0, 3, 4, 5
proc _fsReadCMOS
push ecx
movzx ecx, al
mov al, [static_cmos + ecx]
pop ecx
xor ah, ah
shl ax, 4
shr al, 4
aad
ret
endp
proc _page_fault_handler
ret
endp
+187 -63
View File
@@ -3,7 +3,7 @@
UMKa - User-Mode KolibriOS developer tools
Copyright (C) 2017-2023 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2017-2026 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru>
*/
@@ -30,8 +30,6 @@
typedef void siginfo_t;
#endif
#define STDCALL __attribute__((__stdcall__))
enum {
UMKA_RUNNING_NEVER,
UMKA_RUNNING_NOT_YET,
@@ -153,7 +151,7 @@ struct dbg_regs {
uint32_t dr0, dr1, dr2, dr3, dr7;
};
struct __attribute__((packed)) process_information {
struct [[gnu::packed]] process_information {
uint32_t cpu_usage;
uint16_t window_stack_position;
uint16_t window_stack_value;
@@ -173,7 +171,7 @@ struct __attribute__((packed)) process_information {
static_assert(sizeof(struct process_information) == 0x400,
"must be 0x400 bytes long");
struct __attribute__((packed)) wdata {
struct [[gnu::packed]] wdata {
struct box box;
uint32_t cl_workarea;
uint32_t cl_titlebar;
@@ -214,11 +212,11 @@ struct system_colors {
};
enum fs_enc {
INVALID_ENCODING = -1,
DEFAULT_ENCODING,
CP866,
UTF16,
UTF8,
INVALID_ENCODING,
};
enum f70or80 {
@@ -287,17 +285,18 @@ struct partition {
struct diskfunc {
uint32_t strucsize;
STDCALL void (*close)(void *userdata);
STDCALL void (*closemedia)(void *userdata);
STDCALL int (*querymedia)(void *userdata, struct diskmediainfo *info);
STDCALL int (*read)(void *userdata, void *buffer, off_t startsector,
size_t *numsectors);
STDCALL int (*write)(void *userdata, void *buffer, off_t startsector,
size_t *numsectors);
STDCALL int (*flush)(void *userdata);
STDCALL unsigned int (*adjust_cache_size)(void *userdata,
[[gnu::stdcall]] void (*close)(void *userdata);
[[gnu::stdcall]] void (*closemedia)(void *userdata);
[[gnu::stdcall]] int (*querymedia)(void *userdata,
struct diskmediainfo *info);
[[gnu::stdcall]] int (*read)(void *userdata, void *buffer,
off_t startsector, size_t *numsectors);
[[gnu::stdcall]] int (*write)(void *userdata, void *buffer,
off_t startsector, size_t *numsectors);
[[gnu::stdcall]] int (*flush)(void *userdata);
[[gnu::stdcall]] unsigned int (*adjust_cache_size)(void *userdata,
size_t suggested_size);
STDCALL int (*loadtray)(void *userdata, int flags);
[[gnu::stdcall]] int (*loadtray)(void *userdata, int flags);
};
struct disk;
@@ -324,17 +323,26 @@ struct disk {
struct disk_cache app_cache;
};
struct bdfe_datetime {
uint32_t time;
uint32_t date;
};
#define BDFE_ATTR_READ_ONLY 0x01
#define BDFE_ATTR_HIDDEN 0x02
#define BDFE_ATTR_SYSTEM 0x04
#define BDFE_ATTR_VOLUME_LABEL 0x08
#define BDFE_ATTR_DIRECTORY 0x10
#define BDFE_ATTR_NOT_ARCHIVED 0x20
struct bdfe {
uint32_t attr;
uint32_t enc;
uint32_t ctime;
uint32_t cdate;
uint32_t atime;
uint32_t adate;
uint32_t mtime;
uint32_t mdate;
struct bdfe_datetime c_datetime;
struct bdfe_datetime a_datetime;
struct bdfe_datetime m_datetime;
uint64_t size;
char name[0x777]; // how to handle this properly? FIXME
char name[0x777]; // how to handle this properly? union? FIXME
};
struct f7080ret {
@@ -342,16 +350,16 @@ struct f7080ret {
uint32_t count;
};
struct __attribute__((packed)) f7080s0arg {
struct [[gnu::packed]] f7080s0arg {
uint32_t sf;
uint64_t offset;
uint32_t count;
void *buf;
union {
struct {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} __attribute__((packed)) f70;
} f70;
struct {
uint32_t path_encoding;
const char *path;
@@ -359,17 +367,17 @@ struct __attribute__((packed)) f7080s0arg {
} u;
};
struct __attribute__((packed)) f7080s1arg {
struct [[gnu::packed]] f7080s1arg {
uint32_t sf;
uint32_t offset;
uint32_t encoding;
uint32_t size;
void *buf;
union {
struct {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} __attribute__((packed)) f70;
} f70;
struct {
uint32_t path_encoding;
const char *path;
@@ -377,6 +385,41 @@ struct __attribute__((packed)) f7080s1arg {
} u;
};
struct [[gnu::packed]] f7080s2arg {
uint32_t sf;
uint32_t reserved1;
uint32_t reserved2;
uint32_t size;
void *buf;
union {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} f70;
struct {
int path_encoding;
const char *path;
} f80;
} u;
};
struct [[gnu::packed]] f7080s3arg {
uint32_t sf;
uint64_t offset;
uint32_t size;
void *buf;
union {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} f70;
struct {
int path_encoding;
const char *path;
} f80;
} u;
};
struct f7080s1info {
uint32_t version;
uint32_t cnt;
@@ -385,17 +428,17 @@ struct f7080s1info {
struct bdfe bdfes[];
};
struct __attribute__((packed)) f7080s5arg {
struct [[gnu::packed]] f7080s5arg {
uint32_t sf;
uint32_t reserved1;
uint32_t flags;
uint32_t reserved2;
void *buf;
struct bdfe *info;
union {
struct {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} __attribute__((packed)) f70;
} f70;
struct {
uint32_t path_encoding;
const char *path;
@@ -403,17 +446,71 @@ struct __attribute__((packed)) f7080s5arg {
} u;
};
struct __attribute__((packed)) f7080s7arg {
struct [[gnu::packed]] f7080s6arg {
uint32_t sf;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
struct bdfe *info;
union {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} f70;
struct {
uint32_t path_encoding;
const char *path;
} f80;
} u;
};
struct [[gnu::packed]] f7080s7arg {
uint32_t sf;
uint32_t flags;
char *params;
uint32_t reserved1;
uint32_t reserved2;
union {
struct {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} __attribute__((packed)) f70;
} f70;
struct {
uint32_t path_encoding;
const char *path;
} f80;
} u;
};
struct [[gnu::packed]] f7080s8arg {
uint32_t sf;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
void *reserved4;
union {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} f70;
struct {
uint32_t path_encoding;
const char *path;
} f80;
} u;
};
struct [[gnu::packed]] f7080s9arg {
uint32_t sf;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
void *reserved4;
union {
struct [[gnu::packed]] {
uint8_t zero;
const char *path;
} f70;
struct {
uint32_t path_encoding;
const char *path;
@@ -424,8 +521,12 @@ struct __attribute__((packed)) f7080s7arg {
union f7080arg {
struct f7080s0arg s0;
struct f7080s1arg s1;
struct f7080s3arg s3;
struct f7080s5arg s5;
struct f7080s5arg s6;
struct f7080s7arg s7;
struct f7080s8arg s8;
struct f7080s9arg s9;
};
#define KF_READONLY 0x01
@@ -510,9 +611,9 @@ struct net_device {
char *name; // ptr to 0 terminated string
// ptrs to driver functions
STDCALL void (*unload) (void);
STDCALL void (*reset) (void);
STDCALL int (*transmit) (net_buff_t *);
[[gnu::stdcall]] void (*unload) (void);
[[gnu::stdcall]] void (*reset) (void);
[[gnu::stdcall]] int (*transmit) (net_buff_t *);
uint32_t link_state; // link state (0 = no link)
uint32_t hwacc; // bitmask stating enabled HW accelerations (offload
@@ -591,15 +692,22 @@ void
i40(void);
time_t
kos_time_to_epoch(uint32_t *time);
kos_bdfe_time_to_epoch(struct bdfe_datetime *time);
STDCALL struct disk *
disk_add(struct diskfunc *disk, const char *name, void *userdata, uint32_t flags);
void
kos_epoch_to_bdfe_time(uint32_t epoch, struct bdfe_datetime *time);
STDCALL void *
[[gnu::stdcall]]
struct disk *
disk_add(struct diskfunc *disk, const char *name, void *userdata,
uint32_t flags);
[[gnu::stdcall]]
void *
disk_media_changed(struct disk *disk, int inserted);
STDCALL void
[[gnu::stdcall]]
void
disk_del(struct disk *disk);
void
@@ -620,11 +728,13 @@ extern char kos_ramdisk[RAMDISK_MAX_LEN];
struct disk *
kos_ramdisk_init(void);
STDCALL void
[[gnu::stdcall]]
void
kos_set_mouse_data(uint32_t btn_state, int32_t xmoving, int32_t ymoving,
int32_t vscroll, int32_t hscroll);
STDCALL net_buff_t *
[[gnu::stdcall]]
net_buff_t *
kos_net_buff_alloc(size_t size);
struct idt_entry {
@@ -638,7 +748,8 @@ typedef int (*hw_int_handler_t)(void*);
extern struct idt_entry kos_idts[];
STDCALL void
[[gnu::stdcall]]
void
kos_attach_int_handler(int irq, hw_int_handler_t handler, void *userdata);
void
@@ -686,28 +797,36 @@ extern struct pci_dev *kos_pci_root;
void
kos_acpi_aml_init(void);
STDCALL void
[[gnu::stdcall]]
void
kos_aml_attach(acpi_node_t *parent, acpi_node_t *node);
STDCALL void
[[gnu::stdcall]]
void
kos_acpi_fill_pci_irqs(void *ctx);
STDCALL amlctx_t*
[[gnu::stdcall]]
amlctx_t*
kos_acpi_aml_new_thread(void);
STDCALL acpi_node_t*
[[gnu::stdcall]]
acpi_node_t*
kos_aml_alloc_node(int32_t type);
STDCALL acpi_node_t*
[[gnu::stdcall]]
acpi_node_t*
kos_aml_constructor_integer(void);
STDCALL acpi_node_t*
[[gnu::stdcall]]
acpi_node_t*
kos_aml_constructor_package(size_t el_cnt);
STDCALL acpi_node_t*
[[gnu::stdcall]]
acpi_node_t*
kos_acpi_lookup_node(acpi_node_t *root, char *name);
STDCALL void
[[gnu::stdcall]]
void
kos_acpi_print_tree(void *ctx);
#define MAX_PCI_DEVICES 256
@@ -718,13 +837,17 @@ extern void *kos_acpi_dev_next;
void kos_eth_input(void *buf);
STDCALL void*
[[gnu::stdcall]]
void*
kos_kernel_alloc(size_t len);
STDCALL void
[[gnu::stdcall]]
void
kos_pci_walk_tree(struct pci_dev *node,
STDCALL void* (*test)(struct pci_dev *node, void *arg),
STDCALL void* (*clbk)(struct pci_dev *node, void *arg),
[[gnu::stdcall]] void* (*test)(struct pci_dev *node,
void *arg),
[[gnu::stdcall]] void* (*clbk)(struct pci_dev *node,
void *arg),
void *arg);
struct f75ret {
@@ -760,11 +883,12 @@ kos_net_add_device(struct net_device *dev) {
return dev_num;
}
STDCALL void
[[gnu::stdcall]]
void
kos_window_set_screen(ssize_t left, ssize_t top, ssize_t right, ssize_t bottom,
ssize_t proc);
struct __attribute__((packed)) display {
struct [[gnu::packed]] display {
int32_t x;
int32_t y;
size_t width;
@@ -821,7 +945,7 @@ struct e820entry {
#define MAX_MEMMAP_BLOCKS 32
struct __attribute__((packed)) boot_data {
struct [[gnu::packed]] boot_data {
uint8_t bpp; // bits per pixel
uint16_t pitch; // scanline length
uint8_t pad1[5];
@@ -1076,7 +1200,7 @@ extern void *acpi_ctx;
extern uint32_t kos_acpi_usage;
extern uint32_t kos_acpi_node_alloc_cnt;
extern uint32_t kos_acpi_node_free_cnt;
extern uint32_t kos_acpi_count_nodes(void *ctx) STDCALL;
extern uint32_t kos_acpi_count_nodes(void *ctx) [[gnu::stdcall]];
extern struct srv srv_list;
extern struct dlldescr dll_list;
extern struct smem shmem_list;
+4 -4
View File
@@ -58,9 +58,9 @@ bdfe_to_stat(struct bdfe *kf, struct stat *st) {
st->st_nlink = 1;
st->st_size = kf->size;
}
st->st_atime = kos_time_to_epoch(&(kf->atime));
st->st_mtime = kos_time_to_epoch(&(kf->mtime));
st->st_ctime = kos_time_to_epoch(&(kf->ctime));
st->st_atime = kos_bdfe_time_to_epoch(&(kf->a_datetime));
st->st_ctime = kos_bdfe_time_to_epoch(&(kf->c_datetime));
st->st_mtime = kos_bdfe_time_to_epoch(&(kf->m_datetime));
}
static void *
@@ -83,7 +83,7 @@ fs_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) {
struct bdfe file;
struct f7080s5arg fX0 = {.sf = 5,
.flags = 0,
.buf = &file,
.info = &file,
.u = {.f80 = {.path_encoding = UTF8,
.path = path
}
+1
View File
@@ -153,6 +153,7 @@ io_async_read(int fd, void *buf, size_t count, void *arg) {
ssize_t
io_async_write(int fd, const void *buf, size_t count, void *arg) {
fprintf(stderr, "### io_async_write not implemented!\n");
(void)fd;
(void)buf;
(void)count;
+2 -1
View File
@@ -25,7 +25,8 @@ struct devices_dat_entry {
uint32_t pad2;
};
static STDCALL void*
[[gnu::stdcall]]
static void*
dump_devices_dat_iter(struct pci_dev *node, void *arg) {
FILE *f = arg;
if (node->gsi) {
+4 -2
View File
@@ -19,7 +19,8 @@
#include "vdisk/raw.h"
#include "vdisk/qcow2.h"
STDCALL int
[[gnu::stdcall]]
int
vdisk_querymedia(void *userdata, struct diskmediainfo *minfo) {
COVERAGE_OFF();
struct vdisk *disk = userdata;
@@ -30,7 +31,8 @@ vdisk_querymedia(void *userdata, struct diskmediainfo *minfo) {
return KOS_ERROR_SUCCESS;
}
STDCALL size_t
[[gnu::stdcall]]
size_t
vdisk_adjust_cache_size(void *userdata, size_t suggested_size) {
struct vdisk *disk = userdata;
if (disk->adjust_cache_size) {
+232 -79
View File
@@ -4,7 +4,7 @@
UMKa - User-Mode KolibriOS developer tools
vdisk - virtual disk, qcow2 format
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2023,2025-2026 Ivan Baravy <dunkaist@gmail.com>
*/
#include <errno.h>
@@ -16,12 +16,18 @@
#include "umkaio.h"
#include "em_inflate/em_inflate.h"
#define L1_MAX_LEN (32u*1024u*1024u)
#define L1_MAX_ENTRIES (L1_MAX_LEN / sizeof(uint64_t))
#define QCOW2_DIRTY_SUFFIX ".dirty"
struct qcow2_file {
char *fname;
int fd;
uint64_t *l1;
};
struct vdisk_qcow2 {
struct vdisk vdisk;
int fd;
struct qcow2_file base;
struct qcow2_file dirty;
size_t cluster_bits;
size_t cluster_size;
uint8_t *cluster;
@@ -30,20 +36,15 @@ struct vdisk_qcow2 {
uint64_t l2_entry_cmp_x;
uint64_t l2_entry_cmp_offset_mask;
uint64_t l2_entry_cmp_sect_cnt_mask;
size_t header_length;
size_t refcount_order;
size_t refcount_table_clusters;
off_t refcount_table_offset;
size_t l1_size;
uint64_t sector_idx_mask;
uint64_t *l1;
uint64_t prev_cluster_index;
};
#define QCOW2_MAGIC "QFI\xfb"
struct qcow2_header {
char magic[4];
[[gnu::nonstring]] char magic[4];
uint32_t version;
uint64_t back_file_offset;
uint32_t back_file_size;
@@ -74,6 +75,20 @@ struct qcow2_header {
#define L2_ENTRY_FORMAT 0x4000000000000000ULL
#define L2_ENTRY_STATUS 0x8000000000000000ULL
#define BSWAP32(x) ( (((uint32_t)(x) & 0x000000ffu) << 24) \
+ (((uint32_t)(x) & 0x0000ff00u) << 8) \
+ (((uint32_t)(x) & 0x00ff0000u) >> 8) \
+ (((uint32_t)(x) & 0xff000000u) >> 24))
#define BSWAP64(x) ( (((uint64_t)(x) & 0x00000000000000ffull) << 56) \
+ (((uint64_t)(x) & 0x000000000000ff00ull) << 40) \
+ (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) \
+ (((uint64_t)(x) & 0x00000000ff000000ull) << 8) \
+ (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) \
+ (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) \
+ (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) \
+ (((uint64_t)(x) & 0xff00000000000000ull) >> 56))
static inline uint32_t
be32(void *p) {
uint8_t *x = p;
@@ -90,110 +105,247 @@ be64(void *p) {
+ ((uint64_t)x[1] << 48) + ((uint64_t)x[0] << 56);
}
static void
qcow2_read_guest_sector(struct vdisk_qcow2 *d, uint64_t sector, uint8_t *buf) {
static int
qcow2_read_guest_cluster(struct vdisk_qcow2 *d, struct qcow2_file *qf,
uint64_t cluster_index) {
uint64_t cluster_offset;
size_t l2_entries = d->cluster_size / sizeof(uint64_t);
uint64_t offset = sector * d->vdisk.sect_size;
uint64_t cluster_index = offset / d->cluster_size;
uint64_t l1_index = (cluster_index) / l2_entries;
uint64_t l2_index = (cluster_index) % l2_entries;
uint64_t l1_entry = d->l1[l1_index];
uint64_t l1_entry = qf->l1[l1_index]; // TODO: move all l2 to mem
uint64_t l2_entry;
if (cluster_index == d->prev_cluster_index) {
memcpy(buf,
d->cluster + (sector & d->sector_idx_mask) * d->vdisk.sect_size,
d->vdisk.sect_size);
return;
}
d->prev_cluster_index = cluster_index;
uint64_t l2_table_offset = l1_entry & L1_ENTRY_OFFSET_MASK;
if (!l2_table_offset) {
memset(buf, 0, d->vdisk.sect_size);
return;
return 0;
}
lseek(d->fd, l2_table_offset + l2_index*sizeof(l2_entry), SEEK_SET);
if (!io_read(d->fd, &l2_entry, sizeof(l2_entry), d->vdisk.io)) {
lseek(qf->fd, l2_table_offset + l2_index*sizeof(l2_entry), SEEK_SET);
if (!io_read(qf->fd, &l2_entry, sizeof(l2_entry), d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
return;
return -1;
}
l2_entry = be64(&l2_entry);
if ((l2_entry & L2_ENTRY_FORMAT) == CLUSTER_FORMAT_STANDARD) {
if (l2_entry & L2_ENTRY_STD_ZEROED) {
printf("[vdisk.qcow2] cluster 0x%" PRIx64 " is zeroed\n",
cluster_index);
memset(buf, 0, d->vdisk.sect_size);
return;
}
cluster_offset = l2_entry & L2_ENTRY_STD_OFFSET;
lseek(d->fd, cluster_offset, SEEK_SET);
if (!io_read(d->fd, d->cluster, d->cluster_size, d->vdisk.io)) {
if (!cluster_offset) {
return 0;
}
lseek(qf->fd, cluster_offset, SEEK_SET);
if (!io_read(qf->fd, d->cluster, d->cluster_size, d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
return;
return -1;
}
} else {
// compressed
off_t cmp_offset = d->l2_entry_cmp_offset_mask & l2_entry;
printf("cmp_offset: 0x%" PRIx64 "\n", cmp_offset);
lseek(d->fd, cmp_offset, SEEK_SET);
lseek(qf->fd, cmp_offset, SEEK_SET);
size_t additional_sectors = (l2_entry & d->l2_entry_cmp_sect_cnt_mask)
>> d->l2_entry_cmp_x;
size_t cmp_size = 512 - (cmp_offset & 511) + additional_sectors*512;
if (!io_read(d->fd, d->cmp_cluster, d->cluster_size, d->vdisk.io)) {
if (!io_read(qf->fd, d->cmp_cluster, d->cluster_size, d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
return;
return -1;
}
unsigned long dest_size = d->cluster_size;
em_inflate(d->cluster, dest_size, d->cmp_cluster, cmp_size);
}
memcpy(buf,
d->cluster + (sector & d->sector_idx_mask) * d->vdisk.sect_size,
d->vdisk.sect_size);
return 1;
}
STDCALL void
static int
qcow2_read_guest_sector(struct vdisk_qcow2 *d, uint64_t sector, uint8_t *buf) {
uint64_t offset = sector * d->vdisk.sect_size;
uint64_t cluster_index = offset / d->cluster_size;
int status = 0;
if (d->dirty.fd) {
status = qcow2_read_guest_cluster(d, &d->dirty, cluster_index);
}
if (!status) {
status = qcow2_read_guest_cluster(d, &d->base, cluster_index);
}
if (status < 0) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
return KOS_ERROR_DEVICE;
}
if (!status) {
memset(buf, 0, d->vdisk.sect_size);
} else {
memcpy(buf,
d->cluster + (sector & d->sector_idx_mask) * d->vdisk.sect_size,
d->vdisk.sect_size);
}
return KOS_ERROR_SUCCESS;
}
static int
qcow2_write_guest_cluster(struct vdisk_qcow2 *d, struct qcow2_file *qf,
uint64_t cluster_index) {
uint64_t cluster_offset;
size_t l2_entries = d->cluster_size / sizeof(uint64_t);
uint64_t l1_index = (cluster_index) / l2_entries;
uint64_t l2_index = (cluster_index) % l2_entries;
uint64_t l1_entry = qf->l1[l1_index];
uint64_t l2_entry;
d->prev_cluster_index = ~(uint64_t)0;
uint64_t l2_table_offset = l1_entry & L1_ENTRY_OFFSET_MASK;
if (!l2_table_offset) {
l2_table_offset = lseek(qf->fd, 0u, SEEK_END);
qf->l1[l1_index] = l2_table_offset;
uint8_t *zero_cluster = calloc(1, d->cluster_size);
write(qf->fd, zero_cluster, d->cluster_size);
free(zero_cluster);
}
lseek(qf->fd, l2_table_offset + l2_index*sizeof(l2_entry), SEEK_SET);
if (!io_read(qf->fd, &l2_entry, sizeof(l2_entry), d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
return -1;
}
l2_entry = be64(&l2_entry);
cluster_offset = l2_entry & L2_ENTRY_STD_OFFSET;
if (!cluster_offset) {
cluster_offset = lseek(qf->fd, 0u, SEEK_END);
uint64_t cluster_offset_be = BSWAP64(cluster_offset + L2_ENTRY_STATUS);
lseek(qf->fd, l2_table_offset + l2_index*sizeof(l2_entry), SEEK_SET);
write(qf->fd, &cluster_offset_be, sizeof(uint64_t));
}
lseek(qf->fd, cluster_offset, SEEK_SET);
if (!io_write(qf->fd, d->cluster, d->cluster_size, d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't write to image file: %s\n",
strerror(errno));
return -1;
}
return 1;
}
static int
qcow2_write_guest_sector(struct vdisk_qcow2 *d, uint64_t sector, uint8_t *buf) {
uint64_t offset = sector * d->vdisk.sect_size;
uint64_t cluster_index = offset / d->cluster_size;
d->prev_cluster_index = ~(uint64_t)0; // TODO: rename to cached_cluster_idx
int status = 0;
status = qcow2_read_guest_cluster(d, &d->dirty, cluster_index);
if (!status) {
status = qcow2_read_guest_cluster(d, &d->base, cluster_index);
}
if (!status) {
memset(d->cluster, 0, d->cluster_size);
}
memcpy(d->cluster + (sector & d->sector_idx_mask) * d->vdisk.sect_size,
buf, d->vdisk.sect_size);
status = qcow2_write_guest_cluster(d, &d->dirty, cluster_index);
return 1;
}
[[gnu::stdcall]]
void
vdisk_qcow2_close(void *userdata) {
COVERAGE_OFF();
struct vdisk_qcow2 *d = userdata;
if (d->fd) {
close(d->fd);
if (d->base.fname) {
free(d->base.fname);
if (d->base.fd) {
close(d->base.fd);
}
}
if (d->dirty.fname) {
if (d->dirty.fd) {
lseek(d->dirty.fd, d->l1_table_offset, SEEK_SET);
for (uint64_t *x = d->dirty.l1; x < d->dirty.l1 + d->l1_size; x++) {
*x = be64(x);
}
write(d->dirty.fd, d->dirty.l1, d->l1_size * sizeof(uint64_t));
close(d->dirty.fd);
}
unlink(d->dirty.fname);
free(d->dirty.fname);
}
free(d->cluster);
free(d->cmp_cluster);
free(d->l1);
free(d->base.l1);
free(d->dirty.l1);
free(d);
COVERAGE_ON();
}
STDCALL int
[[gnu::stdcall]]
int
vdisk_qcow2_read(void *userdata, void *buffer, off_t startsector,
size_t *numsectors) {
COVERAGE_OFF();
struct vdisk_qcow2 *d = userdata;
int status = KOS_ERROR_SUCCESS;
for (size_t i = 0; i < *numsectors; i++) {
qcow2_read_guest_sector(d, startsector + i, buffer);
status = qcow2_read_guest_sector(d, startsector + i, buffer);
if (status < 0) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
break;
}
buffer = (uint8_t*)buffer + d->vdisk.sect_size;
}
COVERAGE_ON();
return KOS_ERROR_SUCCESS;
return status;
}
STDCALL int
// TODO: change to io_*
static int
qcow2_init_dirty_file(struct vdisk_qcow2 *d) {
int fd;
if ((fd = open(d->dirty.fname, O_RDWR | O_BINARY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {
fprintf(stderr, "[vdisk.qcow2] can't open file '%s': %s\n",
d->dirty.fname, strerror(errno));
}
struct qcow2_header h = {.magic = QCOW2_MAGIC,
.version = BSWAP32(3u),
.back_file_offset = 0u,
.back_file_size = 0u,
.cluster_bits = BSWAP32(d->cluster_bits),
.size = BSWAP64(d->vdisk.sect_cnt
* d->vdisk.sect_size),
.crypt_method = 0u,
.l1_size = BSWAP32(d->l1_size),
.l1_table_offset = BSWAP64(d->l1_table_offset),
};
write(fd, &h, sizeof(h));
d->dirty.l1 = calloc(d->l1_size, sizeof(uint64_t));
off_t aligned = d->l1_table_offset + d->l1_size * sizeof(uint64_t);
aligned += 1u << d->cluster_bits;
aligned &= ~( (1u << d->cluster_bits) - 1);
ftruncate(fd, aligned);
return fd;
}
[[gnu::stdcall]]
int
vdisk_qcow2_write(void *userdata, void *buffer, off_t startsector,
size_t *numsectors) {
COVERAGE_OFF();
struct vdisk_qcow2 *d = userdata;
(void)d;
(void)buffer;
(void)startsector;
(void)numsectors;
fprintf(stderr, "[vdisk.qcow2] writing is not implemented");
if (!d->dirty.fd) {
d->dirty.fd = qcow2_init_dirty_file(d);
}
for (size_t i = 0; i < *numsectors; i++) {
int status = qcow2_write_guest_sector(d, startsector + i, buffer);
if (status < 0) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
}
buffer = (uint8_t*)buffer + d->vdisk.sect_size;
}
COVERAGE_ON();
return KOS_ERROR_UNSUPPORTED_FS;
return KOS_ERROR_SUCCESS;
}
struct vdisk*
@@ -206,6 +358,16 @@ vdisk_init_qcow2(const char *fname, const struct umka_io *io) {
return NULL;
}
d->base.fname = strdup(fname);
d->dirty.fname = malloc(512);
const char *fbasename = strrchr(fname, '/');
if (!fbasename) {
fbasename = fname;
} else {
fbasename++;
}
sprintf(d->dirty.fname, "%s" QCOW2_DIRTY_SUFFIX, fbasename);
d->vdisk.diskfunc = (struct diskfunc) {.strucsize = sizeof(struct diskfunc),
.close = vdisk_qcow2_close,
.read = vdisk_qcow2_read,
@@ -213,21 +375,23 @@ vdisk_init_qcow2(const char *fname, const struct umka_io *io) {
};
d->vdisk.io = io;
d->prev_cluster_index = ~(uint64_t)0;
if ((d->fd = open(fname, O_RDONLY | O_BINARY)) == -1) {
fprintf(stderr, "[vdisk.qcow2] can't open file '%s': %s\n", fname,
strerror(errno));
if ((d->base.fd = open(d->base.fname, O_RDONLY | O_BINARY)) == -1) {
fprintf(stderr, "[vdisk.qcow2] can't open file '%s': %s\n",
d->base.fname, strerror(errno));
vdisk_qcow2_close(d);
return NULL;
}
d->vdisk.sect_size = 512;
if (strstr(fname, "s4096") != NULL || strstr(fname, "s4k") != NULL) {
if ((strstr(d->base.fname, "s4096") != NULL)
|| (strstr(d->base.fname, "s4k") != NULL)) {
d->vdisk.sect_size = 4096;
} else if (strstr(fname, "s2048") != NULL || strstr(fname, "s2k") != NULL) {
} else if ((strstr(d->base.fname, "s2048") != NULL)
|| (strstr(d->base.fname, "s2k") != NULL)) {
d->vdisk.sect_size = 2048;
}
struct qcow2_header header;
if (!io_read(d->fd, &header, sizeof(struct qcow2_header), d->vdisk.io)) {
if (!io_read(d->base.fd, &header, sizeof(struct qcow2_header), d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
vdisk_qcow2_close(d);
@@ -276,8 +440,6 @@ vdisk_init_qcow2(const char *fname, const struct umka_io *io) {
d->l1_size = be32(&header.l1_size);
d->l1_table_offset = be64(&header.l1_table_offset);
d->refcount_table_offset = be64(&header.refcount_table_offset);
d->refcount_table_clusters = be32(&header.refcount_table_clusters);
uint64_t incompatible_features = be64(&header.incompatible_features);
if (incompatible_features) {
@@ -287,15 +449,6 @@ vdisk_init_qcow2(const char *fname, const struct umka_io *io) {
return NULL;
}
d->refcount_order = be32(&header.refcount_order);
if (d->refcount_order < 4 || d->refcount_order > 6) {
fprintf(stderr, "[vdisk.qcow2] bad refcount_order value: %u\n",
d->refcount_order);
vdisk_qcow2_close(d);
return NULL;
}
d->header_length = be32(&header.header_length);
d->cluster = (uint8_t*)malloc(d->cluster_size);
if (!d->cluster) {
fprintf(stderr, "[vdisk.qcow2] can't allocate memory: %s\n",
@@ -312,23 +465,23 @@ vdisk_init_qcow2(const char *fname, const struct umka_io *io) {
return NULL;
}
d->l1 = (uint64_t*)malloc(d->l1_size * sizeof(uint64_t));
if (!d->l1) {
d->base.l1 = (uint64_t*)malloc(d->l1_size * sizeof(uint64_t));
if (!d->base.l1) {
fprintf(stderr, "[vdisk.qcow2] can't allocate memory: %s\n",
strerror(errno));
vdisk_qcow2_close(d);
return NULL;
}
lseek(d->fd, d->l1_table_offset, SEEK_SET);
if (!io_read(d->fd, d->l1, d->l1_size * sizeof(uint64_t), d->vdisk.io)) {
lseek(d->base.fd, d->l1_table_offset, SEEK_SET);
if (!io_read(d->base.fd, d->base.l1, d->l1_size * sizeof(uint64_t), d->vdisk.io)) {
fprintf(stderr, "[vdisk.qcow2] can't read from image file: %s\n",
strerror(errno));
vdisk_qcow2_close(d);
return NULL;
}
for (uint64_t *x = d->l1; x < d->l1 + d->l1_size; x++) {
for (uint64_t *x = d->base.l1; x < d->base.l1 + d->l1_size; x++) {
*x = be64(x);
}
+6 -3
View File
@@ -20,7 +20,8 @@ struct vdisk_raw {
int fd;
};
STDCALL void
[[gnu::stdcall]]
void
vdisk_raw_close(void *userdata) {
COVERAGE_OFF();
struct vdisk_raw *disk = userdata;
@@ -29,7 +30,8 @@ vdisk_raw_close(void *userdata) {
COVERAGE_ON();
}
STDCALL int
[[gnu::stdcall]]
int
vdisk_raw_read(void *userdata, void *buffer, off_t startsector,
size_t *numsectors) {
COVERAGE_OFF();
@@ -41,7 +43,8 @@ vdisk_raw_read(void *userdata, void *buffer, off_t startsector,
return KOS_ERROR_SUCCESS;
}
STDCALL int
[[gnu::stdcall]]
int
vdisk_raw_write(void *userdata, void *buffer, off_t startsector,
size_t *numsectors) {
COVERAGE_OFF();
+6 -3
View File
@@ -16,14 +16,16 @@
#include "umka.h"
#include "vnet.h"
static STDCALL void
[[gnu::stdcall]]
static void
vnet_unload_file(void) {
printf("vnet_unload_file\n");
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL void
[[gnu::stdcall]]
static void
vnet_reset_file(void) {
printf("vnet_reset_file\n");
COVERAGE_ON();
@@ -38,7 +40,8 @@ dump_net_buff(net_buff_t *buf) {
putchar('\n');
}
static STDCALL int
[[gnu::stdcall]]
static int
vnet_transmit_file(net_buff_t *buf) {
struct vnet *net;
__asm__ __inline__ __volatile__ (
+6 -3
View File
@@ -16,13 +16,15 @@
#include "umka.h"
#include "vnet.h"
static STDCALL void
[[gnu::stdcall]]
static void
vnet_unload_null(void) {
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL void
[[gnu::stdcall]]
static void
vnet_reset_null(void) {
COVERAGE_ON();
COVERAGE_OFF();
@@ -38,7 +40,8 @@ dump_net_buff(net_buff_t *buf) {
}
*/
static STDCALL int
[[gnu::stdcall]]
static int
vnet_transmit_null(net_buff_t *buf) {
struct vnet *net;
__asm__ __inline__ __volatile__ (
+4 -3
View File
@@ -14,9 +14,10 @@
char pci_path[UMKA_PATH_MAX] = ".";
__attribute__((stdcall)) uint32_t pci_read(uint32_t bus, uint32_t dev,
uint32_t fun, uint32_t offset,
size_t len) {
[[gnu::stdcall]]
uint32_t pci_read(uint32_t bus, uint32_t dev,
uint32_t fun, uint32_t offset,
size_t len) {
(void)bus;
(void)dev;
(void)fun;