In the other article Get inode number of a given file, in this article, I will show an example how to get a given file's physical disk block numbers.

The basic idea is to open the given file, use stat function to get the number of blocks in 512, then convert it to io block number(4k, adjust it for your own filesystem if your linux kernel page size is not 4k), the print out each pair of logical and physical block number.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>

/*
 * * get_block - for the file associated with the given fd, returns the physical block mapping to logical_block
 */

int get_block (int fd, int logical_block)
{
        int ret;
        ret = ioctl (fd, FIBMAP, &logical_block);
        if (ret <0 ){
                perror ("ioctl");
                return -1;
        }
        return logical_block;
}

/*
 * get_nr_blocks - returns the number of logical blocks
 * consumed by the file associated with fd
 */
int get_nr_blocks (int fd)
{
        struct stat buf;
        int ret,blocks_in_4k;
        ret = fstat (fd, &buf);
        if ( ret < 0 ) {
                perror ("fstat");
                return -1;
        }
        blocks_in_4k = buf.st_blocks/8;
        return blocks_in_4k;
}

/*
 * print_blocks - for each logical block consumed by the file
 * associated with fd, prints to standard out the tuple
 * "(logical block, physical block)"
 */
void  print_blocks (int fd)
{
        int nr_blocks,i;
        int f_phys_block,e_phys_block;
        nr_blocks = get_nr_blocks (fd);

        if (nr_blocks <0 ) {
                fprintf (stderr, "get_nr_blocks failed!\n");
                return;
        }

        if (nr_blocks == 0) {
                printf( "no allocated blocks\n");
                return;

        } else if ( nr_blocks == 1)
                printf ("1 block\n\n");
        else
                printf ("this file has %d blocks\n\n",nr_blocks);

        for (i =0; i <nr_blocks; i++) {
                int phys_block;
                phys_block = get_block (fd, i );
                if (phys_block <0 ) {
                        fprintf (stderr, "get_block failed!\n");
                        return;
                }
                if ( !phys_block)
                        continue;
                if ( i == 0 )
                        f_phys_block=phys_block;
                if ( i == nr_blocks -1 )
                        e_phys_block=phys_block;
                printf ("(%u, %u)\n",i,phys_block);
        }

        if ( nr_blocks != e_phys_block - f_phys_block + 1) {
                printf ("\nthis file is fragmented \n");
                printf ("total blocks <%u>,first physical block <%u>, the last physical block <%u>\n",nr_blocks,f_phys_block,e_phys_block);
        }
        putchar ('\n');
}

int main (int argc, char *argv[] )
{
        int fd;

        if (argc <2 ) {
                fprintf (stderr, "usage: %s <file>\n",argv[0]);
        }

        fd = open (argv[1],O_RDONLY);
        if (fd <0) {
                perror ("open");
                return 1;
        }
        print_blocks(fd);

        return 0;
}

Compile and run:

#cc get_pblock.c -o get_pblock
 #./get_pblock xfs_irecover.c
this file has 4 blocks

(0, 113295548)
(1, 113295549)
(2, 113295550)
(3, 113295551)