Extend sector numbers to 64 bit, dump hash and bytes of read data.
This commit is contained in:
parent
cfdd6a2820
commit
c4a635322a
4
.gitignore
vendored
4
.gitignore
vendored
@ -13,3 +13,7 @@ mkfilepattern
|
||||
*.img.info
|
||||
t_*.out
|
||||
.gdb_history
|
||||
kolibri.fas
|
||||
kolibri.sym
|
||||
kolibri.lst
|
||||
kolibri.prp
|
||||
|
2
cio.c
2
cio.c
@ -6,7 +6,7 @@
|
||||
|
||||
typedef struct {
|
||||
FILE *file;
|
||||
uint32_t sect_cnt;
|
||||
uint64_t sect_cnt;
|
||||
uint32_t sect_size;
|
||||
} vdisk_t;
|
||||
|
||||
|
178
kofu.c
178
kofu.c
@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
@ -12,38 +13,65 @@
|
||||
#include "kolibri.h"
|
||||
#include "trace.h"
|
||||
|
||||
// http://home.thep.lu.se/~bjorn/crc/
|
||||
/* Simple public domain implementation of the standard CRC32 checksum.
|
||||
* Outputs the checksum for each file given as a command line argument.
|
||||
* Invalid file names and files that cause errors are silently skipped.
|
||||
* The program reads from stdin if it is called with no arguments. */
|
||||
|
||||
uint32_t crc32_for_byte(uint32_t r) {
|
||||
for(int j = 0; j < 8; ++j)
|
||||
r = (r & 1? 0: (uint32_t)0xEDB88320L) ^ r >> 1;
|
||||
return r ^ (uint32_t)0xFF000000L;
|
||||
}
|
||||
|
||||
void crc32(const void *data, size_t n_bytes, uint32_t* crc) {
|
||||
static uint32_t table[0x100];
|
||||
if(!*table)
|
||||
for(size_t i = 0; i < 0x100; ++i)
|
||||
table[i] = crc32_for_byte(i);
|
||||
for(size_t i = 0; i < n_bytes; ++i)
|
||||
*crc = table[(uint8_t)*crc ^ ((uint8_t*)data)[i]] ^ *crc >> 8;
|
||||
}
|
||||
|
||||
#define FGETS_BUF_LEN 4096
|
||||
#define MAX_COMMAND_ARGS 42
|
||||
#define PRINT_BYTES_PER_LINE 32
|
||||
#define MAX_DIRENTS_TO_READ 100
|
||||
#define MAX_BYTES_TO_READ 1024
|
||||
#define MAX_BYTES_TO_READ (16*1024)
|
||||
|
||||
char cmd_buf[FGETS_BUF_LEN];
|
||||
bool is_tty;
|
||||
int cmd_num = 0;
|
||||
bool trace = false;
|
||||
|
||||
bool parse_uintmax(const char *str, uintmax_t *res) {
|
||||
char *endptr;
|
||||
*res = strtoumax(str, &endptr, 0);
|
||||
bool ok = (str != endptr) && (*endptr == '\0');
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool parse_uint32(const char *str, uint32_t *res) {
|
||||
uintmax_t x;
|
||||
if (parse_uintmax(str, &x) && x <= UINT32_MAX) {
|
||||
*res = x;
|
||||
return true;
|
||||
} else {
|
||||
perror("invalid number");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool parse_uint64(const char *str, uint64_t *res) {
|
||||
uintmax_t x;
|
||||
if (parse_uintmax(str, &x) && x <= UINT64_MAX) {
|
||||
*res = x;
|
||||
return true;
|
||||
} else {
|
||||
perror("invalid number");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void print_bytes(uint8_t *x, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("%2.2x", x[i]);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void print_hash(uint8_t *x, size_t len) {
|
||||
hash_context ctx;
|
||||
hash_oneshot(&ctx, x, len);
|
||||
for (size_t i = 0; i < HASH_SIZE; i++) {
|
||||
printf("%2.2x", ctx.hash[i]);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void prompt() {
|
||||
printf("#%d> ", cmd_num);
|
||||
fflush(stdout);
|
||||
@ -81,8 +109,8 @@ void kofu_disk_del(int argc, const char **argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
void ls_range(struct f70s1arg *f70) {
|
||||
f70ret r;
|
||||
void ls_range(f70s1arg_t *f70) {
|
||||
f70ret_t r;
|
||||
uint32_t requested = f70->size;
|
||||
if (f70->size > MAX_DIRENTS_TO_READ) {
|
||||
f70->size = MAX_DIRENTS_TO_READ;
|
||||
@ -94,7 +122,7 @@ void ls_range(struct f70s1arg *f70) {
|
||||
kos_fuse_lfn(f70, &r);
|
||||
f70->offset += f70->size;
|
||||
printf("status = %d, count = %d\n", r.status, r.count);
|
||||
struct f70s1ret *dir = f70->buf;
|
||||
f70s1info_t *dir = f70->buf;
|
||||
assert((r.status == F70_SUCCESS && r.count == f70->size) ||
|
||||
(r.status == F70_END_OF_FILE && r.count < f70->size)
|
||||
);
|
||||
@ -114,15 +142,15 @@ void ls_range(struct f70s1arg *f70) {
|
||||
}
|
||||
}
|
||||
|
||||
void ls_all(struct f70s1arg *f70) {
|
||||
f70ret r;
|
||||
void ls_all(f70s1arg_t *f70) {
|
||||
f70ret_t r;
|
||||
while (true) {
|
||||
kos_fuse_lfn(f70, &r);
|
||||
printf("status = %d, count = %d\n", r.status, r.count);
|
||||
if (r.status != F70_SUCCESS && r.status != F70_END_OF_FILE) {
|
||||
abort();
|
||||
}
|
||||
struct f70s1ret *dir = f70->buf;
|
||||
f70s1info_t *dir = f70->buf;
|
||||
f70->offset += dir->cnt;
|
||||
assert((r.status == F70_SUCCESS && r.count == f70->size) ||
|
||||
(r.status == F70_END_OF_FILE && r.count < f70->size)
|
||||
@ -139,8 +167,8 @@ void ls_all(struct f70s1arg *f70) {
|
||||
|
||||
void kofu_ls(int argc, const char **argv) {
|
||||
(void)argc;
|
||||
struct f70s1ret *dir = (struct f70s1ret*)malloc(sizeof(struct f70s1ret) + sizeof(struct bdfe) * MAX_DIRENTS_TO_READ);
|
||||
struct f70s1arg f70 = {1, 0, CP866, MAX_DIRENTS_TO_READ, dir, 0, argv[1]};
|
||||
f70s1info_t *dir = (f70s1info_t*)malloc(sizeof(f70s1info_t) + sizeof(bdfe_t) * MAX_DIRENTS_TO_READ);
|
||||
f70s1arg_t f70 = {1, 0, CP866, MAX_DIRENTS_TO_READ, dir, 0, argv[1]};
|
||||
if (argv[2]) {
|
||||
sscanf(argv[2], "%"SCNu32, &f70.size);
|
||||
if (argv[3]) {
|
||||
@ -156,17 +184,21 @@ void kofu_ls(int argc, const char **argv) {
|
||||
|
||||
void kofu_stat(int argc, const char **argv) {
|
||||
(void)argc;
|
||||
f70ret r;
|
||||
struct bdfe file;
|
||||
struct f70s5arg f70 = {5, 0, 0, 0, &file, 0, argv[1]};
|
||||
f70s5arg_t f70 = {.sf = 5, .flags = 0, .zero = 0};
|
||||
f70ret_t r;
|
||||
bdfe_t file;
|
||||
f70.buf = &file;
|
||||
f70.path = argv[1];
|
||||
kos_fuse_lfn(&f70, &r);
|
||||
printf("attr: 0x%2.2x\n", file.attr);
|
||||
printf("size: %llu\n", file.size);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
void read_range(struct f70s0arg *f70) {
|
||||
f70ret r;
|
||||
hash_context ctx;
|
||||
uint32_t requested = f70->size;
|
||||
if (f70->size > MAX_BYTES_TO_READ) {
|
||||
f70->size = MAX_BYTES_TO_READ;
|
||||
@ -181,13 +213,9 @@ void read_range(struct f70s0arg *f70) {
|
||||
assert((r.status == F70_SUCCESS && r.count == f70->size) ||
|
||||
(r.status == F70_END_OF_FILE && r.count < f70->size)
|
||||
);
|
||||
for (size_t i = 0; i < r.count; i++) {
|
||||
if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("%2.2x", ((uint8_t*)f70->buf)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
print_bytes(f70->buf, r.count);
|
||||
hash_oneshot(&ctx, f70->buf, r.count);
|
||||
print_hash(ctx.hash, HASH_SIZE);
|
||||
if (r.status == F70_END_OF_FILE) {
|
||||
break;
|
||||
}
|
||||
@ -203,37 +231,58 @@ void read_all(struct f70s0arg *f70) {
|
||||
assert((r.status == F70_SUCCESS && r.count == f70->size) ||
|
||||
(r.status == F70_END_OF_FILE && r.count < f70->size)
|
||||
);
|
||||
for (size_t i = 0; i < r.count; i++) {
|
||||
if (i % PRINT_BYTES_PER_LINE == 0 && i != 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf("%2.2x", ((uint8_t*)f70->buf)[i]);
|
||||
if () {
|
||||
print_bytes(f70->buf, r.count);
|
||||
}
|
||||
if () {
|
||||
hash_context ctx;
|
||||
hash_oneshot(&ctx, f70->buf, r.count);
|
||||
print_hash(ctx.hash, HASH_SIZE);
|
||||
}
|
||||
printf("\n");
|
||||
if (r.status == F70_END_OF_FILE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void kofu_read(int argc, const char **argv) {
|
||||
(void)argc;
|
||||
uint8_t *buf = (uint8_t*)malloc(MAX_BYTES_TO_READ);
|
||||
struct f70s0arg f70 = {0, 0, 0, MAX_BYTES_TO_READ, buf, 0, argv[1]};
|
||||
// optind = 1;
|
||||
// while ((opt = getopt(argc, argv, "fcshd:")) != -1) {
|
||||
// switch (opt) {
|
||||
// case
|
||||
if (argv[2]) {
|
||||
sscanf(argv[2], "%"SCNu32, &f70.size);
|
||||
if (argv[3]) {
|
||||
sscanf(argv[3], "%"SCNu32, &f70.offset_lo);
|
||||
}
|
||||
read_range(&f70);
|
||||
} else {
|
||||
read_all(&f70);
|
||||
f70s0arg_t f70 = {.sf = 0, .zero = 0};
|
||||
f70ret_t r;
|
||||
bool dump_bytes = false, dump_hash = false;
|
||||
if (argc < 4) {
|
||||
printf("usage: %s <offset> <length> [-b] [-h]\n", argv[0]);
|
||||
return;
|
||||
}
|
||||
free(buf);
|
||||
int opt = 1;
|
||||
f70.path = argv[opt++];
|
||||
if ((opt >= argc) || !parse_uint64(argv[opt++], &f70.offset))
|
||||
return;
|
||||
if ((opt >= argc) || !parse_uint32(argv[opt++], &f70.count))
|
||||
return;
|
||||
for (; opt < argc; opt++) {
|
||||
if (!strcmp(argv[opt], "-b")) {
|
||||
dump_bytes = true;
|
||||
} else if (!strcmp(argv[opt], "-h")) {
|
||||
dump_hash = true;
|
||||
} else {
|
||||
printf("invalid option: '%s'\n", argv[opt]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
f70.buf = (uint8_t*)malloc(f70.count);
|
||||
|
||||
kos_fuse_lfn(&f70, &r);
|
||||
assert((r.status == F70_SUCCESS && r.count == f70.count) ||
|
||||
(r.status == F70_END_OF_FILE && r.count < f70.count));
|
||||
|
||||
if (dump_bytes)
|
||||
print_bytes(f70.buf, r.count);
|
||||
if (dump_hash)
|
||||
print_hash(f70.buf, r.count);
|
||||
|
||||
free(f70.buf);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -251,13 +300,6 @@ struct func_table funcs[] = {
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
void crc() {
|
||||
uint8_t data[] = {1,2,3,4};
|
||||
uint32_t x = 0;
|
||||
crc32(data, 4, &x);
|
||||
printf("crc=%"PRIx32"\n", x);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
18
kofuse.c
18
kofuse.c
@ -35,7 +35,7 @@
|
||||
|
||||
#define DIRENTS_TO_READ 100
|
||||
|
||||
static void bdfe_to_stat(struct bdfe *kf, struct stat *st) {
|
||||
static void bdfe_to_stat(bdfe_t *kf, struct stat *st) {
|
||||
if (kf->attr & KF_FOLDER) {
|
||||
st->st_mode = S_IFDIR | 0755;
|
||||
st->st_nlink = 2;
|
||||
@ -62,9 +62,9 @@ static int kofuse_getattr(const char *path, struct stat *stbuf,
|
||||
int res = 0;
|
||||
|
||||
|
||||
struct bdfe file;
|
||||
struct f70s5arg f70 = {5, 0, 0, 0, &file, 0, path};
|
||||
f70ret r;
|
||||
bdfe_t file;
|
||||
f70s5arg_t f70 = {.sf = 5, .flags = 0, .buf = &file, .zero = 0, .path = path};
|
||||
f70ret_t r;
|
||||
kos_fuse_lfn(&f70, &r);
|
||||
|
||||
bdfe_to_stat(&file, stbuf);
|
||||
@ -79,9 +79,9 @@ static int kofuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||
(void) fi;
|
||||
(void) flags;
|
||||
|
||||
struct f70s1ret *dir = (struct f70s1ret*)malloc(sizeof(struct f70s1ret) + sizeof(struct bdfe) * DIRENTS_TO_READ);
|
||||
struct f70s1arg f70 = {1, 0, CP866, DIRENTS_TO_READ, dir, 0, path};
|
||||
f70ret r;
|
||||
f70s1info_t *dir = (f70s1info_t*)malloc(sizeof(f70s1info_t) + sizeof(bdfe_t) * DIRENTS_TO_READ);
|
||||
f70s1arg_t f70 = {1, 0, CP866, DIRENTS_TO_READ, dir, 0, path};
|
||||
f70ret_t r;
|
||||
kos_fuse_lfn(&f70, &r);
|
||||
for (size_t i = 0; i < dir->cnt; i++) {
|
||||
filler(buf, dir->bdfes[i].name, NULL, 0, 0);
|
||||
@ -105,8 +105,8 @@ static int kofuse_read(const char *path, char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi) {
|
||||
(void) fi;
|
||||
|
||||
struct f70s5arg f70 = {0, offset, offset >> 32, size, buf, 0, path};
|
||||
f70ret r;
|
||||
f70s0arg_t f70 = {.sf = 0, .offset = offset, .count = size, .buf = buf, .zero = 0, .path = path};
|
||||
f70ret_t r;
|
||||
kos_fuse_lfn(&f70, &r);
|
||||
return size;
|
||||
}
|
||||
|
15
kolibri.asm
15
kolibri.asm
@ -30,12 +30,20 @@ include 'blkdev/disk_cache.inc'
|
||||
include 'fs/fs_lfn.inc'
|
||||
include 'crc.inc'
|
||||
|
||||
include 'sha3.asm'
|
||||
|
||||
struct VDISK
|
||||
File dd ?
|
||||
SectCnt dd ? ; FIXME: dq
|
||||
SectCnt DQ ?
|
||||
SectSize dd ? ; sector size
|
||||
ends
|
||||
|
||||
public sha3_256_oneshot as 'hash_oneshot'
|
||||
proc sha3_256_oneshot c uses ebx esi edi ebp, _ctx, _data, _len
|
||||
stdcall sha3_256.oneshot, [_ctx], [_data], [_len]
|
||||
ret
|
||||
endp
|
||||
|
||||
; TODO: move to trace_lbr
|
||||
public set_eflags_tf
|
||||
set_eflags_tf:
|
||||
@ -206,9 +214,10 @@ proc vdisk_querymedia stdcall uses ebx esi edi ebp, vdisk, mediainfo
|
||||
mov [ecx + DISKMEDIAINFO.Flags], 0
|
||||
mov eax, [edx + VDISK.SectSize]
|
||||
mov [ecx + DISKMEDIAINFO.SectorSize], eax
|
||||
mov eax, [edx + VDISK.SectCnt]
|
||||
mov eax, [edx + VDISK.SectCnt.lo]
|
||||
mov dword [ecx + DISKMEDIAINFO.Capacity + 0], eax
|
||||
mov dword [ecx + DISKMEDIAINFO.Capacity + 4], 0
|
||||
mov eax, [edx + VDISK.SectCnt.hi]
|
||||
mov dword [ecx + DISKMEDIAINFO.Capacity + 4], eax
|
||||
|
||||
movi eax, DISK_STATUS_OK
|
||||
ret
|
||||
|
51
kolibri.h
51
kolibri.h
@ -2,8 +2,9 @@
|
||||
#define KOLIBRI_H_INCLUDED
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum encoding {
|
||||
enum {
|
||||
DEFAULT,
|
||||
CP866,
|
||||
UTF16,
|
||||
@ -27,11 +28,6 @@ typedef enum {
|
||||
} f70status;
|
||||
|
||||
typedef struct {
|
||||
uint32_t status;
|
||||
uint32_t count;
|
||||
} f70ret;
|
||||
|
||||
struct bdfe {
|
||||
uint32_t attr;
|
||||
uint32_t enc;
|
||||
uint32_t ctime;
|
||||
@ -42,19 +38,23 @@ struct bdfe {
|
||||
uint32_t mdate;
|
||||
uint64_t size;
|
||||
char name[264];
|
||||
};
|
||||
} bdfe_t;
|
||||
|
||||
struct f70s0arg {
|
||||
typedef struct {
|
||||
uint32_t status;
|
||||
uint32_t count;
|
||||
} f70ret_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sf;
|
||||
uint32_t offset_lo;
|
||||
uint32_t offset_hi;
|
||||
uint32_t size;
|
||||
uint64_t offset;
|
||||
uint32_t count;
|
||||
void *buf;
|
||||
uint8_t zero;
|
||||
const char *path;
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed)) f70s0arg_t;
|
||||
|
||||
struct f70s1arg {
|
||||
typedef struct {
|
||||
uint32_t sf;
|
||||
uint32_t offset;
|
||||
uint32_t encoding;
|
||||
@ -62,17 +62,17 @@ struct f70s1arg {
|
||||
void *buf;
|
||||
uint8_t zero;
|
||||
const char *path;
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed)) f70s1arg_t;
|
||||
|
||||
struct f70s1ret {
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
uint32_t cnt;
|
||||
uint32_t total_cnt;
|
||||
uint32_t reserved[5];
|
||||
struct bdfe bdfes[0];
|
||||
};
|
||||
bdfe_t bdfes[0];
|
||||
} f70s1info_t;
|
||||
|
||||
struct f70s5arg {
|
||||
typedef struct {
|
||||
uint32_t sf;
|
||||
uint32_t reserved1;
|
||||
uint32_t flags;
|
||||
@ -80,7 +80,7 @@ struct f70s5arg {
|
||||
void *buf;
|
||||
uint8_t zero;
|
||||
const char *path;
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed)) f70s5arg_t;
|
||||
|
||||
#define KF_READONLY 0x01
|
||||
#define KF_HIDDEN 0x02
|
||||
@ -88,14 +88,25 @@ struct f70s5arg {
|
||||
#define KF_LABEL 0x08
|
||||
#define KF_FOLDER 0x10
|
||||
|
||||
#define HASH_SIZE 32
|
||||
typedef struct {
|
||||
uint8_t hash[HASH_SIZE];
|
||||
uint8_t opaque[1024-HASH_SIZE];
|
||||
} hash_context;
|
||||
|
||||
uint32_t kos_time_to_epoch(uint32_t *time);
|
||||
void *kos_fuse_init(int fd, uint32_t sect_cnt, uint32_t sect_sz);
|
||||
void kos_fuse_lfn(void *f70arg, f70ret *r);
|
||||
void kos_fuse_lfn(void *f70sXarg, f70ret_t *r);
|
||||
|
||||
void kos_init(void);
|
||||
void *kos_disk_add(const char *file_name, const char *disk_name);
|
||||
int kos_disk_del(const char *name);
|
||||
|
||||
//void hash_init(void *ctx);
|
||||
//void hash_update(void *ctx, void *data, size_t len);
|
||||
//void hash_final(void *ctx);
|
||||
void hash_oneshot(void *ctx, void *data, size_t len);
|
||||
|
||||
void set_eflags_tf(int x);
|
||||
void coverage_begin(void);
|
||||
void coverage_end(void);
|
||||
|
4
makefile
4
makefile
@ -1,6 +1,6 @@
|
||||
FASM=fasm
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -Wextra -g -O0 -D_FILE_OFFSET_BITS=64
|
||||
CFLAGS=-Wall -Wextra -g -O0 -D_FILE_OFFSET_BITS=64 -Wno-address-of-packed-member
|
||||
CFLAGS_32=-m32
|
||||
LDFLAGS=
|
||||
LDFLAGS_32=-m32
|
||||
@ -14,7 +14,7 @@ kofuse: kofuse.o kolibri.o cio.o
|
||||
$(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs`
|
||||
|
||||
kolibri.o kolibri.fas: kolibri.asm kolibri.h
|
||||
INCLUDE="$(KOLIBRI_TRUNK)" $(FASM) $< $@ -s kolibri.fas
|
||||
INCLUDE="$(KOLIBRI_TRUNK);$(LIBCRASH_X86)" $(FASM) $< $@ -s kolibri.fas
|
||||
|
||||
kolibri.sym: kolibri.fas
|
||||
symbols kolibri.fas kolibri.sym
|
||||
|
Loading…
Reference in New Issue
Block a user