[PATCH] corrupted free inodes list



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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]