如何使用 x86-64 Linux 系统调用附加到文件?
How to append to a file using x86-64 Linux system calls?
我正在创建一个文件,然后使用系统调用打开它。
正在创建:
mov rax, 85
mov rdi, path
mov rsi, 400
syscall
开幕式:
mov rax, 2
mov rdi, path
mov rsi, 2 ; I found somewhere that I should use 400 to append
syscall
mov r8, rax ; save the file handle
写作:
mov rax, 1
mov rdi, r8
mov rsi, output
mov rdx, length
syscall
完成这些步骤后,我自然关闭文件,但是我无法附加到它,每次执行这些操作时它只是重写文件的内容,但是例如我计算了前 n 个素数并将它们存储在一些内存块中,现在我想在文件中写下这 n 个素数,但如果不添加更多行我无法这样做。
还有一种方法可以不指定 rdx
中 write
的字符串长度,而是让字符串以 /0
?[=17= 结尾]
要附加到文件,请使用 O_APPEND = 0x400
标志作为 rsi
中的 int flags
参数。所以你很接近:它是一个十六进制值 400 而不是你怀疑的十进制值 400。
这是十六进制原始 int flags
值的列表:
O_ACCMODE = 0x3
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000
O_CREAT = 0x40
O_DIRECT = 0x4000
O_DIRECTORY = 0x10000
O_DSYNC = 0x1000
O_EXCL = 0x80
O_FSYNC = 0x101000
O_LARGEFILE = 0x0
O_NDELAY = 0x800
O_NOATIME = 0x40000
O_NOCTTY = 0x100
O_NOFOLLOW = 0x20000
O_NONBLOCK = 0x800
O_RDONLY = 0x0
O_RDWR = 0x2
O_RSYNC = 0x101000
O_SYNC = 0x101000
O_TRUNC = 0x200
O_WRONLY = 0x1
所以这应该有效:
mov rax, 2
lea rdi, [rel path]
mov rsi, 0x441 ; O_CREAT| O_WRONLY | O_APPEND
mov edx, 0q666 ; octal permissions in case O_CREAT has to create it
syscall
mov r8, rax ; save the file descriptor
我添加了三个值来创建文件(如果它不存在)或者以 write_only 模式打开它(如果它存在)。您可以将它们定义为 assemble-time equ
常量,这样您实际上可以在源代码中编写 mov esi, O_CREAT| O_WRONLY | O_APPEND
。
此外,请确保在您包含 O_CREAT 时为第三个参数(权限)提供一个值。否则,文件可能会因其权限而使用随机垃圾创建,可能包括 setuid + exec。通常你传递八进制 666
(NASM 0q666
) 并让用户的 umask 取消对其他和可选组的写权限。
如果您实际上不想打开它来创建它(如果它尚不存在),请省略 O_CREAT。然后它将 return -ENOENT
.
Also is there a way to not specify the length of the string in rdx, but instead have the string be terminated by a /0?
简而言之:没有
创建一个 strlen
函数并将结果传递给 rdx
。内核系统调用将文件描述符上的数据 read/written 作为缓冲区 + 长度,只有路径名作为 C 隐式长度字符串。
我正在创建一个文件,然后使用系统调用打开它。
正在创建:
mov rax, 85
mov rdi, path
mov rsi, 400
syscall
开幕式:
mov rax, 2
mov rdi, path
mov rsi, 2 ; I found somewhere that I should use 400 to append
syscall
mov r8, rax ; save the file handle
写作:
mov rax, 1
mov rdi, r8
mov rsi, output
mov rdx, length
syscall
完成这些步骤后,我自然关闭文件,但是我无法附加到它,每次执行这些操作时它只是重写文件的内容,但是例如我计算了前 n 个素数并将它们存储在一些内存块中,现在我想在文件中写下这 n 个素数,但如果不添加更多行我无法这样做。
还有一种方法可以不指定 rdx
中 write
的字符串长度,而是让字符串以 /0
?[=17= 结尾]
要附加到文件,请使用 O_APPEND = 0x400
标志作为 rsi
中的 int flags
参数。所以你很接近:它是一个十六进制值 400 而不是你怀疑的十进制值 400。
这是十六进制原始 int flags
值的列表:
O_ACCMODE = 0x3
O_APPEND = 0x400
O_ASYNC = 0x2000
O_CLOEXEC = 0x80000
O_CREAT = 0x40
O_DIRECT = 0x4000
O_DIRECTORY = 0x10000
O_DSYNC = 0x1000
O_EXCL = 0x80
O_FSYNC = 0x101000
O_LARGEFILE = 0x0
O_NDELAY = 0x800
O_NOATIME = 0x40000
O_NOCTTY = 0x100
O_NOFOLLOW = 0x20000
O_NONBLOCK = 0x800
O_RDONLY = 0x0
O_RDWR = 0x2
O_RSYNC = 0x101000
O_SYNC = 0x101000
O_TRUNC = 0x200
O_WRONLY = 0x1
所以这应该有效:
mov rax, 2
lea rdi, [rel path]
mov rsi, 0x441 ; O_CREAT| O_WRONLY | O_APPEND
mov edx, 0q666 ; octal permissions in case O_CREAT has to create it
syscall
mov r8, rax ; save the file descriptor
我添加了三个值来创建文件(如果它不存在)或者以 write_only 模式打开它(如果它存在)。您可以将它们定义为 assemble-time equ
常量,这样您实际上可以在源代码中编写 mov esi, O_CREAT| O_WRONLY | O_APPEND
。
此外,请确保在您包含 O_CREAT 时为第三个参数(权限)提供一个值。否则,文件可能会因其权限而使用随机垃圾创建,可能包括 setuid + exec。通常你传递八进制 666
(NASM 0q666
) 并让用户的 umask 取消对其他和可选组的写权限。
如果您实际上不想打开它来创建它(如果它尚不存在),请省略 O_CREAT。然后它将 return -ENOENT
.
Also is there a way to not specify the length of the string in rdx, but instead have the string be terminated by a /0?
简而言之:没有
创建一个 strlen
函数并将结果传递给 rdx
。内核系统调用将文件描述符上的数据 read/written 作为缓冲区 + 长度,只有路径名作为 C 隐式长度字符串。