how to make holes in file to erase data by c in li

2019-07-20 13:18发布

问题:

Updated: This FALLOC_FL_PUNCH_HOLE is not originally supported by 3.0.0-17, I think I need to patch it.

I know linux have this hole feature, and I am wondering if I could make a hole in a existing file.

For specific, I have created a file named hole_test by these codes:

 18 #include <stdlib.h>
 19 #include <sys/types.h>
 20 #include <sys/stat.h>
 21 #include <fcntl.h>
 22 #include <unistd.h>
 23 #include <errno.h>
 24 
 25 int main(int argc, char **argv)
 26 {
 27     int fd;
 28     char a[7]="happy!";
 30     fd = open("hole_test", O_CREAT|O_RDWR, 0666);
 31     if(fd == -1)
 32             printf("error, %s\n", (char *)strerror(errno));
 35 //  fallocate(fd, 0x02, 0,0);
 36 //  pwrite(fd, a, sizeof(a), 0);
 37 //  pwrite(fd, a, sizeof(b), 65536);
 38     close(fd);
 39     return 0;
 40 }

firstly, I user L36 L37 to create a file. the stat hole_test shows that:

  File: `hole_test'
  Size: 65540       Blocks: 16         IO Block: 4096   regular file
Device: 801h/2049d  Inode: 1052101     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/   bxshi)   Gid: ( 1000/   bxshi)
Access: 2012-04-03 23:02:35.227664608 +0800
Modify: 2012-04-03 23:02:35.227664608 +0800
Change: 2012-04-03 23:02:35.227664608 +0800

Then I use L35 and comment L36 L37 to make a hole in my file.(0x02 equals to FALLOC_FL_PUNCH_HOLE, I did not find where it is defined so just use its value)

and then, by stat hole_test, the Blocks is still 16.

  File: `hole_test'
  Size: 65540       Blocks: 16         IO Block: 4096   regular file
Device: 801h/2049d  Inode: 1052101     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/   bxshi)   Gid: ( 1000/   bxshi)
Access: 2012-04-03 23:02:35.227664608 +0800
Modify: 2012-04-03 23:02:35.227664608 +0800
Change: 2012-04-03 23:02:35.227664608 +0800

I want to know if I could make new holes in this hole_test file to erase existing data?

How could I make a hole in hole_test at offset 0 to 7, in that way I think the Blocks could become 8 and the string I wrote would disappear.

Hope you guys could know what I said and give me some advice.

回答1:

You use fallocate(fd, FALLOC_FL_PUNCH_HOLE, offset, len). (Supported since Linux 2.6.38) See https://lwn.net/Articles/415889/ for behind-the-scenes details and accompanying patches.



回答2:

According to the man page for fallocate(2):

The FALLOC_FL_PUNCH_HOLE flag must be ORed with FALLOC_FL_KEEP_SIZE in mode; in other words, even when punching off the end of the file, the file size (as reported by stat(2)) does not change.

At least on ext4, if you just pass FALLOC_FL_PUNCH_HOLE, fallocate() will return Operation not supported.

Also note that:

The FALLOC_FL_* flags are defined in glibc headers only since version 2.18.

So you may need to manually define them if you're using a supported kernel with an earlier version of libc:

// Constants are defined in glibc >= 2.18
#define FALLOC_FL_KEEP_SIZE    0x1
#define FALLOC_FL_PUNCH_HOLE   0x2