I write this code and it would not unlink a file if invoked from the same directory as the file to delete, it would unlink files from other dirs
.section .data
fpath:
.asciz "/home/user/filename" # path to file to delete
.section .text
.globl _start
_start:
movl $10, %eax # unlink syscall
movl $fpath, %ebx # path to file to delete
int $0x80
movl %eax, %ebx # put syscall ret value in ebx
movl $1, %eax # exit syscall
int $0x80
What i want is to unlink all files (including itself) in the directory in which it is running.
You need to recursively delete the directory contents before you can delete the directory itself. The following is in C but uses no standard library functions, only syscalls:
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <dirent.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
struct linux_dirent64 {
ino64_t d_ino;
off64_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
static void rmrf(int dfd, const char *name) {
unsigned char buffer[16384];
struct linux_dirent64 *dirent;
int fd, off, size;
fd = syscall(SYS_openat, dfd, name, O_RDONLY | O_DIRECTORY);
if (fd == -1) {
syscall(SYS_exit, 1);
}
do {
size = syscall(SYS_getdents64, fd, buffer, sizeof(buffer));
if (size < 0) {
syscall(SYS_exit, 1);
}
for (off = 0; off < size; off += dirent->d_reclen) {
dirent = (struct linux_dirent64 *)&buffer[off];
if (dirent->d_name[0] == '.' &&
(dirent->d_name[1] == '\0' ||
(dirent->d_name[1] == '.' &&
(dirent->d_name[2] == '\0')))) {
continue;
}
if (dirent->d_type != DT_DIR) {
if (!syscall(SYS_unlinkat, fd, dirent->d_name, 0)) {
continue;
}
if (dirent->d_type != DT_UNKNOWN) {
syscall(SYS_exit, 1);
}
}
rmrf(fd, dirent->d_name);
}
} while (off);
syscall(SYS_close, fd);
if (syscall(SYS_unlinkat, dfd, name, AT_REMOVEDIR)) {
syscall(SYS_exit, -1);
}
}
int main() {
const char fpath[] = "/home/user/filename";
if (syscall(SYS_unlink, fpath)) {
rmrf(0, fpath);
}
syscall(SYS_exit, 0);
}