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

时间:2015-09-08 19:30:05

标签: c filesystems ioctl

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

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

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>

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);
}

任何帮助表示感谢。

2 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

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

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

您不进行任何错误检查也无济于事。

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

此代码正常运行:

e2fslibs-dev

请记住以root用户身份运行。

<强>更新

Giuseppe Guerrini中建议his answer,您可能希望使用#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <linux/fs.h> #include <ext2fs/ext2_fs.h> 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; } ,而不需要包含FS_IMMUTABLE_FL

ext2_fs.h