diff --git a/src/constants/file.asm b/src/constants/file.asm index a802669..cd61a32 100644 --- a/src/constants/file.asm +++ b/src/constants/file.asm @@ -1,73 +1,75 @@ section .rodata ; Open flags - O_ACCMODE equ 00000003q - O_RDONLY equ 00000000q - O_WRONLY equ 00000001q - O_RDWR equ 00000002q - O_CREAT equ 00000100q ;create if not exist - O_EXCL equ 00000200q ;fail if file exists and O_EXCL+O_CREAT set - O_NOCTTY equ 00000400q - O_TRUNC equ 00001000q - O_APPEND equ 00002000q - O_NONBLOCK equ 00004000q - O_DSYNC equ 00010000q - FASYNC equ 00020000q - O_DIRECT equ 00040000q - O_LARGEFILE equ 00100000q - O_DIRECTORY equ 00200000q - O_NOFOLLOW equ 00400000q - O_NOATIME equ 01000000q - O_CLOEXEC equ 02000000q - __O_SYNC equ 04000000q - O_SYNC equ (__O_SYNC | O_DSYNC) - O_PATH equ 01000000q - __O_TMPFILE equ 02000000q - O_TMPFILE equ (__O_TMPFILE | O_DIRECTORY) - O_NDELAY equ O_NONBLOCK + O_ACCMODE equ 00000003q + O_RDONLY equ 00000000q + O_WRONLY equ 00000001q + O_RDWR equ 00000002q + O_CREAT equ 00000100q ;create if not exist + O_EXCL equ 00000200q ;fail if file exists and O_EXCL+O_CREAT set + O_NOCTTY equ 00000400q + O_TRUNC equ 00001000q + O_APPEND equ 00002000q + O_NONBLOCK equ 00004000q + O_DSYNC equ 00010000q + FASYNC equ 00020000q + O_DIRECT equ 00040000q + O_LARGEFILE equ 00100000q + O_DIRECTORY equ 00200000q + O_NOFOLLOW equ 00400000q + O_NOATIME equ 01000000q + O_CLOEXEC equ 02000000q + __O_SYNC equ 04000000q + O_SYNC equ (__O_SYNC | O_DSYNC) + O_PATH equ 01000000q + __O_TMPFILE equ 02000000q + O_TMPFILE equ (__O_TMPFILE | O_DIRECTORY) + O_NDELAY equ O_NONBLOCK ; Permission flags - S_IXOTH equ 00001q ;o=x - S_IWOTH equ 00002q ;o=w - S_IROTH equ 00004q ;o=r - S_IRWXO equ 00007q ;o=rwx - S_IXGRP equ 00010q ;g=x - S_IWGRP equ 00020q ;g=w - S_IRGRP equ 00040q ;g=r - S_IRWXG equ 00070q ;g=rwx - S_IXUSR equ 00100q ;u=x - S_IWUSR equ 00200q ;u=w - S_IRUSR equ 00400q ;u=r - S_IRWXU equ 00700q ;u=rwx - S_ISVTX equ 0001000q ;sticky bit - S_ISGID equ 0002000q ;set-group-ID bit - S_ISUID equ 0004000q ;set-user-ID bit + S_IXOTH equ 00001q ;o=x + S_IWOTH equ 00002q ;o=w + S_IROTH equ 00004q ;o=r + S_IRWXO equ 00007q ;o=rwx + S_IXGRP equ 00010q ;g=x + S_IWGRP equ 00020q ;g=w + S_IRGRP equ 00040q ;g=r + S_IRWXG equ 00070q ;g=rwx + S_IXUSR equ 00100q ;u=x + S_IWUSR equ 00200q ;u=w + S_IRUSR equ 00400q ;u=r + S_IRWXU equ 00700q ;u=rwx + S_ISVTX equ 0001000q ;sticky bit + S_ISGID equ 0002000q ;set-group-ID bit + S_ISUID equ 0004000q ;set-user-ID bit ; Stat buffer fields - ST_DEV equ 0 ; Device unsigned - ST_INO equ 8 ; File serial number unsigned - ST_NLINK equ 16 ; Number of links unsigned - ST_MODE equ 24 ; File mode unsigned, 4 bytes - ST_UID equ 28 ; User ID of the file's owner unsigned, 4 bytes - ST_GID equ 32 ; Group ID of the file's group unsigned, 4 bytes - ST__PAD0 equ 36 - ST_RDEV equ 40 ; Device number, if device unsigned - ST_SIZE equ 48 ; Size of file, in bytes signed - ST_BLKSIZE equ 56 ; Optimal block size for I/O signed - ST_BLOCKS equ 64 ; Number 512-byte blocks allocated signed - ST_ATIME equ 72 ; Time of last access unsigned - ST_ATIME_NSEC equ 80 ; unsigned - ST_MTIME equ 88 ; Time of last modification unsigned - ST_MTIME_NSEC equ 96 ; unsigned - ST_CTIME equ 104 ; Time of last status change unsigned - ST_CTIME_NSEC equ 112 ; unsigned - ST__UNUSED equ 120 - ST__END equ 128 ; End of stat buffer - STATBUFF_SIZE equ ST__END + ST_DEV equ 0 ; Device unsigned + ST_INO equ 8 ; File serial number unsigned + ST_NLINK equ 16 ; Number of links unsigned + ST_MODE equ 24 ; File mode unsigned, 4 bytes + ST_UID equ 28 ; User ID of the file's owner unsigned, 4 bytes + ST_GID equ 32 ; Group ID of the file's group unsigned, 4 bytes + ST__PAD0 equ 36 + ST_RDEV equ 40 ; Device number, if device unsigned + ST_SIZE equ 48 ; Size of file, in bytes signed + ST_BLKSIZE equ 56 ; Optimal block size for I/O signed + ST_BLOCKS equ 64 ; Number 512-byte blocks allocated signed + ST_ATIME equ 72 ; Time of last access unsigned + ST_ATIME_NSEC equ 80 ; unsigned + ST_MTIME equ 88 ; Time of last modification unsigned + ST_MTIME_NSEC equ 96 ; unsigned + ST_CTIME equ 104 ; Time of last status change unsigned + ST_CTIME_NSEC equ 112 ; unsigned + ST__UNUSED equ 120 + ST__END equ 128 ; End of stat buffer + STATBUFF_SIZE equ ST__END - AT_FDCWD equ -100 + AT_FDCWD equ -100 + AT_SYMLINK_NOFOLLOW equ 0x100 + AT_SYMLINK_FOLLOW equ 0x400 ; File types - S_IFDIR equ 0040000q ; Directory - S_IFCHR equ 0020000q ; Character device - S_IFBLK equ 0060000q ; Block device - S_IFREG equ 0100000q ; Regular file - S_IFIFO equ 0010000q ; FIFO - S_IFLNK equ 0120000q ; Symbolic link - S_IFSOCK equ 0140000q ; Socket + S_IFDIR equ 0040000q ; Directory + S_IFCHR equ 0020000q ; Character device + S_IFBLK equ 0060000q ; Block device + S_IFREG equ 0100000q ; Regular file + S_IFIFO equ 0010000q ; FIFO + S_IFLNK equ 0120000q ; Symbolic link + S_IFSOCK equ 0140000q ; Socket diff --git a/src/file.asm b/src/file.asm index 2c7b458..df23a1f 100644 --- a/src/file.asm +++ b/src/file.asm @@ -7,6 +7,7 @@ extern umask_get section .text global stat + global lstat global fgettype global fgetmod global fopen @@ -34,6 +35,19 @@ stat: add rsp, SIZE_QWORD ret +;----- lstat(*file[], *statBuffer[]) -----; +; Same as stat, except do not follow links +lstat: + sub rsp, SIZE_QWORD + mov rax, NR_newfstatat + mov rdx, rsi + mov rsi, rdi + mov rdi, AT_FDCWD + mov r10, AT_SYMLINK_NOFOLLOW + syscall + add rsp, SIZE_QWORD + ret + ;----- fgettype(*statBuffer[]) -----; ; Gets file type from stat buffer ; Return value: Permissions of given file or -EINVAL if statBuffer is invalid (first bit is 0) diff --git a/src/tests.asm b/src/tests.asm index 49f0387..3ccbf8f 100644 --- a/src/tests.asm +++ b/src/tests.asm @@ -93,6 +93,7 @@ extern fclose extern fexist extern fwrite extern stat +extern lstat extern fgettype extern fgetmod @@ -136,6 +137,7 @@ section .rodata TEST_fopen equ 1 ;Includes fclose TEST_fwrite equ 1 TEST_stat equ 1 + TEST_lstat equ 1 TEST_fgettype equ 1 TEST_fgetmod equ 1 @@ -349,7 +351,8 @@ section .rodata fwriteStr1 db "%c%c%c%c%c%c%c%c\n",EOS ;stat() addTestHeader(_stat, "stat") - addTest(stat1, "stat(file1)") + addTest(stat1, "stat('tests', statBuff1)") + bin_file db "tests",EOS statStr db "\t## Stats of file: %s ##\n" db "\tDevice: %u\n" db "\tInode: %u\n" @@ -364,9 +367,13 @@ section .rodata db "\tatime: %u.%u\n" db "\tmtime: %u.%u\n" db "\tctime: %u.%u\n",EOS + ;lstat() + addTestHeader(_lstat, "lstat") + addTest(lstat1, "lstat('test', statBuff2)") ;fgettype() addTestHeader(_fgettype, "fgettype") - addTest(fgettype1, "fgettype(statBuffer)") + addTest(fgettype1, "fgettype(statBuff1)") + addTest(fgettype2, "fgettype(statBuff2)") fgettypeStr db "\t- '%s' is filetype: %s\n",EOS ftype_dir db "Directory",EOS ftype_char db "Character Device",EOS @@ -378,14 +385,16 @@ section .rodata ftype_unknown db "Unknown (function fgettype() or stat() failed succesfully)",EOS ;fgetmod() addTestHeader(_fgetmod, "fgetmod") - addTest(fgetmod1, "fgetmod(statBuffer)") + addTest(fgetmod1, "fgetmod(statBuff1)") + addTest(fgetmod2, "fgetmod(statbuff2)") fgetmodStr db "\t- File permissions of file '%s': %04o\n",EOS section .bss strBuff1 resb 64 strBuff2 resb 64 fp1 resq 1 - statBuff resb STATBUFF_SIZE + statBuff1 resb STATBUFF_SIZE + statBuff2 resb STATBUFF_SIZE section .text global _start @@ -1284,30 +1293,64 @@ _start: printTestHeader(_stat) printTest(stat1) - lea rdi, [rel file1] - lea rsi, [rel statBuff] + lea rdi, [rel bin_file] + lea rsi, [rel statBuff1] call stat assert_eq(0) lea rdi, [rel statStr] - lea rsi, [rel file1] - mov rdx, [statBuff + ST_DEV] - mov rcx, [statBuff + ST_INO] - mov r8, [statBuff + ST_NLINK] - mov r9d, [statBuff + ST_MODE] - push qword [statBuff + ST_CTIME_NSEC] - push qword [statBuff + ST_CTIME] - push qword [statBuff + ST_MTIME_NSEC] - push qword [statBuff + ST_MTIME] - push qword [statBuff + ST_ATIME_NSEC] - push qword [statBuff + ST_ATIME] - push qword [statBuff + ST_BLOCKS] - push qword [statBuff + ST_BLKSIZE] - push qword [statBuff + ST_SIZE] - push qword [statBuff + ST_RDEV] - mov r10d, [statBuff + ST_GID] + lea rsi, [rel bin_file] + mov rdx, [statBuff1 + ST_DEV] + mov rcx, [statBuff1 + ST_INO] + mov r8, [statBuff1 + ST_NLINK] + mov r9d, [statBuff1 + ST_MODE] + push qword [statBuff1 + ST_CTIME_NSEC] + push qword [statBuff1 + ST_CTIME] + push qword [statBuff1 + ST_MTIME_NSEC] + push qword [statBuff1 + ST_MTIME] + push qword [statBuff1 + ST_ATIME_NSEC] + push qword [statBuff1 + ST_ATIME] + push qword [statBuff1 + ST_BLOCKS] + push qword [statBuff1 + ST_BLKSIZE] + push qword [statBuff1 + ST_SIZE] + push qword [statBuff1 + ST_RDEV] + mov r10d, [statBuff1 + ST_GID] push r10 - mov r10d, [statBuff + ST_UID] + mov r10d, [statBuff1 + ST_UID] + push r10 + call printf + add rsp, SIZE_QWORD * 12 +%endif + +;--- lstat() +%if TEST_lstat + printTestHeader(_lstat) + + printTest(lstat1) + lea rdi, [rel bin_file] + lea rsi, [rel statBuff2] + call lstat + assert_eq(0) + + lea rdi, [rel statStr] + lea rsi, [rel bin_file] + mov rdx, [statBuff2 + ST_DEV] + mov rcx, [statBuff2 + ST_INO] + mov r8, [statBuff2 + ST_NLINK] + mov r9d, [statBuff2 + ST_MODE] + push qword [statBuff2 + ST_CTIME_NSEC] + push qword [statBuff2 + ST_CTIME] + push qword [statBuff2 + ST_MTIME_NSEC] + push qword [statBuff2 + ST_MTIME] + push qword [statBuff2 + ST_ATIME_NSEC] + push qword [statBuff2 + ST_ATIME] + push qword [statBuff2 + ST_BLOCKS] + push qword [statBuff2 + ST_BLKSIZE] + push qword [statBuff2 + ST_SIZE] + push qword [statBuff2 + ST_RDEV] + mov r10d, [statBuff2 + ST_GID] + push r10 + mov r10d, [statBuff2 + ST_UID] push r10 call printf add rsp, SIZE_QWORD * 12 @@ -1317,8 +1360,9 @@ _start: %if TEST_fgettype printTestHeader(_fgettype) + ; TEST 1: fgettype(statBuff1) printTest(fgettype1) - lea rdi, [rel statBuff] + lea rdi, [rel statBuff1] call fgettype assert_neq(-EINVAL) @@ -1326,49 +1370,102 @@ _start: lea rsi, [rel ftype_dir] cmp rax, S_IFDIR cmove rdx, rsi - je .fgettype_cnt + je .fgettype1cnt lea rsi, [rel ftype_char] cmp rax, S_IFCHR cmove rdx, rsi - je .fgettype_cnt + je .fgettype1cnt lea rsi, [rel ftype_blk] cmp rax, S_IFBLK cmove rdx, rsi - je .fgettype_cnt + je .fgettype1cnt lea rsi, [rel ftype_reg] cmp rax, S_IFREG cmove rdx, rsi - je .fgettype_cnt + je .fgettype1cnt lea rsi, [rel ftype_fifo] cmp rax, S_IFIFO cmove rdx, rsi - je .fgettype_cnt + je .fgettype1cnt lea rsi, [rel ftype_link] cmp rax, S_IFLNK cmove rdx, rsi - je .fgettype_cnt + je .fgettype1cnt lea rsi, [rel ftype_sock] cmp rax, S_IFSOCK cmove rdx, rsi - .fgettype_cnt: + .fgettype1cnt: lea rdi, [rel fgettypeStr] - lea rsi, [rel file1] + lea rsi, [rel bin_file] call printf + + ; TEST 2: fgettype(statBuff2) + printTest(fgettype2) + lea rdi, [rel statBuff2] + call fgettype + assert_neq(-EINVAL) + + lea rdx, [rel ftype_unknown] + lea rsi, [rel ftype_dir] + cmp rax, S_IFDIR + cmove rdx, rsi + je .fgettype2cnt + lea rsi, [rel ftype_char] + cmp rax, S_IFCHR + cmove rdx, rsi + je .fgettype2cnt + lea rsi, [rel ftype_blk] + cmp rax, S_IFBLK + cmove rdx, rsi + je .fgettype2cnt + lea rsi, [rel ftype_reg] + cmp rax, S_IFREG + cmove rdx, rsi + je .fgettype2cnt + lea rsi, [rel ftype_fifo] + cmp rax, S_IFIFO + cmove rdx, rsi + je .fgettype2cnt + lea rsi, [rel ftype_link] + cmp rax, S_IFLNK + cmove rdx, rsi + je .fgettype2cnt + lea rsi, [rel ftype_sock] + cmp rax, S_IFSOCK + cmove rdx, rsi + + .fgettype2cnt: + lea rdi, [rel fgettypeStr] + lea rsi, [rel bin_file] + call printf + %endif ;--- fgetmod() %if TEST_fgetmod printTestHeader(_fgetmod) + ; TEST 1: fgetmod(statBuff1) printTest(fgetmod1) - lea rdi, [rel statBuff] + lea rdi, [rel statBuff1] call fgetmod assert_neq(-EINVAL) lea rdi, [rel fgetmodStr] - lea rsi, [rel file1] + lea rsi, [rel bin_file] mov rdx, rax call printf + + ; TEST 2: fgetmod(statBuff2) + printTest(fgetmod2) + lea rdi, [rel statBuff2] + call fgetmod + assert_neq(-EINVAL) + lea rdi, [rel fgetmodStr] + lea rsi, [rel bin_file] + mov rdx, rax + call printf + %endif ;;;