Add block device support to file_getfilesize on Linux
[mono.git] / mono / io-layer / io.c
index 7f3846d8fa80cd4c73218df5e1a9677632ee5f25..e060a7d3724205f07768a0c4454352471cb2dc73 100644 (file)
 #include <fnmatch.h>
 #include <stdio.h>
 #include <utime.h>
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#endif
 
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
@@ -798,6 +802,34 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
                return(INVALID_FILE_SIZE);
        }
        
+       /* fstat indicates block devices as zero-length, so go a different path */
+#ifdef BLKGETSIZE64
+       if (S_ISBLK(statbuf.st_mode)) {
+               guint64 bigsize;
+               if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
+#ifdef DEBUG
+                       g_message ("%s: handle %p ioctl BLKGETSIZE64 failed: %s",
+                                  __func__, handle, strerror(errno));
+#endif
+
+                       _wapi_set_last_error_from_errno ();
+                       return(INVALID_FILE_SIZE);
+               }
+               
+               size = bigsize & 0xFFFFFFFF;
+               if (highsize != NULL) {
+                       *highsize = bigsize>>32;
+               }
+
+#ifdef DEBUG
+               g_message ("%s: Returning block device size %d/%d",
+                          __func__, size, *highsize);
+#endif
+       
+               return(size);
+       }
+#endif
+       
 #ifdef HAVE_LARGE_FILE_SUPPORT
        size = statbuf.st_size & 0xFFFFFFFF;
        if (highsize != NULL) {