在C中使用ioctl()设置不可变标志

我试图创建一个创建文件的脚本,然后将其设置为不可变的,类似于linux的chattr +i命令。 脚本编译 (使用gcc), 运行创建文件 。 但是文件本身不是不可变的,可以使用简单的rm -f 删除 。 我试图在chattr调用chattr地方找到一个名为ioctl的函数。 然后,我使用了我可以收集的一些小信息,并提出了我在下面的内容。 我从ext2_fs.h缩小了它,但它似乎不起作用。 我显然忽视了一些事情。

对上一个条目的更新编译但在ioctl()函数上返回-1perror()显示错误的地址

 #include  #include  #include  #include  #include  int main() { FILE *fp; char shovel[16] = "I have a shovel!"; fp = fopen("/shovel.txt", "w+"); fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp); ioctl(fileno(fp), FS_IOC_SETFLAGS, 0x00000010); fclose(fp); } 

任何帮助赞赏。

主要问题是ioctl想要一个指向掩码的指针 ,而不是直接常量。 您必须定义一个int变量,将掩码( 0x10 )存储在其中并将其地址作为ioctl第三个参数传递。

另外,我会添加一些提示:

  • 其他更改属性的程序用于直接使用低级I / O(打开,关闭…)。 此外,该文件通常使用O_RDONLY打开。
  • 使用FS_IMMUTABLE_FL不是原始常量。
  • 首先获取当前属性掩码( FS_IOC_SETFLAGS )并使用新标志对其进行掩码,以便服务不会丢失其他设置。

您正在使用正确的ioctl命令,但是您传递了错误的参数。

ioctl_list(2)的联机帮助页显示FS_IOC_SETFLAGS期望接收指向intint * )的指针,但是您传递的是整数文字(因此是Bad Address错误)。

你不做任何错误检查的事实也没有帮助。

传递给FS_IOC_SETFLAGS的正确标志是一个保存值EXT2_IMMUTABLE_FL的指针,该值在ext2fs/ext2_fs.h定义(一些较旧/不同的Linux发行版似乎在linux/ext2_fs.h ),所以你需要#include 。 确保安装e2fslibs-dev (可能你也需要linux-headers)。

这段代码有效:

 #include  #include  #include  #include  #include  #include  int main() { FILE *fp; char shovel[16] = "I have a shovel!"; if ((fp = fopen("shovel.txt", "w+")) == NULL) { perror("fopen(3) error"); exit(EXIT_FAILURE); } fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp); int val = EXT2_IMMUTABLE_FL; if (ioctl(fileno(fp), FS_IOC_SETFLAGS, &val) < 0) perror("ioctl(2) error"); fclose(fp); return 0; } 

记得以root身份运行它。

更新

正如Giuseppe Guerrini在他的回答中建议的那样,您可能想要使用FS_IMMUTABLE_FL ,而您不需要包含ext2_fs.h

 #include  #include  #include  #include  #include  int main() { FILE *fp; char shovel[16] = "I have a shovel!"; if ((fp = fopen("shovel.txt", "w+")) == NULL) { perror("fopen(3) error"); exit(EXIT_FAILURE); } fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp); int val = FS_IMMUTABLE_FL; if (ioctl(fileno(fp), FS_IOC_SETFLAGS, &val) < 0) perror("ioctl(2) error"); fclose(fp); return 0; }