1#define _LARGEFILE64_SOURCE
2#include <unistd.h>
3#include <string.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include <fcntl.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/ioctl.h>
10#include <sys/stat.h>
11#include <libgen.h>
12#include <linux/hdreg.h>
13#include <linux/types.h>
14#include <linux/fs.h>
15
16struct file_ext {
17	__u32 f_pos;
18	__u32 start_blk;
19	__u32 end_blk;
20	__u32 blk_count;
21};
22
23void print_ext(struct file_ext *ext)
24{
25	if (ext->end_blk == 0)
26		printf("%8d    %8d    %8d    %8d\n", ext->f_pos, 0, 0, ext->blk_count);
27	else
28		printf("%8d    %8d    %8d    %8d\n", ext->f_pos, ext->start_blk,
29					ext->end_blk, ext->blk_count);
30}
31
32void print_stat(struct stat64 *st)
33{
34	printf("--------------------------------------------\n");
35	printf("dev       [%d:%d]\n", major(st->st_dev), minor(st->st_dev));
36	printf("ino       [0x%8lx : %ld]\n", st->st_ino, st->st_ino);
37	printf("mode      [0x%8x : %d]\n", st->st_mode, st->st_mode);
38	printf("nlink     [0x%8lx : %ld]\n", st->st_nlink, st->st_nlink);
39	printf("uid       [0x%8x : %d]\n", st->st_uid, st->st_uid);
40	printf("gid       [0x%8x : %d]\n", st->st_gid, st->st_gid);
41	printf("size      [0x%8lx : %ld]\n", st->st_size, st->st_size);
42	printf("blksize   [0x%8lx : %ld]\n", st->st_blksize, st->st_blksize);
43	printf("blocks    [0x%8lx : %ld]\n", st->st_blocks, st->st_blocks);
44	printf("--------------------------------------------\n\n");
45}
46
47void stat_bdev(struct stat64 *st, unsigned int *start_lba)
48{
49	struct stat bdev_stat;
50	struct hd_geometry geom;
51	char devname[32] = { 0, };
52	char linkname[32] = { 0, };
53	int fd;
54
55	sprintf(devname, "/dev/block/%d:%d", major(st->st_dev), minor(st->st_dev));
56
57	fd = open(devname, O_RDONLY);
58	if (fd < 0)
59		return;
60
61	if (fstat(fd, &bdev_stat) < 0)
62		goto out;
63
64	if (S_ISBLK(bdev_stat.st_mode)) {
65		if (ioctl(fd, HDIO_GETGEO, &geom) < 0)
66			*start_lba = 0;
67		else
68			*start_lba = geom.start;
69	}
70
71	if (readlink(devname, linkname, sizeof(linkname)) < 0)
72		goto out;
73
74	printf("----------------bdev info-------------------\n");
75	printf("devname = %s\n", basename(linkname));
76	printf("start_lba = %u\n", *start_lba);
77
78out:
79	close(fd);
80
81}
82
83int main(int argc, char *argv[])
84{
85	int fd;
86	int ret = 0;
87	char *filename;
88	struct stat64 st;
89	int total_blks;
90	unsigned int i;
91	struct file_ext ext;
92	__u32 start_lba;
93	__u32 blknum;
94
95	if (argc != 2) {
96		fprintf(stderr, "No filename\n");
97		exit(-1);
98	}
99	filename = argv[1];
100
101	fd = open(filename, O_RDONLY|O_LARGEFILE);
102	if (fd < 0) {
103		ret = errno;
104		perror(filename);
105		exit(-1);
106	}
107
108	fsync(fd);
109
110	if (fstat64(fd, &st) < 0) {
111		ret = errno;
112		perror(filename);
113		goto out;
114	}
115
116	stat_bdev(&st, &start_lba);
117
118	total_blks = (st.st_size + st.st_blksize - 1) / st.st_blksize;
119
120	printf("\n----------------file info-------------------\n");
121	printf("%s :\n", filename);
122	print_stat(&st);
123	printf("file_pos   start_blk     end_blk        blks\n");
124
125	blknum = 0;
126	if (ioctl(fd, FIBMAP, &blknum) < 0) {
127		ret = errno;
128		perror("ioctl(FIBMAP)");
129		goto out;
130	}
131	ext.f_pos = 0;
132	ext.start_blk = blknum;
133	ext.end_blk = blknum;
134	ext.blk_count = 1;
135
136	for (i = 1; i < total_blks; i++) {
137		blknum = i;
138
139		if (ioctl(fd, FIBMAP, &blknum) < 0) {
140			ret = errno;
141			perror("ioctl(FIBMAP)");
142			goto out;
143		}
144
145		if ((blknum == 0 && blknum == ext.end_blk) || (ext.end_blk + 1) == blknum) {
146			ext.end_blk = blknum;
147			ext.blk_count++;
148		} else {
149			print_ext(&ext);
150			ext.f_pos = i * st.st_blksize;
151			ext.start_blk = blknum;
152			ext.end_blk = blknum;
153			ext.blk_count = 1;
154		}
155	}
156
157	print_ext(&ext);
158out:
159	close(fd);
160	return ret;
161}
162