X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Ffilefrag.c;h=27675b198e7579ab5c5e28495cc883d625af1c6c;hb=a2ff0f31c1987a480ffc4dacb7adf93f0aecf7f6;hp=043e0ba269ec9bfc62d2757fec9bcf3c2831a731;hpb=9642413014c0c037339c392cdc20343c4e80f079;p=tools%2Fe2fsprogs.git diff --git a/misc/filefrag.c b/misc/filefrag.c index 043e0ba..27675b1 100644 --- a/misc/filefrag.c +++ b/misc/filefrag.c @@ -9,6 +9,15 @@ * %End-Header% */ +#ifndef __linux__ +#include +#include + +int main(void) { + fputs("This program is only supported on Linux!\n", stderr); + exit(EXIT_FAILURE); +} +#else #define _LARGEFILE64_SOURCE #include @@ -18,9 +27,16 @@ #include #include #include +#ifdef HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif #include #include #include +#include #include int verbose = 0; @@ -28,13 +44,23 @@ int verbose = 0; #define FIBMAP _IO(0x00,1) /* bmap access */ #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ +#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ +#define EXT3_IOC_GETFLAGS _IOR('f', 1, long) + +static unsigned int div_ceil(unsigned int a, unsigned int b) +{ + if (!a) + return 0; + return ((a - 1) / b) + 1; +} + static unsigned long get_bmap(int fd, unsigned long block) { int ret; - unsigned long b; + unsigned int b; b = block; - ret = ioctl(fd, FIBMAP, &b); + ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes a pointer to an integer */ if (ret < 0) { if (errno == EPERM) { fprintf(stderr, "No permission to use FIBMAP ioctl; must have root privileges\n"); @@ -47,21 +73,32 @@ static unsigned long get_bmap(int fd, unsigned long block) #define EXT2_DIRECT 12 -void frag_report(const char *filename) +static void frag_report(const char *filename) { struct statfs fsinfo; +#ifdef HAVE_FSTAT64 struct stat64 fileinfo; - long i, fd, bs, block, last_block, numblocks; +#else + struct stat fileinfo; +#endif + int bs; + long fd; + unsigned long block, last_block = 0, numblocks, i; long bpib; /* Blocks per indirect block */ long cylgroups; int discont = 0, expected; int is_ext2 = 0; + unsigned int flags; if (statfs(filename, &fsinfo) < 0) { perror("statfs"); return; } +#ifdef HAVE_FSTAT64 if (stat64(filename, &fileinfo) < 0) { +#else + if (stat(filename, &fileinfo) < 0) { +#endif perror("stat"); return; } @@ -73,31 +110,46 @@ void frag_report(const char *filename) (fsinfo.f_type == 0xef53)) is_ext2++; if (verbose) { - printf("Filesystem type is: %lx\n", fsinfo.f_type); + printf("Filesystem type is: %lx\n", + (unsigned long) fsinfo.f_type); } - cylgroups = (fsinfo.f_blocks + fsinfo.f_bsize*8-1) / fsinfo.f_bsize*8; + cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize*8); if (verbose) { printf("Filesystem cylinder groups is approximately %ld\n", cylgroups); } - fd = open(filename, O_RDONLY | O_LARGEFILE); +#ifdef HAVE_OPEN64 + fd = open64(filename, O_RDONLY); +#else + fd = open(filename, O_RDONLY); +#endif if (fd < 0) { perror("open"); return; } - if (ioctl(fd, FIGETBSZ, &bs) < 0) { + if (ioctl(fd, FIGETBSZ, &bs) < 0) { /* FIGETBSZ takes an int */ perror("FIGETBSZ"); + close(fd); return; } + if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0) + flags = 0; + if (flags & EXT4_EXTENTS_FL) { + printf("File is stored in extents format\n"); + is_ext2 = 0; + } if (verbose) printf("Blocksize of file %s is %d\n", filename, bs); bpib = bs / 4; numblocks = (fileinfo.st_size + (bs-1)) / bs; - if (verbose) - printf("File size of %s is %lld (%d blocks)\n", filename, + if (verbose) { + printf("File size of %s is %lld (%ld blocks)\n", filename, (long long) fileinfo.st_size, numblocks); + printf("First block: %lu\nLast block: %lu\n", + get_bmap(fd, 0), get_bmap(fd, numblocks - 1)); + } for (i=0; i < numblocks; i++) { - if (is_ext2) { + if (is_ext2 && last_block) { if (((i-EXT2_DIRECT) % bpib) == 0) last_block++; if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0) @@ -106,14 +158,15 @@ void frag_report(const char *filename) last_block++; } block = get_bmap(fd, i); - if (i && (block != last_block +1) ) { + if (block == 0) + continue; + if (last_block && (block != last_block +1) ) { if (verbose) - printf("Discontinuity: Block %ld is at %ld (was %ld)\n", + printf("Discontinuity: Block %ld is at %lu (was %lu)\n", i, block, last_block); discont++; } - if (block) - last_block = block; + last_block = block; } if (discont==0) printf("%s: 1 extent found", filename); @@ -125,10 +178,10 @@ void frag_report(const char *filename) (expected>1) ? "s" : ""); else fputc('\n', stdout); - + close(fd); } -void usage(const char *progname) +static void usage(const char *progname) { fprintf(stderr, "Usage: %s [-v] file ...\n", progname); exit(1); @@ -157,6 +210,4 @@ int main(int argc, char**argv) } return 0; } - - - +#endif