通过写入无意中创建巨大的文件

时间:2016-09-07 14:47:57

标签: c linux system-calls

这是我正在使用的代码:

 #include <stdio.h>
 #include <stdlib.h>
 void main(){
  test = creat("TEST",0751);
  close(test);
  test = open("TEST",2);
  write(test, "123456789101112131415",21);
  lseek(test,-2,2);
  read(test,swap_array,2);
  write(test,swap_array,2);
  lseek(test,-6, 1);
  write(test,"xx",2);
 }

这会创建一个8gb文件,而不是插入&#34; xx&#34;在我想要的数字之间。我的代码有什么问题?

2 个答案:

答案 0 :(得分:3)

您未能包含相应的头文件。你应该至少包括:

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>

此外,这将使您可以访问使代码可维护所需的符号常量。

以下是您的计划的工作版本:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


int main() {
 char swap_array[2];
 int test = creat("TEST",0751);
 close(test);
 test = open("TEST",O_RDWR);
 write(test, "123456789101112131415",21);
 lseek(test,-2,SEEK_END);
 read(test,swap_array,2);
 write(test,swap_array,2);
 lseek(test,-6, SEEK_CUR);
 write(test,"xx",2);
 return 0;
}

答案 1 :(得分:3)

您可能没有包含标题,因此范围内lseek()可能没有原型,因此中间参数中的2int,但lseek() } {(1> longoff_t,你在64位机器上sizeof(int) != sizeof(long)所以这两个2被系统调用误解(可能将它们视为偏移量,无论出于何种原因,堆栈上剩下的内容被解释为SEEK_SET或以其他方式跳转到较大的偏移量。)

基本上,您可能会将不准确的类型信息传递给系统调用,因为您没有包含正确的标头。经典(在POSIX干扰之前),中间2将为2L,因为l中的lseek()代表“长” - 在此之前,有{{1}使用普通seek()(在16位int类型的日子里) - 确保将int作为lseek()传递 需要。这些天,long需要lseek();使用原型对于确保您编写的内容正确解释为off_t

至关重要

在该描述中潜伏着很多UB,但是你没有使用off_t等事实会引发警告标志。另外,为什么文件可执行?这看起来不像你正在编写的可执行代码。

此代码变体更加谨慎(并且不会在Mac OS X 10.11.6上使用GCC 6.2.0创建8 GiB文件)。

SEEK_SET

我使用#include <fcntl.h> #include <sys/stat.h> #include <unistd.h> #define MODE_0751 (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH) int main(void) { // All error checking omitted char swap_array[2]; int test = creat("TEST", MODE_0751); close(test); test = open("TEST", O_RDWR); write(test, "123456789101112131415", 21); lseek(test, -2L, SEEK_END); read(test, swap_array, 2); write(test, swap_array, 2); lseek(test, -6L, SEEK_CUR); write(test, "xx", 2); close(test); return 0; } 的(非常)旧习惯,但它们是可选的。各种2可以由L(和sizeof(swap_array))替换。我很久以前就学会了C语言,八进制权限是开展业务的唯一方式; sizeof("xx")-1和相关名称是未来几年。我发现一个4位或5位八进制数字比一串S_IRWXU名称更易读。

确保使用选项集编译代码,以便在使用函数之前需要原型。例如,我使用:

S_Iwxyz