在 C 中使用 ioctl() 设置不可变标志
Setting Immutable Flag using ioctl() in C
我试图创建一个脚本来创建一个文件,然后将其设置为不可变,类似于 linux 的 chattr +i
命令。 脚本编译(使用 gcc),运行并创建文件。但是 文件 本身 不是不可变的,可以通过简单的 rm -f
删除 。我试图在调用 chattr
的地方进行堆栈跟踪,我发现了一个名为 ioctl
的函数。然后,我使用了我能收集到的少量信息,并得出了下面的结论。我从 ext2_fs.h
缩小了它的范围,但它似乎不起作用。我显然忽略了一些东西。
对先前条目的更新:编译但returns-1 ioctl() 函数。 地址错误 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);
}
感谢任何帮助。
主要问题是 ioctl
需要一个指向 掩码的 指针,而不是直接常量。您必须定义一个 int 变量,将掩码 (0x10
) 存储在其中并将其地址作为 ioctl
.
的第三个参数传递
此外,我会添加一些提示:
- 其他改变属性的程序直接使用低级I/O(打开,关闭...)。此外,该文件通常使用
O_RDONLY
打开。
- 使用
FS_IMMUTABLE_FL
代替原始常量。
- 首先获取当前属性掩码 (
FS_IOC_SETFLAGS
) 并用新标志对其进行掩码,这样服务就不会丢失其他设置。
您使用了正确的 ioctl 命令,但传递给它的参数错误。
ioctl_list(2)
的联机帮助页显示 FS_IOC_SETFLAGS
期望收到指向 int
的指针(一个 int *
),但您向它传递了一个整数文字(因此 Bad Address 错误)。
您不进行任何错误检查这一事实也无济于事。
传递给 FS_IOC_SETFLAGS
的正确标志是一个指针,其中包含值 EXT2_IMMUTABLE_FL
,它在 ext2fs/ext2_fs.h
中定义(一些较旧的/不同的 Linux 发行版似乎放在 linux/ext2_fs.h
下),所以你需要 #include <ext2fs/etx2_fs.h>
。确保安装 e2fslibs-dev
(您可能还需要 linux-headers)。
此代码有效:
#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;
}
记住 运行 这是 root。
更新:
作为 Giuseppe Guerrini suggests in ,您可能想改用 FS_IMMUTABLE_FL
,并且不需要包括 ext2_fs.h
:
#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!";
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;
}
我试图创建一个脚本来创建一个文件,然后将其设置为不可变,类似于 linux 的 chattr +i
命令。 脚本编译(使用 gcc),运行并创建文件。但是 文件 本身 不是不可变的,可以通过简单的 rm -f
删除 。我试图在调用 chattr
的地方进行堆栈跟踪,我发现了一个名为 ioctl
的函数。然后,我使用了我能收集到的少量信息,并得出了下面的结论。我从 ext2_fs.h
缩小了它的范围,但它似乎不起作用。我显然忽略了一些东西。
对先前条目的更新:编译但returns-1 ioctl() 函数。 地址错误 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);
}
感谢任何帮助。
主要问题是 ioctl
需要一个指向 掩码的 指针,而不是直接常量。您必须定义一个 int 变量,将掩码 (0x10
) 存储在其中并将其地址作为 ioctl
.
此外,我会添加一些提示:
- 其他改变属性的程序直接使用低级I/O(打开,关闭...)。此外,该文件通常使用
O_RDONLY
打开。 - 使用
FS_IMMUTABLE_FL
代替原始常量。 - 首先获取当前属性掩码 (
FS_IOC_SETFLAGS
) 并用新标志对其进行掩码,这样服务就不会丢失其他设置。
您使用了正确的 ioctl 命令,但传递给它的参数错误。
ioctl_list(2)
的联机帮助页显示 FS_IOC_SETFLAGS
期望收到指向 int
的指针(一个 int *
),但您向它传递了一个整数文字(因此 Bad Address 错误)。
您不进行任何错误检查这一事实也无济于事。
传递给 FS_IOC_SETFLAGS
的正确标志是一个指针,其中包含值 EXT2_IMMUTABLE_FL
,它在 ext2fs/ext2_fs.h
中定义(一些较旧的/不同的 Linux 发行版似乎放在 linux/ext2_fs.h
下),所以你需要 #include <ext2fs/etx2_fs.h>
。确保安装 e2fslibs-dev
(您可能还需要 linux-headers)。
此代码有效:
#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;
}
记住 运行 这是 root。
更新:
作为 Giuseppe Guerrini suggests in FS_IMMUTABLE_FL
,并且不需要包括 ext2_fs.h
:
#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!";
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;
}