🎯 외부 함수 __error를 사용해서 errno의 값을 세팅해줄 것
- Your code must set the variable errno properly.
- For that, you are allowed to call the extern ___error.
🎯 error number의 줄임말로, 가장 최근 에러의 번호를 담는 integer 타입 변수다
프로그램이 시작하면 errno는 0으로 초기화된다
에러가 생기면 시스템 콜 함수는 NULL이나 -1 등을 반환한다.
에러 타입을 파악하기 위해 외부변수 errno에 에러 번호가 담긴다
매뉴얼 페이지에서 에러 번호에 따른 에러 타입을 명시하고 있다
man errno
When a system call detects an error, it returns an integer value indicating failure (usually -1) and sets the variable errno accordingly. <This allows interpretation of the failure on receiving a -1 and to take action accordingly.> Successful calls never set errno; once set, it remains until another error occurs.
...
0 Error 0. Not used.
1 EPERM Operation not permitted. An attempt was made to perform an operation limited to processes with appropriate privileges or to the owner of a file or other resources.2 ENOENT No such file or directory. A component of a specified pathname did not exist, or the pathname was an empty string.
...
🎯 errno의 주소를 리턴하는 함수
# /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include/sys/errno.h
extern int * __error(void);
#define errno (*__error())
🎯 errno에 에러번호를 세팅하려면 errno의 주소가 필요하다 (___error의 리턴값)
FreeBSD에서는 시스템콜이 errno를 세팅하는 대신 errno를 바로 리턴하고 carry flag를 1로 바꿔준다고 한다
FreeBSD는 정통 유닉스 운영체제며 Mac OS X의 일부가 FreeBSD를 바탕으로 개발되었다고 한다
때문에 Mac OS X 를 사용하는 컴퓨터에서는 시스템 콜 에러시 직접 시스템 콜의 리턴값을 -1로 세팅하고 변수 errno에 에러넘버를 세팅해주어야한다
write나 read 함수 매뉴얼의 리턴값 설명을 보면 -1을 리턴하고 errno라는 변수를 세팅하라고 되어있다
따라서 write나 read 함수에서 ___error()를 호출하면 된다
man 2 write
man 2 read
Otherwise, a -1 is returned and the global variable errno is set to indicate the error.
🥊 에러가 발생하면 -1을 리턴하고 ___error를 사용해서 errno의 값을 세팅
;_ft_write.s
section .text
global _ft_write ; fd = rdi, buf = rsi, bytes count = rdx
extern ___error
_ft_write: mov rax, 0x2000004
syscall
jc set_error ; if error, carry flag = 1, rax = error number
ret
set_error:
mov rcx, rax ; save error number to rcx
call ___error ; returns errno's address: rax = errno address
mov [rax], rcx ; save error number to errno address value
; errno = error number, rax -> errno
mov rax, -1 ; return value rax = -1
ret