Ваша проблема не в сборке, а в понимании основных системных вызовов POSIX / Unix.open("dir")
не делает последующие системные вызовы unlink / rmdir относительно этого каталога, они все еще относятся к вашему текущему рабочему каталогу.Вы можете изменить это с помощью chdir()
.
(И это проще сделать с C, чем с asm. Для большинства системных вызовов оболочка glibc тривиальна и передает все аргументы без изменений ядру.это не так, в разделе NOTES справочной страницы Linux это указано.)
Там - это системные вызовы, которые выполняют действия, связанные с дескриптором файла открытого каталога (вместо этого)CWD) , чьи имена добавляют суффикс ...at
к традиционным именам системных вызовов.Документация использует синтаксис C для описания системных вызовов, но, учитывая ABI, он говорит вам, как вызывать их в asm.
unlinkat(int dirfd, const char *pathname, int flags)
- fd-относительный
rmdir
фактически выполняется с unlinkat(fd, path, AT_REMOVEDIR)
.(В противном случае при flags=0
unlinkat ведет себя как обычный unlink
). linkat
, symlinkat
, readlinkat
, statat
, mkdirat
, execveat
, ... различные другие, включая renameat
, и забавный renameat2
, который принимает флаги, позволяющие вам атомарно менять два пути в одной и той же файловой системе.
Раздел примечаний справочной страницы openat
объясняет, почему эти системные вызовы at
существуют в первую очередь, в Rationale for openat()
- избегает условий гонкимежду readdir и open, если кто-то еще rename
sa компонент каталога пути.А поскольку chdir()
для каждого процесса, а не для каждого потока, позволяет разным потокам одновременно выполнять относительные операции в разных каталогах.
Как сказал Шут, используйтеstrace find test -name 'test.txt' -delete
или что-то в этом роде, чтобы увидеть, как на самом деле выполнять рекурсию через каталоги с open(O_DIRECTORY)
, getdents
и unlinkat
.
getdents
это необработанный системный вызов, над которым в Linux построен интерфейс POSIX readdir
.Страницы руководства документируют это.В asm вы можете использовать вызовы функций libc для readdir
, или вам придется использовать getdents
самостоятельно.
Или, поскольку вы на самом деле не рекурсивных, просто жестко запрограммировав некоторые относительные пути, вы можете просто сделать unlink("test/test.txt")
и rmdir("test")
системные вызовы.