NASM x86_64: 文件打开 (SYS_OPEN) 错误列表?

NASM x86_64: File opening (SYS_OPEN) error list?

我正在编写一个读取文件的 linux x64 汇编程序,我想处理诸如找不到文件或权限错误之类的错误。

在哪里可以找到 SYS_OPEN 错误代码的列表?

查找代码的方法(有点有趣)

我打开文件的代码:

SYS_OPEN    equ 2
O_RDONLY    equ 0

section .data
    filename db "file.txt", 0

section .text
    global _start

_start:
    mov rax, SYS_OPEN
    mov rdi, filename
    mov rsi, O_RDONLY
    mov rdx, 0644o
    syscall

    [...]

当文件打开成功时RAX寄存器指向file descriptor(正整数),如果失败则RAX指向错误(负整数)。我设法通过删除所有用户的所有权限来引发权限错误:

chmod 0000 file.txt

这会导致错误代码 -13。通过删除文件,我设法得到错误 -2。我在哪里可以找到 SYS_OPEN 错误代码的列表?

PS: 可能是我的 google 技术生疏了

您可以将其解释为 errno 的值,这里是 table (to list all of the codes use errno -l), also take a look at the docs。 table的一部分:

number hex symbol description
2 0x02 ENOENT No such file or directory
13 0x0d EACCES Permission denied

描述了这样决定的原因:

-4095-1-errno个代码。([=99的实际最高错误数=]实际上已经定义了目前大约133EHWPOISON,但那是官方范围。)

strace ./myprog 可以为您解码它们,因此您在玩系统调用时不需要在玩具程序中实际编写错误检查。

例如:

$ strace touch /tmp/xyjklj/bar
...  (dynamic linker / process startup stuff)

openat(AT_FDCWD, "/tmp/xyjklj/bar", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = -1 ENOENT (No such file or directory)
utimensat(AT_FDCWD, "/tmp/xyjklj/bar", NULL, 0) = -1 ENOENT (No such file or directory)

... (more system calls as touch(1) finds a locale-specific set of error messages and prints

-1 是 libc 包装器函数实际上 returns;errno 代码是 strace 从 asm 系统调用 return 值解码的内容,glibc 包装器将存储该值在 errno 中。在 asm 中使用原始系统调用时,您不必为此浪费指令。但 strace 仍会说“-1”,而不是数字错误代码)


大多数方法的文档 SYS_open 可能会失败

每个系统调用手册页都记录了特定系统调用可能会失败的错误代码,以及可能发生的情况。 (这些列表 并不完全详尽 ,例如没有涵盖像 NFS 这样的特定文件系统可能 return 的怪异事物,例如 EMULTIHOP(见评论)。)

关于您的情况,请参阅 the ERRORs section of the open(2) man page。例如ENOENT 有多个条目,涵盖了可能导致该 return 值的所有情况。

  • ENOENT - O_CREAT is not set and the named file does not exist.

  • ENOENT - A directory component in pathname does not exist or is a dangling symbolic link.

  • ENOENT - pathname refers to a nonexistent directory, O_TMPFILE and one of O_WRONLY or O_RDWR were specified in flags, but this kernel version does not provide the O_TMPFILE functionality.

(剧透警告,2ENOENT,所以 -2-ENOENT。)

当然还有许多其他有趣的路径名和文件访问内容(尤其是 open(2))可能出错的方式,包括:

  • EACCES (-13) - The requested access to the file is not allowed, or search permission is denied for one of the directories in the path prefix of pathname, or the file did not exist yet and write access to the parent directory is not allowed. (See also path_resolution(7).)

  • EFAULT - pathname points outside your accessible address space.

  • ENAMETOOLONG - pathname was too long.

  • EBUSY - O_EXCL was specified in flags and pathname refers to a block device that is in use by the system (e.g., it is mounted).
    [this would require root, otherwise you'd get EACCESS]

  • ETXTBSY - pathname refers to an executable image which is currently being executed and write access was requested.

  • EWOULDBLOCK - The O_NONBLOCK flag was specified, and an incompatible lease was held on the file (see fcntl(2)).

  • ENODEV - pathname refers to a device special file and no corresponding device exists. (This is a Linux kernel bug; in this situation ENXIO must be returned.)

  • ELOOP - Too many symbolic links were encountered in resolving pathname. EISDIR - pathname refers to a directory and the access requested involved writing (that is, O_WRONLY or O_RDWR is set). ENOTDIR - A component used as a directory in pathname is not, in fact, a directory, or O_DIRECTORY was specified and pathname was not a directory.

  • EPERM - The O_NOATIME flag was specified, but the effective user ID of the caller did not match the owner of the file and the caller was not privileged.

以及各种限制,例如打开文件的数量(ENFILE、EMFILE)或 ENOSPC 磁盘 space 已满。以上不是一个完整的列表,我只是用了一种方法来获取很多(但不是全部)错误代码。


根据 funnydman 的回答,您可以在手册页中查找错误值的数字 -> 符号含义。或者查看 /usr/include/asm-generic/errno-base.h(完整路径在某些系统上可能不同,您只能通过 #include <errno.h> 间接包含此文件)