+captive_giochannel_size(): detect 'GIOChannel' file/device size
authorshort <>
Thu, 12 Dec 2002 03:59:22 +0000 (03:59 +0000)
committershort <>
Thu, 12 Dec 2002 03:59:22 +0000 (03:59 +0000)
src/libcaptive/storage/Makefile.am
src/libcaptive/storage/size.c [new file with mode: 0644]

index a1a09e0..78e1c81 100644 (file)
@@ -21,4 +21,5 @@ include $(top_srcdir)/src/libcaptive/Makefile-libcaptive.am
 
 noinst_LTLIBRARIES=libstorage.la
 libstorage_la_SOURCES= \
-               cdrom.c
+               cdrom.c \
+               size.c
diff --git a/src/libcaptive/storage/size.c b/src/libcaptive/storage/size.c
new file mode 100644 (file)
index 0000000..47948e9
--- /dev/null
@@ -0,0 +1,74 @@
+/* $Id$
+ * Detect media size of given GIOChannel for libcaptive
+ * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+
+#include "captive/storage.h"   /* self */
+#include <glib/gmessages.h>
+#include <glib/gtypes.h>
+
+
+guint64 captive_giochannel_size(GIOChannel *iochannel)
+{
+gint fd;
+gint64 low,high,mid;
+GIOStatus erriostatus;
+gchar bufchar;
+gsize bufchargot;
+
+       g_return_val_if_fail(iochannel!=NULL,0);
+
+       fd=g_io_channel_unix_get_fd(iochannel);
+       g_return_val_if_fail(fd!=-1,0);
+
+       /* FIXME: TODO: ioctl() detection */
+
+       /* low  ==high: low (high)
+        * low+1==high: mid==low; NORMAL: no change: high
+        * low+1==high: mid==low; EOF   : high=mid => 'low==high' case
+        */
+       for (low=0,
+                       high=
+                                       G_MAXINT;       /* FIXME: 'G_MAXINT64' fails on g_io_channel_seek_position() */
+                       low+1<high;) {
+               mid=low+(high-low)/2;   /* beware of 'gint64' overflow! */
+
+               erriostatus=g_io_channel_seek_position(iochannel,mid,G_SEEK_SET,
+                               NULL);  /* error */
+               g_assert(erriostatus==G_IO_STATUS_NORMAL);
+               g_assert(sizeof(bufchar)==1);
+               erriostatus=g_io_channel_read_chars(iochannel,
+                               &bufchar, /* buf */
+                               sizeof(bufchar),        /* count */
+                               &bufchargot,    /* bytes_read */
+                               NULL);  /* error */
+               g_assert(erriostatus==G_IO_STATUS_NORMAL || erriostatus==G_IO_STATUS_EOF);
+               g_assert(0
+                               || (erriostatus==G_IO_STATUS_NORMAL && bufchargot==1)
+                               || (erriostatus==G_IO_STATUS_EOF    && bufchargot==0));
+
+               if (erriostatus==G_IO_STATUS_NORMAL)
+                       low=mid;
+               else
+                       high=mid;
+               }
+       
+       g_assert(high>=0);
+       return high;
+}