- /* Check the size of the file against the number of blocks
- allocated for it, counting both data and indirect blocks.
- If there is a smaller number of blocks that would be
- necessary to accommodate a file of this size, this is safe
- to say that we have a sparse file: at least one of those
- blocks in the file is just a useless hole. For sparse
- files not having more hole blocks than indirect blocks, the
- sparseness will go undetected. */
-
- /* Bruno Haible sent me these statistics for Linux. It seems
- that some filesystems count indirect blocks in st_blocks,
- while others do not seem to:
-
- minix-fs tar: size=7205, st_blocks=18 and ST_NBLOCKS=18
- extfs tar: size=7205, st_blocks=18 and ST_NBLOCKS=18
- ext2fs tar: size=7205, st_blocks=16 and ST_NBLOCKS=16
- msdos-fs tar: size=7205, st_blocks=16 and ST_NBLOCKS=16
-
- Dick Streefland reports the previous numbers as misleading,
- because ext2fs use 12 direct blocks, while minix-fs uses only
- 6 direct blocks. Dick gets:
-
- ext2 size=20480 ls listed blocks=21
- minix size=20480 ls listed blocks=21
- msdos size=20480 ls listed blocks=20
-
- It seems that indirect blocks *are* included in st_blocks.
- The minix filesystem does not account for phantom blocks in
- st_blocks, so `du' and `ls -s' give wrong results. So, the
- --sparse option would not work on a minix filesystem. */
-
- if (ST_NBLOCKS (current_stat)
- < (current_stat.st_size / ST_NBLOCKSIZE
- + (current_stat.st_size % ST_NBLOCKSIZE != 0)))
- {
- off_t filesize = current_stat.st_size;
- int counter;
-
- header = start_header (p, ¤t_stat);
- if (header == NULL)
- {
- exit_status = TAREXIT_FAILURE;
- return;
- }
- header->header.typeflag = GNUTYPE_SPARSE;
- header_moved = 1;
-
- /* Call the routine that figures out the layout of the
- sparse file in question. UPPERBOUND is the index of the
- last element of the "sparsearray," i.e., the number of
- elements it needed to describe the file. */
-
- upperbound = deal_with_sparse (p, header);
-
- /* See if we'll need an extended header later. */
-
- if (upperbound > SPARSES_IN_OLDGNU_HEADER - 1)
- header->oldgnu_header.isextended = 1;
-
- /* We store the "real" file size so we can show that in
- case someone wants to list the archive, i.e., tar tvf
- <file>. It might be kind of disconcerting if the
- shrunken file size was the one that showed up. */
-
- OFF_TO_OCT (current_stat.st_size,
- header->oldgnu_header.realsize);
-
- /* This will be the new "size" of the file, i.e., the size
- of the file minus the blocks of holes that we're
- skipping over. */
-
- find_new_file_size (&filesize, upperbound);
- current_stat.st_size = filesize;
- OFF_TO_OCT (filesize, header->header.size);
-
- for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
- {
- if (!sparsearray[counter].numbytes)
- break;
-
- OFF_TO_OCT (sparsearray[counter].offset,
- header->oldgnu_header.sp[counter].offset);
- SIZE_TO_OCT (sparsearray[counter].numbytes,
- header->oldgnu_header.sp[counter].numbytes);
- }
-
- }