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