Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / client / lib.c
index 9c80d9c..01bc7bf 100644 (file)
 #include <libgnomevfs/gnome-vfs-result.h>
 #include <glib/gmessages.h>
 #include "captive/macros.h"
-#include "reactos/ddk/rtl.h"   /* for InitializeObjectAttributes() */
+#include "reactos/ntos/rtl.h"  /* for InitializeObjectAttributes() */
 #include "captive/unicode.h"
 #include <libgnomevfs/gnome-vfs-utils.h>       /* for gnome_vfs_unescape_string() */
-#include <glib/gprintf.h>
-#include "captive/client.h"
+#include "captive/options.h"
+#include <glib/gstrfuncs.h>
 
 
+/* Returns: g_malloc() allocated absolute pathname string */
+gchar *captive_path_normalize(const gchar *raw_pathname)
+{
+gchar *r,*r_end,*s,*d;
+
+       g_return_val_if_fail(raw_pathname!=NULL,NULL);
+       g_return_val_if_fail(g_path_is_absolute(raw_pathname),NULL);
+
+       r=g_strdup(raw_pathname);
+
+       /* coalesce '/'es */
+       for (d=s=r;*s;s++) {
+               if (*s==G_DIR_SEPARATOR && d>r && d[-1]==G_DIR_SEPARATOR)
+                       continue;
+               *d++=*s;
+               }
+       g_assert(d>r);
+       if (d>(r+1) && d[-1]==G_DIR_SEPARATOR)
+               d--;
+       *d++=G_DIR_SEPARATOR;
+       r_end=d;
+
+       /* 'r' is NOT NULL-terminated here! */
+
+       for (d=s=r+1;s<r_end;) {
+               if (!strncmp(s-1,"/./",3)) {
+                       s+=2;
+                       continue;
+                       }
+               if (!strncmp(s-1,"/../",4)) {
+                       s+=3;
+                       g_assert(d[-1]==G_DIR_SEPARATOR);
+                       if (d>r+1) {
+                               do {
+                                       d--;
+                                       } while (d[-1]!=G_DIR_SEPARATOR);
+                               }
+                       continue;
+                       }
+               *d++=*s++;
+               }
+       g_assert(d[-1]==G_DIR_SEPARATOR);       /* trailing '/' */
+       if (d>r+1)      /* leave at least "/" */
+               d--;
+       *d='\0';
+
+       g_assert(g_path_is_absolute(r));
+
+       return r;
+}
+
 /* function will leave g_malloc()ed 'ObjectAttributes->ObjectName'!
  */
 GnomeVFSResult captive_ObjectAttributes_init(const gchar *pathname,OBJECT_ATTRIBUTES *ObjectAttributes)
 {
 gchar *w32_path,*s,*d;
 const gchar *media_root;
+gchar *pathname_normalized;
 
        g_return_val_if_fail(pathname!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
        g_return_val_if_fail(ObjectAttributes!=NULL,GNOME_VFS_ERROR_BAD_PARAMETERS);
@@ -50,8 +102,10 @@ const gchar *media_root;
         * and later IopCreateFile() would not consider it FO_DIRECT_DEVICE_OPEN (e.g. w/o any direct mount!).
         * On the other side it will somehow get managed automatically and it works even
         * without the trailing "\\." for root directory open - don't ask me why. :-)
+        * Tested: \\Device\\CaptiveHarddisk0\\. FAIL
+        *         \\Device\\CaptiveHarddisk0\\  OK
         */
-       switch (captive_option_media) {
+       switch (captive_options->media) {
                case CAPTIVE_OPTION_MEDIA_CDROM: media_root="\\Device\\CdRom0";           break;        /* libcaptive/storage/cdrom.c */
                case CAPTIVE_OPTION_MEDIA_DISK:  media_root="\\Device\\CaptiveHarddisk0"; break;        /* libcaptive/storage/disk.c */
                default:
@@ -59,8 +113,10 @@ const gchar *media_root;
                        media_root="";
                }
 
+       pathname_normalized=captive_path_normalize(pathname);
        w32_path=(gchar *)/* de-const it as we can modify it but we must not free() it */
-                       captive_printf_alloca("%s\\%s",media_root,pathname);
+                       captive_printf_alloca("%s\\%s",media_root,pathname_normalized);
+       g_free(pathname_normalized);
        /* translate '/' -> '\' */
        for (s=w32_path;(s=strchr(s,'/'));s++)
                *s='\\';
@@ -78,3 +134,24 @@ const gchar *media_root;
 
        return GNOME_VFS_OK;
 }
+
+
+void captive_giochannel_setup(GIOChannel *giochannel)
+{
+GIOStatus erriostatus;
+
+       g_return_if_fail(giochannel!=NULL);
+
+       if (g_io_channel_get_encoding(giochannel)) {
+               if (!g_io_channel_get_buffered(giochannel))     /* Prevent: Need to have NULL encoding to set the buffering state ... */
+                       g_io_channel_set_buffered(giochannel,TRUE);     /* Prevent: Need to set the channel buffered before setting the encoding. */
+               erriostatus=g_io_channel_set_encoding(giochannel,
+                               NULL,   /* encoding; force binary data */
+                               NULL);  /* error */
+               g_assert(erriostatus==G_IO_STATUS_NORMAL);
+               }
+       erriostatus=g_io_channel_flush(giochannel,
+                       NULL);  /* error */
+       g_assert(erriostatus==G_IO_STATUS_NORMAL);
+       g_io_channel_set_buffered(giochannel,FALSE);
+}