Whamcloud - gitweb
Don't write changes to the backup superblocks by default
[tools/e2fsprogs.git] / misc / filefrag.c
index 8463efd..27675b1 100644 (file)
@@ -44,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");
@@ -66,18 +76,29 @@ static unsigned long get_bmap(int fd, unsigned long block)
 static void frag_report(const char *filename)
 {
        struct statfs   fsinfo;
+#ifdef HAVE_FSTAT64
        struct stat64   fileinfo;
-       long            i, fd, bs, block, last_block = 0, 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;
        }
@@ -89,35 +110,46 @@ static void frag_report(const char *filename)
            (fsinfo.f_type == 0xef53))
                is_ext2++;
        if (verbose) {
-               printf("Filesystem type is: %x\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 %ld\n", filename, bs);
+               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 (%ld blocks)\n", filename, 
                       (long long) fileinfo.st_size, numblocks);
-               printf("First block: %ld\nLast block: %ld\n",
+               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)
@@ -126,14 +158,15 @@ static void frag_report(const char *filename)
                                last_block++;
                }
                block = get_bmap(fd, i);
-               if (i && block && (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);