Re: large device major/minor numbers not supported



Koblinger Egmont wrote:
Code in question probably is in screen.c, just after line 200. How do we
know stat is using 12 + 20 bytes and not 8 + 8?

I tested my patch on NetBSD and Solaris. Hope it works for you, too.

Roland
Index: configure.ac
===================================================================
RCS file: /cvsroot/mc/mc/configure.ac,v
retrieving revision 1.18
diff -u -p -u -r1.18 configure.ac
--- configure.ac	3 Dec 2004 05:45:21 -0000	1.18
+++ configure.ac	21 Jan 2005 09:52:41 -0000
@@ -152,7 +152,7 @@ AC_PROG_INSTALL
 AC_CHECK_HEADERS([unistd.h string.h memory.h grp.h limits.h malloc.h \
 	stdlib.h termios.h utime.h fcntl.h pwd.h sys/statfs.h sys/time.h \
 	sys/timeb.h sys/select.h sys/ioctl.h stropts.h arpa/inet.h \
-	security/pam_misc.h sys/socket.h])
+	security/pam_misc.h sys/socket.h sys/types.h sys/mkdev.h])
 
 AC_HEADER_TIME
 AC_HEADER_SYS_WAIT
Index: src/screen.c
===================================================================
RCS file: /cvsroot/mc/mc/src/screen.c,v
retrieving revision 1.199
diff -u -p -u -r1.199 screen.c
--- src/screen.c	16 Nov 2004 23:54:15 -0000	1.199
+++ src/screen.c	21 Jan 2005 09:52:44 -0000
@@ -45,6 +45,7 @@
 #include "execute.h"
 #include "widget.h"
 #include "menu.h"		/* menubar_visible */
+#include "utilunix.h"
 #define WANT_WIDGETS
 #include "main.h"		/* the_menubar */
 
@@ -190,6 +191,43 @@ string_file_name (file_entry *fe, int le
     return buffer;
 }
 
+static inline int ilog10(dev_t n)
+{
+    int digits = 1;
+    do {
+	digits++, n /= 10;
+    } while (n != 0);
+    return digits;
+}
+
+static void format_device_number (char *buf, size_t bufsize, dev_t dev)
+{
+    dev_t maj_dev = major(dev);
+    dev_t min_dev = minor(dev);
+    int maj_digits = ilog10(major(~((dev_t)0)));
+    int min_digits = ilog10(minor(~((dev_t)0)));
+
+    g_assert(bufsize >= 1);
+    if (maj_digits + 1 + min_digits + 1 <= bufsize) {
+    	g_snprintf(buf, bufsize, "%*lu,%*lu",
+	    maj_digits, (unsigned long) maj_dev,
+	    min_digits, (unsigned long) min_dev);
+    } else {
+        int maj_used_digits = ilog10(major(dev));
+        int min_used_digits = ilog10(minor(dev));
+	if (maj_used_digits + 1 + min_used_digits + 1 <= bufsize) {
+	    g_snprintf(buf, bufsize, "%lu,%lu",
+		(unsigned long) maj_dev,
+		(unsigned long) min_dev);
+	} else if (maj_digits + 1 + 3 + 1 <= bufsize) {
+	    g_snprintf(buf, bufsize, "%*lu,~~~",
+		maj_digits, (unsigned long) maj_dev);
+	} else {
+            g_snprintf(buf, bufsize, "[dev]");
+	}
+    }
+}
+
 /* size */
 static const char *
 string_file_size (file_entry *fe, int len)
@@ -203,9 +241,7 @@ string_file_size (file_entry *fe, int le
 
 #ifdef HAVE_STRUCT_STAT_ST_RDEV
     if (S_ISBLK (fe->st.st_mode) || S_ISCHR (fe->st.st_mode))
-        g_snprintf (buffer, sizeof (buffer), "%3d,%3d",
-		    (int) ((fe->st.st_rdev >> 8) & 0xff),
-		    (int) (fe->st.st_rdev & 0xff));
+        format_device_number (buffer, len + 1, fe->st.st_rdev);
     else
 #endif
     {
#ifndef MC_UTILUNIX_H
#define MC_UTILUNIX_H

/* The major/minor macros are not specified in SUSv3, so we can only hope
 * they are provided by the operating system or emulate it.
 */

#include <sys/types.h>		/* BSD */
#ifdef HAVE_SYS_MKDEV_H
# include <sys/mkdev.h>		/* Solaris 9 */
#endif

#ifndef major
# define major(devnum) (((devnum) >> 8) & 0xff)
#endif
#ifndef minor
# define minor(devnum) (((devnum) & 0xff)
#endif

#endif


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