Hi

I've found on three machines (I wonder that no one noticed it so far) that mc displays incorrect information on inode count, for example:

|  Filesystem: /                       |
|  Device:    /dev/md0                 |
|  Type:      ext2                     |
|  Free space: 161G (0%) of 552G       |
|  Free nodes: 32864471 (-27%) of 364380

|  Filesystem: /home                   |
|  Device:    /dev/md0                 |
|  Type:      xfs                      |
|  Free space: 15G (13%) of 117G       |
|  Free nodes: 64702776 (-31%) of 669767

|  Filesystem: COMMON:/                |
|  Device:    DISK1-P2:/               |
|  Type:      SPADFS                   |
|  Free space: 36G (40%) of 88G        |
|  Free nodes: 74794575 (-5%) of 1850848

--- the bug is obviously caused by integer overflow when multiplying by 100. When I further investigated the code, I found that it stores free space and free inode count only in "int" variable --- it will cause problems with devices with more than 2^31 blocks (they already exists, but I don't have such). --- so I fixed both block and inode display to use double instead --- after aplying the patch, the output looks sane:

|  Filesystem: HOME:/                  |
|  Device:    DISK1-P2:/               |
|  Type:      SPADFS                   |
|  Free space: 36G (40%) of 88G        |
|  Free nodes: 71M (40%) of 177M       |

--- maybe you could change double to "long long" but I'm not sure if it exists on all machines --- a configure test would probably be needed.

Mikulas
diff -u -r x/mc-4.6.1/src/info.c mc-4.6.1/src/info.c
--- x/mc-4.6.1/src/info.c       2006-12-20 02:53:44.000000000 +0200
+++ mc-4.6.1/src/info.c 2006-12-20 03:08:30.000000000 +0200
@@ -99,13 +99,15 @@
 
     case 16:
        widget_move (&info->widget, 16, 3);
-       if (myfs_stats.nfree >0 && myfs_stats.nodes > 0)
-           printw (const_cast(char *, _("Free nodes: %d (%d%%) of %d")),
-                   myfs_stats.nfree,
-                   myfs_stats.total
-                   ? 100 * myfs_stats.nfree / myfs_stats.nodes : 0,
-                   myfs_stats.nodes);
-       else
+       if (myfs_stats.nfree >0 && myfs_stats.nodes > 0){
+           char buffer1 [6], buffer2[6];
+           size_trunc_len (buffer1, 5, myfs_stats.nfree, 0);
+           size_trunc_len (buffer2, 5, myfs_stats.nodes, 0);
+           printw (const_cast(char *, _("Free nodes: %s (%d%%) of %s")),
+                   buffer1,
+                   (int)(100 * myfs_stats.nfree / myfs_stats.nodes),
+                   buffer2);
+       } else
            addstr (_("No node information"));
        
     case 15:
@@ -114,8 +116,9 @@
            char buffer1 [6], buffer2[6];
            size_trunc_len (buffer1, 5, myfs_stats.avail, 1);
            size_trunc_len (buffer2, 5, myfs_stats.total, 1);
-           printw (const_cast(char *, _("Free space: %s (%d%%) of %s")), 
buffer1, myfs_stats.total ?
-                   (int)(100 * (double)myfs_stats.avail / myfs_stats.total) : 
0,
+           printw (const_cast(char *, _("Free space: %s (%d%%) of %s")),
+                   buffer1,
+                   (int)(100 * myfs_stats.avail / myfs_stats.total),
                    buffer2);
        } else
            addstr (_("No space information"));
diff -u -r x/mc-4.6.1/src/mountlist.c mc-4.6.1/src/mountlist.c
--- x/mc-4.6.1/src/mountlist.c  2006-12-20 02:53:44.000000000 +0200
+++ mc-4.6.1/src/mountlist.c    2006-12-20 02:57:20.000000000 +0200
@@ -132,11 +132,11 @@
 
 struct fs_usage
 {
-  long fsu_blocks;             /* Total blocks. */
-  long fsu_bfree;              /* Free blocks available to superuser. */
-  long fsu_bavail;             /* Free blocks available to non-superuser. */
-  long fsu_files;              /* Total file nodes. */
-  long fsu_ffree;              /* Free file nodes. */
+  double fsu_blocks;           /* Total blocks. */
+  double fsu_bfree;            /* Free blocks available to superuser. */
+  double fsu_bavail;           /* Free blocks available to non-superuser. */
+  double fsu_files;            /* Total file nodes. */
+  double fsu_ffree;            /* Free file nodes. */
 };
 
 static int get_fs_usage (char *path, struct fs_usage *fsp);
@@ -663,8 +663,8 @@
    BLOCKS FROMSIZE-byte blocks, rounding away from zero.
    TOSIZE must be positive.  Return -1 if FROMSIZE is not positive.  */
 
-static long
-fs_adjust_blocks (long blocks, int fromsize, int tosize)
+static double
+fs_adjust_blocks (double blocks, int fromsize, int tosize)
 {
     if (tosize <= 0)
        abort ();
@@ -676,7 +676,7 @@
     else if (fromsize > tosize)        /* E.g., from 2048 to 512.  */
        return blocks * (fromsize / tosize);
     else                       /* E.g., from 256 to 512.  */
-       return (blocks + (blocks < 0 ? -1 : 1)) / (tosize / fromsize);
+       return blocks / (tosize / fromsize);
 }
 
 #if defined(_AIX) && defined(_I386)
diff -u -r X/MC-4.6.1/SRC/MOUNTLIST.H MC-4.6.1/SRC/MOUNTLIST.H
--- x/mc-4.6.1/src/mountlist.h  2006-12-20 02:53:44.000000000 +0200
+++ mc-4.6.1/src/mountlist.h    2006-12-20 02:57:38.000000000 +0200
@@ -24,10 +24,10 @@
     char *typename;
     const char *mpoint;
     const char *device;
-    int avail;
-    int total;
-    int nfree;
-    int nodes;
+    double avail;
+    double total;
+    double nfree;
+    double nodes;
 };
 
 void init_my_statfs (void);
diff -u -r X/MC-4.6.1/SRC/UTIL.C MC-4.6.1/SRC/UTIL.C
--- x/mc-4.6.1/src/util.c       2006-12-20 02:53:44.000000000 +0200
+++ mc-4.6.1/src/util.c 2006-12-20 03:02:49.000000000 +0200
@@ -314,7 +314,7 @@
  *    0=bytes, 1=Kbytes, 2=Mbytes, etc.
  */
 void
-size_trunc_len (char *buffer, int len, off_t size, int units)
+size_trunc_len (char *buffer, int len, double size, int units)
 {
     /* Avoid taking power for every file.  */
     static const off_t power10 [] =
@@ -329,7 +329,7 @@
        len = 9;
 
     for (j = units; suffix [j] != NULL; j++) {
-       if (size == 0) {
+       if (size < 0.5) {
            if (j == units) {
                /* Empty files will print "0" even with minimal width.  */
                g_snprintf (buffer, len + 1, "0");
@@ -342,13 +342,13 @@
            break;
        }
 
-       if (size < power10 [len - (j > 0)]) {
+       if (size < power10 [len - (j > 0)] && size <= MAXULONG) {
            g_snprintf (buffer, len + 1, "%lu%s", (unsigned long) size, 
suffix[j]);
            break;
        }
 
        /* Powers of 1024, with rounding.  */
-       size = (size + 512) >> 10;
+       size = (size + 512) / 1024;
     }
 }
 
diff -u -r x/mc-4.6.1/src/util.h mc-4.6.1/src/util.h
--- x/mc-4.6.1/src/util.h       2006-12-20 02:53:44.000000000 +0200
+++ mc-4.6.1/src/util.h 2006-12-20 03:02:59.000000000 +0200
@@ -47,7 +47,7 @@
  * not including trailing 0. BUFFER should be at least LEN+1 long.
  *
  * Units: size units (0=bytes, 1=Kbytes, 2=Mbytes, etc.) */
-void size_trunc_len (char *buffer, int len, off_t size, int units);
+void size_trunc_len (char *buffer, int len, double size, int units);
 int  is_exe (mode_t mode);
 const char *string_perm (mode_t mode_bits);
 
_______________________________________________
Mc-devel mailing list
http://mail.gnome.org/mailman/listinfo/mc-devel

Reply via email to