Adds fread(), fseek()

This commit is contained in:
2025-07-28 10:05:16 +02:00
parent a8bc8cfa2e
commit a803a216b1
4 changed files with 163 additions and 5 deletions

View File

@@ -75,3 +75,7 @@ section .rodata
S_IFIFO equ 0010000q ; FIFO S_IFIFO equ 0010000q ; FIFO
S_IFLNK equ 0120000q ; Symbolic link S_IFLNK equ 0120000q ; Symbolic link
S_IFSOCK equ 0140000q ; Socket S_IFSOCK equ 0140000q ; Socket
; Seek options
SEEK_SET equ 0
SEEK_CUR equ 1
SEEK_END equ 2

View File

@@ -6,6 +6,7 @@ section .rodata
;NR_stat equ 4 ;NR_stat equ 4
NR_fstat equ 5 NR_fstat equ 5
NR_lstat equ 6 NR_lstat equ 6
NR_lseek equ 8
NR_exit equ 60 NR_exit equ 60
NR_creat equ 85 NR_creat equ 85
NR_umask equ 95 NR_umask equ 95

View File

@@ -14,6 +14,8 @@ section .text
global fclose global fclose
global fexist global fexist
global fwrite global fwrite
global fread
global fseek
;----- stat(*file[], *statBuffer[]) -----; ;----- stat(*file[], *statBuffer[]) -----;
; Gets information from a file, stores it into statBuffer[] ; Gets information from a file, stores it into statBuffer[]
@@ -217,20 +219,19 @@ fexist:
;--- fwrite(*filePointer, *data[], ...) -----; ;--- fwrite(*filePointer, *data[], ...) -----;
; Writes data to given file. Allows format specifiers and variable arguments (see `__INTERNAL_fmt` for supported specifiers) ; Writes data to given file. Allows format specifiers and variable arguments (see `__INTERNAL_fmt` for supported specifiers)
; Return value: Length of given string(data[]), 0 if nothing was written (eg invalid file or file not writable, or data[] is empty) ; Return value: Length of given string(data[]), 0 if nothing was written or -errno if an error occured
; Used registers: ; Used registers:
; rax* (ret) ; rax* (ret)
; rdi (arg) Pointer to file ; rdi (arg) Pointer to file
; rsi (arg) Data to write ; rsi (arg) Data to write
fwrite: fwrite:
push rbp
mov rbp, rsp
cmp rdi, 2 cmp rdi, 2
jg .cnt jg .cnt
xor rax, rax mov rax, -EBADF
leave
ret ret
.cnt: .cnt:
push rbp
mov rbp, rsp
mov rax, rdi mov rax, rdi
mov rdi, rsi mov rdi, rsi
mov rsi, rdx mov rsi, rdx
@@ -241,3 +242,58 @@ fwrite:
call __INTERNAL_fmt call __INTERNAL_fmt
leave leave
ret ret
;--- fread(*filePointer, *buff[], maxLength) ---;
; Reads data from given file.
; Return value: Amount of read characters or -errno if an error occured
; Used registers:
; rax* (ret)
; rdi* (arg) Pointer to file
; rsi (arg) Pointer to buff[] (where to store read data)
; rdx (arg) Size of buff[]
fread:
cmp rdi, 2
jg .cnt
mov rax, -EBADF
ret
.cnt:
sub rsp, SIZE_QWORD
mov rax, NR_read
syscall
cmp rax, rdx
je .subOne
jmp .addAll
.subOne:
add rsi, rax
dec rsi
jmp .addEOS
.addAll:
add rsi, rax
.addEOS:
mov byte [rsi], EOS
.quit:
add rsp, SIZE_QWORD
ret
;--- fseek(*filePointer, mode, offset) ---;
; Sets pointer in file. Mode is SEEK_SET, SEEK_CUR or SEEK_END.
; Return value: On succes returns the resulting offset location as measured in bytes from the beginning of the file. On error, -errno
; Used registers:
; rax* (ret)
; rdi (arg) Pointer to file
; rsi (arg) Seek mode
; rdx (arg) Pointer offset
fseek:
cmp rdi, 2
jg .cnt
mov rax, -EBADF
ret
.cnt:
sub rsp, SIZE_QWORD
mov rax, rsi
mov rsi, rdx
mov rdx, rax
mov rax, NR_lseek
syscall
add rsp, SIZE_QWORD
ret

View File

@@ -96,6 +96,8 @@ extern stat
extern lstat extern lstat
extern fgettype extern fgettype
extern fgetmod extern fgetmod
extern fread
extern fseek
section .rodata section .rodata
;;; ;;;
@@ -136,6 +138,8 @@ section .rodata
;file.asm ;file.asm
TEST_fopen equ 1 ;Includes fclose TEST_fopen equ 1 ;Includes fclose
TEST_fwrite equ 1 TEST_fwrite equ 1
TEST_fread equ 1
TEST_fseek equ 1
TEST_stat equ 1 TEST_stat equ 1
TEST_lstat equ 1 TEST_lstat equ 1
TEST_fgettype equ 1 TEST_fgettype equ 1
@@ -349,6 +353,14 @@ section .rodata
addTest(fwrite3, "fwrite(fp1, 'Howdy environment!') //mode 'w'") addTest(fwrite3, "fwrite(fp1, 'Howdy environment!') //mode 'w'")
addTest(fwrite4, "fwrite(fp1, ''%c%c%c%c%c%c%c%c\n'', 'H', 'e', 'l', 'l', 'o', '!', '?', '!')") addTest(fwrite4, "fwrite(fp1, ''%c%c%c%c%c%c%c%c\n'', 'H', 'e', 'l', 'l', 'o', '!', '?', '!')")
fwriteStr1 db "%c%c%c%c%c%c%c%c\n",EOS fwriteStr1 db "%c%c%c%c%c%c%c%c\n",EOS
;fread()
addTestHeader(_fread, "fread")
addTest(fread1, "fread(fp1, strBuff1, 64)")
;fseek()
addTestHeader(_fseek, "fseek")
addTest(fseek1, "fseek(fp1, SEEK_SET, 5)")
addTest(fseek2, "fseek(fp1, SEEK_CUR, -1)")
addTest(fseek3, "fseek(fp1, SEEK_SET, 0)")
;stat() ;stat()
addTestHeader(_stat, "stat") addTestHeader(_stat, "stat")
addTest(stat1, "stat('tests', statBuff1)") addTest(stat1, "stat('tests', statBuff1)")
@@ -1288,6 +1300,91 @@ _start:
call fclose call fclose
%endif %endif
;--- fread()
%if TEST_fread
printTestHeader(_fread)
mov rdi, [fp1]
call fclose
lea rdi, [rel file1]
mov rsi, 'r'
call fopen
assert_neq(0)
mov [fp1], rax
printTest(fread1)
mov rdi, [fp1]
lea rsi, [rel strBuff1]
mov rdx, 64
call fread
assert_more_eq(1)
lea rdi, [rel strBuff1]
call puts
mov rdi, [fp1]
call fclose
%endif
;--- fseek()
%if TEST_fseek
%macro fseek_relptr 1
%endmacro
%macro fseek_readput 0
mov rdi, [fp1]
lea rsi, [rel strBuff1]
mov rdx, 64
call fread
lea rdi, [rel strBuff1]
call puts
%endmacro
printTestHeader(_fseek)
lea rdi, [rel file1]
mov rsi, 'r'
call fopen
mov [fp1], rax
; TEST 1: fseek(fp1, SEEK_SET, 5)
printTest(fseek1)
mov rdi, [fp1]
mov rsi, SEEK_CUR
mov rdx, 5
call fseek
assert_eq(5)
fseek_readput
; TEST 2: fseek(fp1, SEEK_CUR, -1)
printTest(fseek2)
mov rdi, [fp1]
mov rsi, SEEK_SET
mov rdx, 5
call fseek
;^ fseek_readput (fread) modified pointer, so restore it to result of test 1
mov rdi, [fp1]
mov rsi, SEEK_CUR
mov rdx, -1
call fseek
assert_eq(4)
fseek_readput
; FAIL. Returned is 26 (which is length of the file)
; My best guess is -1 is treated as unsigned. However, according to man 2 lseek:
; The off_t data type is a signed integer data type
; ( offset in rdx is supposed to be (off_t) offset )
; If it turns out unsigned after all, I'll have to manually get current location of pointer (call NR_lseek with SEEK_CUR and offset 0; returned value is current location)
; ... and then substract given argument from that
; TEST 3: fseek(fp1, SEEK_SET, 0)
printTest(fseek3)
mov rdi, [fp1]
mov rsi, SEEK_SET
xor rdx, rdx
call fseek
assert_eq(0)
fseek_readput
mov rdi, [fp1]
call fclose
%endif
;--- stat() ;--- stat()
%if TEST_stat %if TEST_stat
printTestHeader(_stat) printTestHeader(_stat)