changeset 93689:40434d3c3093

(Ffile_attributes): Support inode numbers wider than 32 bits. Remove ugly WINDOWSNT-specific kludge introduced on 2008-03-14 to force inode be positive.
author Eli Zaretskii <eliz@gnu.org>
date Sat, 05 Apr 2008 14:31:42 +0000
parents 3961ad1ac8f2
children c9e7cd4c092d
files src/dired.c
diffstat 1 files changed, 27 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/dired.c	Sat Apr 05 12:03:23 2008 +0000
+++ b/src/dired.c	Sat Apr 05 14:31:42 2008 +0000
@@ -919,8 +919,10 @@
  8. File modes, as a string of ten letters or dashes as in ls -l.
  9. t if file's gid would change if file were deleted and recreated.
 10. inode number.  If inode number is larger than the Emacs integer,
-  this is a cons cell containing two integers: first the high part,
-  then the low 16 bits.
+  but still fits into a 32-bit number, this is a cons cell containing two
+  integers: first the high part, then the low 16 bits.  If the inode number
+  is wider than 32 bits, this is a cons cell containing three integers:
+  first the high 24 bits, then middle 24 bits, and finally the low 16 bits.
 11. Device number.  If it is larger than the Emacs integer, this is
   a cons cell, similar to the inode number.  */)
      (filename, id_format)
@@ -1021,25 +1023,32 @@
   values[9] = (gid != getegid ()) ? Qt : Qnil;
 #endif	/* BSD4_2 (or BSD4_3) */
   /* Shut up GCC warnings in FIXNUM_OVERFLOW_P below.  */
-#ifdef WINDOWSNT
-  {
-    /* The bit-shuffling we do in w32.c:stat can turn on the MSB, which
-       will produce negative inode numbers.  People don't like that, so
-       force a positive inode instead.  */
-    unsigned short tem = s.st_ino;
-    ino = tem;
-  }
-#else
-  ino = s.st_ino;
-#endif
-  if (FIXNUM_OVERFLOW_P (ino))
+  if (sizeof (s.st_ino) > sizeof (ino))
+    ino = (EMACS_INT)(s.st_ino & 0xffffffff);
+  else
+    ino = s.st_ino;
+  if (!FIXNUM_OVERFLOW_P (ino)
+      && (sizeof (s.st_ino) <= sizeof (ino) || (s.st_ino & ~INTMASK) == 0))
+    /* Keep the most common cases as integers.  */
+    values[10] = make_number (ino);
+  else if (sizeof (s.st_ino) <= sizeof (ino)
+	   || ((s.st_ino >> 16) & ~INTMASK) == 0)
     /* To allow inode numbers larger than VALBITS, separate the bottom
        16 bits.  */
-    values[10] = Fcons (make_number (ino >> 16),
-			make_number (ino & 0xffff));
+    values[10] = Fcons (make_number ((EMACS_INT)(s.st_ino >> 16)),
+			make_number ((EMACS_INT)(s.st_ino & 0xffff)));
   else
-    /* But keep the most common cases as integers.  */
-    values[10] = make_number (ino);
+    {
+      /* To allow inode numbers beyond 32 bits, separate into 2 24-bit
+	 high parts and a 16-bit bottom part.  */
+      EMACS_INT high_ino = s.st_ino >> 32;
+      EMACS_INT low_ino  = s.st_ino & 0xffffffff;
+
+      values[10] = Fcons (make_number (high_ino >> 8),
+			  Fcons (make_number (((high_ino & 0xff) << 16)
+					      + (low_ino >> 16)),
+				 make_number (low_ino & 0xffff)));
+    }
 
   /* Likewise for device.  */
   if (FIXNUM_OVERFLOW_P (s.st_dev))