因此,我需要使用x86_64程序集递归删除目录中的文件。 这是我的代码,我知道这很不好。我的问题是每个syscall都可以单独工作(我可以单独删除目录或文档),但是一旦我像这样将它们合并在一起,它就无法工作。 #edit:正如@fuz指出的那样,该问题的描述性不够。因此,我希望它打开包含名为“ test.txt”的文件的目录,删除该文件,然后删除包含该文件的目录。但是当我使用nasm编译它时,它只是退出了程序。我正在使用Linux Mint
global _start
section .text
_start:
;open directory
mov rax, 2 ;sys_open
mov rdi, dir ;pointer to the directory
mov rsi, 0 ;read only
syscall
;delete document
mov rax, 87 ;sys_unlink
mov rdi, doc ;points to the document
syscall
;delete directory
mov rax, 84 ;sys_rmdir
mov rdi, dir
syscall
_exit:
mov rax, 60
mov rdi, 80
syscall
section .data
dir: db 'test',0
doc: db 'test.txt',0
答案 0 :(得分:3)
您的问题不在于汇编,而在于理解基本的POSIX / Unix文件操作系统调用。 open("dir")
以后不会相对于该目录进行unlink / rmdir系统调用,它们仍然相对于您当前的工作目录。您可以使用chdir()
进行更改。
(使用C比使用asm更容易。对于大多数系统调用而言,glibc包装器是微不足道的,并将所有args不变地传递给内核。如果不是这种情况,请参见Linux手册页的NOTES部分记录下来。)
有 个系统调用,它们执行与打开的目录文件描述符(而不是CWD)相关的事情,其名称在文件名后添加了...at
后缀。传统的系统调用名称。该文档使用C语法来描述系统调用,但是在ABI的指导下,它告诉您如何在asm中调用它们。
unlinkat(int dirfd, const char *pathname, int flags)
rmdir
实际上是用unlinkat(fd, path, AT_REMOVEDIR)
完成的。 (否则,对于flags=0
,unlinkat的行为类似于常规的unlink
。)
linkat
,symlinkat
,readlinkat
,statat
,mkdirat
,execveat
,... 其他各种类型,包括renameat
和一个有趣的renameat2
,它带有标志,允许您在同一文件系统上原子地交换两个路径名。
notes section of the openat
man page解释了为什么这些at
系统调用首先存在于Rationale for openat()
下-避免了其他人rename
在readdir和open之间的竞争情况路径的目录组件。而且由于chdir()
是按进程而不是按线程的,因此允许不同的线程同时在不同目录中执行相对的工作。
就像Jester所说的那样,请使用 strace find test -name 'test.txt' -delete
或类似的方法来查看如何通过open(O_DIRECTORY)
,getdents
和{{1} }。
getdents
是在Linux上基于POSIX unlinkat
接口构建的原始系统调用。手册页对此进行了记录。在asm中,您可以使用对readdir
的libc函数调用,也可以自己使用readdir
。
或者由于您实际上并不是递归,只需对一些相对路径进行硬编码,您就可以进行getdents
和unlink("test/test.txt")
系统调用。