;; File: stpdfs.inc

STPDFS_BLOCK_SIZE = 512
STPDFS_NAME_MAX   = 28

	;; Struct: Inode
struc Inode {
	.inode   dw ?
	.nlink   dw ?
	.uid     dw ?
	.gid     dw ?
	.flags   dw ?
	.size    dd ?
	.zones   dd 10 dup(?)
	.actime  dq ?
	.modtime dq ?
}
DEFN Inode

STPDFS_INODE_PER_BLOCK equ STPDFS_BLOCK_SIZE / sizeof.Inode

	;; Struct: DirEntry
struc DirEntry {
	.inum dd ?
	.name db STPDFS_NAME_MAX dup(?)
}
DEFN DirEntry

	;; Function: stpdfs_load_rootdir
	;;
	;; Out:
	;;    
stpdfs_load_rootdir:
	; read first inode
	mov ax, DISK_BUFFER/0x10
	mov es, ax
	mov ax, 2
	mov cx, 1
	xor bx, bx

	call disk_read_sectors

	; root dir is inode 1
	xor ax, ax
	mov es, ax
	mov ecx, sizeof.Inode
	mov esi, DISK_BUFFER + sizeof.Inode
	mov edi, inode_cache
	rep movsb

	mov ax, DISK_BUFFER/0x10
	mov es, ax
	xor bx, bx
	call stpdfs_copy_data

	ret

	;; Function: stpdfs_read_inode
	;; 
	;; copy selected inode from file system to `inode_cache` 
	;;
	;; In:
	;;    EAX - inum
	;;
stpdfs_read_inode:
	; get block where inode is located
	xor edx, edx
	mov ecx, STPDFS_INODE_PER_BLOCK
	div ecx
	add eax, 2

	; read block
	push edx
	push eax
	mov ax, DISK_BUFFER/0x10
	mov es, ax
	pop eax
	mov cx, 1
	xor bx, bx
	call disk_read_sectors
	pop edx

	; copy to inode cache
	mov eax, edx
	mov cl, sizeof.Inode
	mul cl
	movzx esi, ax
	add esi, DISK_BUFFER

	xor ax, ax
	mov es, ax
	mov ecx, sizeof.Inode
	mov edi, inode_cache
	rep movsb

	ret

	;; Function: stpdfs_search
	;;
	;; In:
	;;    SI - filename
	;;
	;; Out:
	;;    EAX - kernel inode
stpdfs_search:
	clc	; clear carry flag
	
	xor ax, ax
	mov es, ax

	xor ecx, ecx
.search_loop:
	cmp ecx, dword [inode_cache + Inode.size]
	jge .search_end

	push ecx

	; check if inum != 0
	mov eax, DISK_BUFFER
	add eax, ecx
	mov edx, [eax]

	or edx, edx
	jz .search_next

	; compare filename
	mov edi, eax
	add edi, 4

	push si
.strcmp:
	mov al, [si]
	cmpsb
	jne .strcmp_not_equal
	or al, al
	jz .kernel_found
	jmp .strcmp
.strcmp_not_equal:
	pop si
.search_next:
	pop ecx
	add ecx, sizeof.DirEntry
	jmp .search_loop
.search_end:
	stc
	ret
.kernel_found:
	pop si
	pop ecx

	mov eax, edx

	clc
	ret

	;; Function: stpdfs_copy_data
	;;
	;; In:
	;;	ES:BX - buffer
	;;
stpdfs_copy_data:
	xor edx, edx
	movzx ebx, bx

	;; read direct
@@:
	cmp ebx, dword [inode_cache + Inode.size]
	jg .all_read
	mov eax, edx
	shl eax, 2
	add eax, inode_cache + Inode.zones
	mov eax, [eax]

	push edx
	push ebx
	mov cx, 1
	call disk_read_sectors
	pop ebx
	pop edx

	add ebx, STPDFS_BLOCK_SIZE
	inc edx
	cmp edx, 7
	jb @b

.indirect_read:
	push ebx
	mov ax, es
	push ax

	mov ax, DISK_BUFFER/0x10
	mov es, ax
	
	mov eax, dword [inode_cache + Inode.zones + 28]
	mov cx, 1
	xor bx, bx
	call disk_read_sectors

	pop ax
	mov es, ax

	pop ebx
	xor edx, edx
@@:
	cmp ebx, dword [inode_cache + Inode.size]
	jg .all_read
	mov eax, edx
	shl eax, 2
	add eax, DISK_BUFFER
	mov eax, [eax]

	mov cx, 1
	push edx
	call disk_read_sectors
	pop edx

	add ebx, STPDFS_BLOCK_SIZE
	inc edx
	cmp edx, 128
	jbe @b
.all_read:
	ret