diff --git a/.gitignore b/.gitignore index 5aa2bac..6755ae5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,7 @@ *.o kofu kofuse +mkdirrange *.img -*.xz +*.img.xz +*.img.info diff --git a/README b/README index af21569..b1b58cf 100644 --- a/README +++ b/README @@ -11,6 +11,9 @@ Kofu is Kolibri Filesystem in Userspace. +BUILD +KOLIBRI_TRUNK + Architecture diff --git a/kocdecl.h b/kocdecl.h deleted file mode 100644 index de273a1..0000000 --- a/kocdecl.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef KOS_H_INCLUDED -#define KOS_H_INCLUDED - -#include -#include - -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; - uint64_t size; - char name[264]; -}; - -#define KF_READONLY 0x01 -#define KF_HIDDEN 0x02 -#define KF_SYSTEM 0x04 -#define KF_LABEL 0x08 -#define KF_FOLDER 0x10 - -uint32_t kos_time_to_epoch(uint32_t *time); -void *kos_fuse_init(int fd); -uint8_t *kos_fuse_readdir(const char *path, off_t offset); -void *kos_fuse_getattr(const char *path); -long *kos_fuse_read(const char *path, char *buf, size_t size, off_t offset); - -#endif diff --git a/kofu.c b/kofu.c index 6c8deb2..6c21bdf 100644 --- a/kofu.c +++ b/kofu.c @@ -8,10 +8,11 @@ #include #include #include -#include "kocdecl.h" +#include "kolibri.h" #define FGETS_BUF_LEN 4096 #define MAX_COMMAND_ARGS 42 +#define DIRENTS_TO_READ 100 char cmd_buf[FGETS_BUF_LEN]; bool is_tty; @@ -37,31 +38,45 @@ char **split_args(char *s) { } void kofu_ls(char **arg) { - void *header = kos_fuse_readdir(arg[1], 0); - uint32_t file_cnt = ((uint32_t*)header)[1]; - printf("file_cnt: %u\n", file_cnt); - struct bdfe *kf = header + 0x20; - for (; file_cnt > 0; file_cnt--) { - printf("%s\n", kf->name); - kf++; + 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, arg[1]}; + while (true) { + int status = kos_fuse_lfn(&f70); + printf("status = %d\n", status); + if (status != 0 && status != 6) { + abort(); + } + f70.offset += dir->cnt; + + for (size_t i = 0; i < dir->cnt; i++) { + printf("%s\n", dir->bdfes[i].name); + } + + if (status == 6) { + break; + } } + free(dir); return; } void kofu_stat(char **arg) { - struct bdfe *kf = kos_fuse_getattr(arg[1]); - printf("attr: 0x%2.2x\n", kf->attr); - printf("size: %llu\n", kf->size); + struct bdfe file; + struct f70s5arg f70 = {5, 0, 0, 0, &file, 0, arg[1]}; + kos_fuse_lfn(&f70); + printf("attr: 0x%2.2x\n", file.attr); + printf("size: %llu\n", file.size); return; } void kofu_read(char **arg) { size_t size; - size_t offset; + off_t offset; sscanf(arg[2], "%zu", &size); - sscanf(arg[3], "%zu", &offset); - char *buf = (char*)malloc(size + 4096); - kos_fuse_read(arg[1], buf, size, offset); + sscanf(arg[3], "%llu", &offset); + uint8_t *buf = (uint8_t*)malloc(size); + struct f70s5arg f70 = {0, offset, offset >> 32, size, buf, 0, arg[1]}; + kos_fuse_lfn(&f70); for (size_t i = 0; i < size; i++) { if (i % 32 == 0 && i != 0) { printf("\n"); @@ -69,6 +84,7 @@ void kofu_read(char **arg) { printf("%2.2x", buf[i]); } printf("\n"); + free(buf); return; } @@ -92,14 +108,13 @@ int main(int argc, char **argv) { is_tty = isatty(STDIN_FILENO); int fd = open(argv[1], O_RDONLY); - if (!kos_fuse_init(fd)) { + struct stat st; + fstat(fd, &st); + if (!kos_fuse_init(fd, st.st_size / 512)) { exit(1); } -//msg_few_args db 'usage: xfskos image [offset]',0x0a //msg_file_not_found db 'file not found: ' -//msg_unknown_command db 'unknown command',0x0a -//msg_not_xfs_partition db 'not xfs partition',0x0a while(next_line()) { if (!is_tty) { prompt(); diff --git a/kofuse.c b/kofuse.c index 2b40dfe..2e4aaaa 100644 --- a/kofuse.c +++ b/kofuse.c @@ -9,7 +9,9 @@ #include #include #include -#include "kocdecl.h" +#include "kolibri.h" + +#define DIRENTS_TO_READ 100 static void bdfe_to_stat(struct bdfe *kf, struct stat *st) { if (kf->attr & KF_FOLDER) { @@ -20,9 +22,9 @@ static void bdfe_to_stat(struct bdfe *kf, struct stat *st) { st->st_nlink = 1; st->st_size = kf->size; } - st->st_atim = (struct timespec){kos_time_to_epoch(&(kf->atime)), 0}; - st->st_mtim = (struct timespec){kos_time_to_epoch(&(kf->mtime)), 0}; - st->st_ctim = (struct timespec){kos_time_to_epoch(&(kf->ctime)), 0}; + st->st_atim = (struct timespec){ .tv_sec = kos_time_to_epoch(&(kf->atime)) }; + st->st_mtim = (struct timespec){ .tv_sec = kos_time_to_epoch(&(kf->mtime)) }; + st->st_ctim = (struct timespec){ .tv_sec = kos_time_to_epoch(&(kf->ctime)) }; } static void *kofuse_init(struct fuse_conn_info *conn, @@ -34,32 +36,34 @@ static void *kofuse_init(struct fuse_conn_info *conn, static int kofuse_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) { - (void) fi; - int res = 0; + (void) fi; + int res = 0; - struct bdfe *kf = kos_fuse_getattr(path); - bdfe_to_stat(kf, stbuf); -// res = -ENOENT; - return res; + + struct bdfe file; + struct f70s5arg f70 = {5, 0, 0, 0, &file, 0, path}; + kos_fuse_lfn(&f70); + + bdfe_to_stat(&file, stbuf); +// res = -ENOENT; + return res; } static int kofuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi, enum fuse_readdir_flags flags) { - (void) offset; - (void) fi; - (void) flags; + (void) offset; + (void) fi; + (void) flags; - void *header = kos_fuse_readdir(path, offset); - - uint32_t i = *(uint32_t*)(header + 4); - struct bdfe *kf = header + 0x20; - for(; i>0; i--) { - filler(buf, kf->name, NULL, 0, 0); - kf++; - } - - return 0; + 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}; + kos_fuse_lfn(&f70); + for (size_t i = 0; i < dir->cnt; i++) { + filler(buf, dir->bdfes[i].name, NULL, 0, 0); + } + free(dir); + return 0; } static int kofuse_open(const char *path, struct fuse_file_info *fi) { @@ -75,10 +79,11 @@ static int kofuse_open(const char *path, struct fuse_file_info *fi) { static int kofuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - (void) fi; + (void) fi; - kos_fuse_read(path, buf, size, offset); - return size; + struct f70s5arg f70 = {0, offset, offset >> 32, size, buf, 0, path}; + kos_fuse_lfn(&f70); + return size; } static struct fuse_operations kofuse_oper = { @@ -95,6 +100,8 @@ int main(int argc, char *argv[]) { exit(1); } int fd = open(argv[2], O_RDONLY); - kos_fuse_init(fd); + struct stat st; + fstat(fd, &st); + kos_fuse_init(fd, st.st_size / 512); return fuse_main(argc-1, argv, &kofuse_oper, NULL); } diff --git a/kocdecl.asm b/kolibri.asm similarity index 56% rename from kocdecl.asm rename to kolibri.asm index 0798a81..f85c4d8 100644 --- a/kocdecl.asm +++ b/kolibri.asm @@ -14,21 +14,6 @@ include 'blkdev/disk_cache.inc' include 'fs/fs_lfn.inc' include 'crc.inc' -struct FS_FUNCTIONS - Free dd ? - Size dd ? - ReadFile dd ? - ReadFolder dd ? - CreateFile dd ? - WriteFile dd ? - SetFileEnd dd ? - GetFileInfo dd ? - SetFileInfo dd ? - Run dd ? - Delete dd ? - CreateFolder dd ? -ends - purge section,mov,add,sub section '.text' executable align 16 @@ -46,7 +31,7 @@ kos_time_to_epoch: ret -;void *kos_fuse_init(int fd); +;void *kos_fuse_init(int fd, uint32_t sect_cnt); public kos_fuse_init kos_fuse_init: push ebx esi edi ebp @@ -54,105 +39,29 @@ kos_fuse_init: mov [pg_data.pages_free], (128*1024*1024)/0x1000 mov eax, [esp + 0x14] - mov [fd], eax - - mov [file_disk.Size], 65536 + mov [file_disk.fd], eax + mov eax, [esp + 0x18] + mov [file_disk.Sectors], eax + mov [file_disk.Logical], 512 stdcall disk_add, disk_functions, disk_name, file_disk, DISK_NO_INSERT_NOTIFICATION mov [disk], eax stdcall disk_media_changed, [disk], 1 mov eax, [disk] - cmp [eax + DISK.NumPartitions], 0 - jnz .done - mov eax, SYS_WRITE - mov ebx, STDOUT - mov ecx, msg_no_partition - mov edx, msg_no_partition.size - int 0x80 - xor eax, eax - .done: - mov [fs_struct], eax + mov eax, [eax + DISK.NumPartitions] pop ebp edi esi ebx ret -;char *kos_fuse_readdir(const char *path, off_t offset) -public kos_fuse_readdir -kos_fuse_readdir: -;DEBUGF 1, '#kos_fuse_readdir\n' - push ebx esi edi ebp - - mov edx, sf70_params - mov dword[edx + 0x00], 1 - mov eax, [esp + 0x18] ; offset - mov [edx + 0x04], eax - mov dword[edx + 0x08], 1 ; cp866 - mov dword[edx + 0x0c], 100 - mov dword[edx + 0x10], sf70_buffer - mov eax, [esp + 0x14] ; path - mov byte[edx + 0x14], 0 - mov [edx + 0x15], eax - - mov ebx, sf70_params +public kos_fuse_lfn +kos_fuse_lfn: + push ebx + mov ebx, [esp + 8] pushad ; file_system_lfn writes here call file_system_lfn popad - pop ebp edi esi ebx - mov eax, sf70_buffer - ret - - -;void *kos_fuse_getattr(const char *path) -public kos_fuse_getattr -kos_fuse_getattr: -;DEBUGF 1, '#kos_fuse_getattr\n' - push ebx esi edi ebp - - mov edx, sf70_params - mov dword[edx + 0x00], 5 - mov dword[edx + 0x04], 0 - mov dword[edx + 0x08], 0 - mov dword[edx + 0x0c], 0 - mov dword[edx + 0x10], sf70_buffer - mov eax, [esp + 0x14] ; path - mov byte[edx + 0x14], 0 - mov [edx + 0x15], eax - - mov ebx, sf70_params - pushad ; file_system_lfn writes here - call file_system_lfn - popad - pop ebp edi esi ebx - mov eax, sf70_buffer - ret - - -;long *kos_fuse_read(const char *path, char *buf, size_t size, off_t offset) -public kos_fuse_read -kos_fuse_read: - push ebx esi edi ebp - - mov edx, sf70_params - mov dword[edx + 0x00], 0 - mov eax, [esp + 0x20] ; offset lo - mov dword[edx + 0x04], eax - mov dword[edx + 0x08], 0 ; offset hi - mov eax, [esp + 0x1c] ; size - mov dword[edx + 0x0c], eax - mov eax, [esp + 0x18] ; buf - mov dword[edx + 0x10], eax - mov eax, [esp + 0x14] ; path - mov byte[edx + 0x14], 0 - mov [edx + 0x15], eax - - mov ebx, sf70_params - pushad ; file_system_lfn writes here - call file_system_lfn - popad - - pop ebp edi esi ebx - mov eax, 0 + pop ebx ret @@ -161,20 +70,22 @@ proc disk_read stdcall, userdata, buffer, startsector:qword, numsectors mov eax, dword[startsector + 0] ; sector lo mov edx, dword[startsector + 4] ; sector hi imul ecx, eax, 512 - mov eax, SYS_LSEEK - mov ebx, [fd] + mov eax, [userdata] + mov ebx, [eax + FILE_DISK.fd] mov edx, SEEK_SET + mov eax, SYS_LSEEK int 0x80 ;DEBUGF 1, "lseek: %x\n", eax popad pushad - mov eax, SYS_READ - mov ebx, [fd] + mov eax, [userdata] + mov ebx, [eax + FILE_DISK.fd] mov ecx, [buffer] mov edx, [numsectors] mov edx, [edx] - imul edx, 512 + imul edx, [eax + FILE_DISK.Logical] + mov eax, SYS_READ int 0x80 ;DEBUGF 1, "read: %d\n", eax popad @@ -185,22 +96,26 @@ endp proc disk_write stdcall, userdata, buffer, startsector:qword, numsectors -ud2 pushad + mov eax, dword[startsector + 0] ; sector lo + mov edx, dword[startsector + 4] ; sector hi imul ecx, eax, 512 - add ecx, 2048*512 - mov eax, SYS_LSEEK - mov ebx, [fd] + mov eax, [userdata] + mov ebx, [eax + FILE_DISK.fd] mov edx, SEEK_SET + mov eax, SYS_LSEEK int 0x80 ;DEBUGF 1, "lseek: %x\n", eax popad pushad + mov eax, [userdata] + mov ebx, [eax + FILE_DISK.fd] + mov ecx, [buffer] + mov edx, [numsectors] + mov edx, [edx] + imul edx, [eax + FILE_DISK.Logical] mov eax, SYS_WRITE - mov ecx, ebx - mov ebx, [fd] - mov edx, 512 int 0x80 ;DEBUGF 1, "write: %d\n", eax popad @@ -213,10 +128,11 @@ endp ; int querymedia(void* userdata, DISKMEDIAINFO* info); proc disk_querymedia stdcall, hd_data, mediainfo mov ecx, [mediainfo] + mov edx, [hd_data] mov [ecx + DISKMEDIAINFO.Flags], 0 - mov [ecx + DISKMEDIAINFO.SectorSize], 512 - mov eax, [hd_data] - mov eax, dword[eax + FILE_DISK.Size + 0] + mov eax, [edx + FILE_DISK.Logical] + mov [ecx + DISKMEDIAINFO.SectorSize], eax + mov eax, [edx + FILE_DISK.Sectors] mov dword [ecx + DISKMEDIAINFO.Capacity], eax mov dword [ecx + DISKMEDIAINFO.Capacity + 4], 0 @@ -252,21 +168,15 @@ proc alloc_pages _cnt endp - - free: ret + proc kernel_free blah ret endp -mutex_init: -mutex_lock: -mutex_unlock: - ret - put_board: pushad mov eax, SYS_WRITE @@ -325,16 +235,12 @@ prevent_medium_removal: Read_TOC: commit_pages: release_pages: +fs_execute: +mutex_init: +mutex_lock: +mutex_unlock: ret -proc fs_execute -; edx = flags -; ecx -> cmdline -; ebx -> absolute file path -; eax = string length - ret -endp - section '.data' writeable align 16 include_debug_strings @@ -350,16 +256,15 @@ disk_functions: disk_functions_end: struct FILE_DISK - Size dd ? + fd dd ? + Sectors dd ? + Logical dd ? ; sector size ends -file_disk FILE_DISK - alloc_pos dd alloc_base -sf70_params rd 6 -msg_no_partition db 'no partition detected',0x0a -msg_no_partition.size = $ - msg_no_partition disk_name db 'hd0',0 +IncludeIGlobals +; crap current_slot dd ? pg_data PG_DATA ide_channel1_mutex MUTEX @@ -370,16 +275,14 @@ ide_channel5_mutex MUTEX ide_channel6_mutex MUTEX ide_channel7_mutex MUTEX ide_channel8_mutex MUTEX -IncludeIGlobals section '.bss' writeable align 16 -fd rd 1 +file_disk FILE_DISK disk dd ? -alloc_base rb 32*1024*1024 -fs_struct rd 1 -sf70_buffer rb 16*1024*1024 +alloc_base rb 8*1024*1024 IncludeUGlobals +; crap DiskNumber db ? ChannelNumber db ? DevErrorCode dd ? @@ -387,4 +290,4 @@ CDSectorAddress dd ? CDDataBuf_pointer dd ? DRIVE_DATA: rb 0x4000 cdpos dd ? -cd_appl_data rd 1 +cd_appl_data dd ? diff --git a/kolibri.h b/kolibri.h new file mode 100644 index 0000000..94a76e9 --- /dev/null +++ b/kolibri.h @@ -0,0 +1,74 @@ +#ifndef KOLIBRI_H_INCLUDED +#define KOLIBRI_H_INCLUDED + +#include + +enum encoding { + DEFAULT, + CP866, + UTF16, + UTF8, +}; + +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; + uint64_t size; + char name[264]; +}; + +struct f70s0arg { + uint32_t sf; + uint32_t offset_lo; + uint32_t offset_hi; + uint32_t size; + void *buf; + uint8_t zero; + const char *path; +} __attribute__((packed)); + +struct f70s1arg { + uint32_t sf; + uint32_t offset; + uint32_t encoding; + uint32_t size; + void *buf; + uint8_t zero; + const char *path; +} __attribute__((packed)); + +struct f70s1ret { + uint32_t version; + uint32_t cnt; + uint32_t total_cnt; + uint32_t reserved[5]; + struct bdfe bdfes[0]; +}; + +struct f70s5arg { + uint32_t sf; + uint32_t reserved1; + uint32_t flags; + uint32_t reserved2; + void *buf; + uint8_t zero; + const char *path; +} __attribute__((packed)); + +#define KF_READONLY 0x01 +#define KF_HIDDEN 0x02 +#define KF_SYSTEM 0x04 +#define KF_LABEL 0x08 +#define KF_FOLDER 0x10 + +uint32_t kos_time_to_epoch(uint32_t *time); +void *kos_fuse_init(int fd, uint32_t sect_cnt); +int kos_fuse_lfn(void *f70arg); + +#endif diff --git a/makefile b/makefile index e6b2d5f..8993cc0 100644 --- a/makefile +++ b/makefile @@ -1,27 +1,32 @@ FASM=fasm CC=gcc -CFLAGS=-m32 -Wall -Wextra -g -O0 -D_FILE_OFFSET_BITS=64 -LDFLAGS=-m32 +CFLAGS=-Wall -Wextra -g -O0 +CFLAGS_32=-m32 -D_FILE_OFFSET_BITS=64 +LDFLAGS= +LDFLAGS_32=-m32 -all: kofu kofuse +all: kofu kofuse tools/mkdirrange -kofu: kofu.o kocdecl.o - $(CC) $(LDFLAGS) $^ -o $@ +kofu: kofu.o kolibri.o + $(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ -kofuse: kofuse.o kocdecl.o - $(CC) $(LDFLAGS) $^ -o $@ `pkg-config fuse3 --libs` +kofuse: kofuse.o kolibri.o + $(CC) $(LDFLAGS) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs` -kocdecl.o: kocdecl.asm kocdecl.h $(KERNEL_TRUNK)/fs/ext.inc $(KERNEL_TRUNK)/fs/xfs.inc $(KERNEL_TRUNK)/fs/xfs.asm - INCLUDE="$(KERNEL_TRUNK);$(KERNEL_TRUNK)/fs;$(KERNEL_TRUNK)/blkdev" $(FASM) $< $@ -m 1234567 +kolibri.o: kolibri.asm kolibri.h + INCLUDE="$(KOLIBRI_TRUNK)" $(FASM) $< $@ -m 100000 -kofu.o: kofu.c kocdecl.h - $(CC) $(CFLAGS) -c $< +kofu.o: kofu.c kolibri.h + $(CC) $(CFLAGS) $(CFLAGS_32) -c $< -kofuse.o: kofuse.c kocdecl.h - $(CC) $(CFLAGS) `pkg-config fuse3 --cflags` -c $< +kofuse.o: kofuse.c kolibri.h + $(CC) $(CFLAGS) $(CFLAGS_32) `pkg-config fuse3 --cflags` -c $< + +tools/mkdirrange: tools/mkdirrange.c + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ .PHONY: all clean clean: - rm -f *.o kofu kofuse + rm -f *.o kofu kofuse tools/mkdirrange diff --git a/tools/mkdirrange.c b/tools/mkdirrange.c new file mode 100644 index 0000000..a888db8 --- /dev/null +++ b/tools/mkdirrange.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include + + +int main(int argc, char *argv[]) +{ + unsigned long begin, end, current; + char dirname[256] = "dir0123456789_blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah\0"; + + if(argc != 3) { + fprintf(stderr, "%s num_begin num_end\n", argv[0]); + exit(1); + } + + sscanf(argv[1], "%lu", &begin); + sscanf(argv[2], "%lu", &end); + + for(current=begin; current<=end; current++) { + sprintf(dirname + 3, "%10.10lu", current); + dirname[13] = '_'; + if(mkdir(dirname, 0755)) { + fprintf(stderr, "error: %s\n", strerror(errno)); + exit(1); + } + } + + return 0; +}