如何使用 lseek 创建带孔的文件?

Posted

技术标签:

【中文标题】如何使用 lseek 创建带孔的文件?【英文标题】:How to create files with holes using lseek? 【发布时间】:2014-08-14 10:42:36 【问题描述】:

我正在学习如何使用 lseek 在文件中创建漏洞。

这是我目前写的代码……

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>

int main()

    int fd;
    char name[20] = "Harry Potter";

    // Creating a file
    if( (fd = open( "book.txt", O_RDWR | O_CREAT , S_IWRITE | S_IREAD ) < 0 )) 
        printf("\ncreat error");    
    

    // Seeking 100th byte, from the begining of the file
    if ( lseek(fd, 100, SEEK_SET) == -1 ) 
        if (errno != 0) 
            perror("lseek");
         
    

    // Writing to the 100th byte, thereby creating a hole
    if( write(fd, name, sizeof(char)*strlen(name)) != sizeof(char)*strlen(name) ) 
        if (errno != 0) 
            perror("write");
        
    

    // closing the file
    if ( close(fd) == -1 ) 
        if (errno != 0)
            perror("close"); 
    

    return 0;

当我编译并执行这段代码时,我得到一个 lseek 错误,并且名称“哈利波特”没有被插入到文件中。这是我执行上述代码时的输出:

lseek: Illegal seek
Harry Potter

我什至试图捕捉所有错误。 请进一步帮助我。

【问题讨论】:

据我所知,你不能越过文件的末尾,如果你想打一个洞,你应该写 0 个字节......一个“洞”是文件系统所做的不考虑有效... ;) open、lseek、write、close 函数是 POSIX(不在标准 C 中),因此您可以添加该标签。 @LeonardoBernardini 除了“据我所知”部分之外,您写的任何内容都不真实——考虑一下您知道,也没有费心去寻找out ...只需阅读 lseek 手册页就会告诉您,正如 OP 试图做的那样,通过查找过去的写入数据会在文件中创建漏洞......但是有一点语法错误;看我的回答。 我的错误和道歉,我几乎可以肯定这是不可行的...... @Shao:Windows C 也支持它们,只是对标题进行了微小的更改。 【参考方案1】:
if( (fd = open( "book.txt", O_RDWR | O_CREAT , S_IWRITE | S_IREAD ) < 0 )) 

如果打开成功则将 fd 设置为 0,如果打开失败则设置为 1。因为您将它设置为 0,也就是您的控制台,所以它是写“哈利波特”的地方,而不是磁盘。而且你不能在终端上寻找。你想要的

if( (fd = open( "book.txt", O_RDWR | O_CREAT , S_IWRITE | S_IREAD )) < 0 ) 

还有

a) 系统调用失败后无需检查 errno != 0。

b) 你应该在出错时退出而不是失败。

c) sizeof(char) 始终为 1,因此无需乘以它。

d) main 应该有一个原型,例如,int main(void)

【讨论】:

很好看。我想这就是为什么一些编译器会警告嵌入式赋值... @david.pfx 对我来说并不难发现......当我看到哈利波特出现在终端机上时,我 99% 确定我会发现这个优先错误。并且 OP 使用的编译器会发出这样的警告,只要 OP 会要求它(例如,gcc -Wall)。 有趣的是,0 是标准输入的文件描述符,而不是输出。在触发错误的 Windows 上。 @david.pfx 是的,在 fd 0 上看到输出是违反直觉的,但是从古代 UNIX 编程开始的 IIRC,终端以读/写方式打开,然后 fd 被复制以产生 0, 1 和 2。这允许向 stdin 发送提示,即使 stdout 和 stderr 被重定向(现在有 /dev/tty )。 @JimBalter 谢谢。我还会记得提到的另外 4 点。我有检查任何类型大小的习惯,所以这就是我做 sizeof(char) 的原因。我这样做是因为我认为 sizeof(char) 在不同的系统上可能会有所不同。

以上是关于如何使用 lseek 创建带孔的文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何获得带孔的二元掩模的边界坐标?

带孔的 SVG 层

带孔的 GeoJson LineString 特征集合

带孔的 Google-SDK-iOS 多边形

在three.js中将带孔的SVG路径转换为挤压形状

可以在 QML 中的 Map 上绘制带有孔的 MapPolygon 吗?