+ if (S_ISREG (current_stat.st_mode)
+ || S_ISCTG (current_stat.st_mode))
+ {
+ int f; /* file descriptor */
+ size_t bufsize;
+ ssize_t count;
+ off_t sizeleft;
+ union block *start;
+ int header_moved;
+ char isextended = 0;
+ int upperbound;
+
+ header_moved = 0;
+
+ if (sparse_option)
+ {
+ /* 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);
+ 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_CHARS (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_CHARS (filesize, header->header.size);
+
+ for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
+ {
+ if (!sparsearray[counter].numbytes)
+ break;