Adds fread(), fseek()
This commit is contained in:
@@ -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
|
||||||
|
@@ -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
|
||||||
|
66
src/file.asm
66
src/file.asm
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user