[gvfs] afp: work on query_info



commit b0cb95e48964c65c17bfb0f2534284878add46cd
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date:   Fri Jun 17 22:04:28 2011 +0200

    afp: work on query_info

 daemon/gvfsafpconnection.c    |    2 +-
 daemon/gvfsafpconnection.h    |    1 +
 daemon/gvfsafpserver.c        |   30 ++--
 daemon/gvfsbackendafp.c       |  130 ++++++++++++++-
 daemon/gvfsbackendafpbrowse.c |  371 +++++++++++++++++++++++++---------------
 5 files changed, 376 insertions(+), 158 deletions(-)
---
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
index 88998fd..f9caeb4 100644
--- a/daemon/gvfsafpconnection.c
+++ b/daemon/gvfsafpconnection.c
@@ -321,7 +321,7 @@ dispatch_reply (GVfsAfpConnection *afp_connection)
     RequestData *req_data;
 
     /* Send back a tickle message */
-    req_data = g_slice_new (RequestData);
+    req_data = g_slice_new0 (RequestData);
     req_data->tickle = TRUE;
 
     g_queue_push_head (priv->request_queue, req_data);
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
index 365464b..14b5502 100644
--- a/daemon/gvfsafpconnection.h
+++ b/daemon/gvfsafpconnection.h
@@ -47,6 +47,7 @@ typedef enum
 {
   AFP_COMMAND_GET_SRVR_INFO = 15,
   AFP_COMMAND_GET_SRVR_PARMS = 16,
+  AFP_COMMAND_GET_VOL_PARMS = 17,
   AFP_COMMAND_LOGIN = 18,
   AFP_COMMAND_LOGIN_CONT = 19,
   AFP_COMMAND_OPEN_VOL = 24,
diff --git a/daemon/gvfsafpserver.c b/daemon/gvfsafpserver.c
index 334efab..aebedd5 100644
--- a/daemon/gvfsafpserver.c
+++ b/daemon/gvfsafpserver.c
@@ -795,19 +795,29 @@ g_vfs_afp_server_login (GVfsAfpServer *afp_serv,
 
   while (TRUE)
   {
+    GString *str;
     GAskPasswordFlags flags;
     gboolean aborted;
 
-    if (prompt == NULL)
+    g_free (prompt);
+
+    str = g_string_new (NULL);
+
+    if (err)
     {
-      /* create prompt */
-      if (initial_user)
-        /* Translators: the first %s is the username, the second the host name */
-        prompt = g_strdup_printf (_("Enter password for afp as %s on %s"), initial_user, afp_serv->server_name);
-      else
-        /* translators: %s here is the hostname */
-        prompt = g_strdup_printf (_("Enter password for afp on %s"), afp_serv->server_name);
+      g_string_append_printf (str, "%s\n", err->message);
+      g_clear_error (&err);
     }
+    
+    /* create prompt */
+    if (initial_user)
+      /* Translators: the first %s is the username, the second the host name */
+      g_string_append_printf (str, _("Enter password for afp as %s on %s"), initial_user, afp_serv->server_name);
+    else
+      /* translators: %s here is the hostname */
+      g_string_append_printf (str, _("Enter password for afp on %s"), afp_serv->server_name);
+
+    prompt = g_string_free (str, FALSE);
 
     flags = G_ASK_PASSWORD_NEED_PASSWORD;
 
@@ -855,9 +865,7 @@ try_login:
     {
       g_vfs_afp_connection_close (afp_serv->conn, cancellable, NULL);
 
-      if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
-        g_clear_error (&err);
-      else
+      if (!g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
         break;
     }
     else
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index c7f8dc4..d8d3412 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -33,8 +33,7 @@
 
 #include "gvfsjobmount.h"
 #include "gvfsjobenumerate.h"
-#include "gvfsjobmountmountable.h"
-#include "gmounttracker.h"
+#include "gvfsjobqueryinfo.h"
 
 #include "gvfsafpserver.h"
 #include "gvfsafpconnection.h"
@@ -55,11 +54,125 @@ struct _GVfsBackendAfp
 	char               *user;
 
   GVfsAfpServer      *server;
+
+  guint32 volume_id;
 };
 
 
 G_DEFINE_TYPE (GVfsBackendAfp, g_vfs_backend_afp, G_VFS_TYPE_BACKEND);
 
+static gboolean
+is_root (const char *filename)
+{
+  const char *p;
+
+  p = filename;
+  while (*p == '/')
+    p++;
+
+  return *p == 0;
+}
+
+static void
+get_vol_parms_cb (GVfsAfpConnection *afp_connection,
+                  GVfsAfpReply      *reply,
+                  GError            *error,
+                  gpointer           user_data)
+{
+  GVfsJobQueryInfo *job = G_VFS_JOB_QUERY_INFO (user_data);
+  GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (job->backend);
+
+  AfpResultCode res_code;
+  GFileInfo *info;
+  guint32 create_date, mod_date;
+  
+  if (!reply)
+  {
+    g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+    return;
+  }
+
+  res_code = g_vfs_afp_reply_get_result_code (reply);
+  if (res_code != AFP_RESULT_NO_ERROR)
+  {
+    g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+                              G_IO_ERROR_FAILED, _("Fetching of volume parameters failed"));
+    return;
+  }
+
+  info = job->file_info;
+
+  g_file_info_set_name (info, afp_backend->volume);
+  
+  /* CreateDate is in apple time e.g. seconds since Januari 1 1904 */
+  create_date = g_data_input_stream_read_uint32 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED,
+                                    create_date - 2082844800);
+
+  /* ModDate is in apple time e.g. seconds since Januari 1 1904 */
+  mod_date = g_data_input_stream_read_uint32 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                                    mod_date - 2082844800);
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+                GVfsJobQueryInfo *job,
+                const char *filename,
+                GFileQueryInfoFlags flags,
+                GFileInfo *info,
+                GFileAttributeMatcher *matcher)
+{
+  GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
+  
+  g_debug ("filename: %s\n", filename);
+  
+  if (is_root (filename))
+  {
+    GIcon *icon;
+
+    g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+    g_file_info_set_name (info, "/");
+    g_file_info_set_display_name (info, g_vfs_backend_get_display_name (backend));
+    g_file_info_set_content_type (info, "inode/directory");
+    icon = g_vfs_backend_get_icon (backend);
+    if (icon != NULL)
+      g_file_info_set_icon (info, icon);
+
+    if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_TIME_CREATED) ||
+        g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_TIME_MODIFIED))
+    {
+      GVfsAfpCommand *comm;
+      AfpVolumeBitmap bitmap;
+      
+      comm = g_vfs_afp_command_new (AFP_COMMAND_GET_VOL_PARMS);
+      /* pad byte */
+      g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
+      /* Volume ID */
+      g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (comm),
+                                       afp_backend->volume_id, NULL, NULL);
+
+      bitmap = AFP_VOLUME_BITMAP_CREATE_DATE_BIT | AFP_VOLUME_BITMAP_MOD_DATE_BIT;
+      g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (comm), bitmap, NULL, NULL);
+
+      g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
+                                          get_vol_parms_cb, G_VFS_JOB (job)->cancellable,
+                                          job);
+      return TRUE;
+    }
+
+    g_vfs_job_succeeded (G_VFS_JOB (job));
+    return TRUE;
+  }
+  else {
+    /* TODO: query info for files */
+    g_vfs_job_succeeded (G_VFS_JOB (job));
+    return TRUE;
+  }
+}
+
 static void
 do_mount (GVfsBackend *backend,
           GVfsJobMount *job,
@@ -93,9 +206,7 @@ do_mount (GVfsBackend *backend,
   g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
   
   /* Volume Bitmap */
-  vol_bitmap = AFP_VOLUME_BITMAP_VOL_ID_BIT | AFP_VOLUME_BITMAP_CREATE_DATE_BIT |
-    AFP_VOLUME_BITMAP_MOD_DATE_BIT | AFP_VOLUME_BITMAP_EXT_BYTES_FREE_BIT |
-    AFP_VOLUME_BITMAP_EXT_BYTES_TOTAL_BIT;
+  vol_bitmap = AFP_VOLUME_BITMAP_VOL_ID_BIT;
   g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (comm), vol_bitmap,
                                    NULL, NULL);
 
@@ -125,7 +236,10 @@ do_mount (GVfsBackend *backend,
   /* Volume Bitmap */
   g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
 
-  /* TODO: get ID etc. */
+  afp_backend->volume_id =
+    g_data_input_stream_read_uint16 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  g_debug ("volume_id: %d", afp_backend->volume_id);
+  
   g_object_unref (reply);
   
   /* set mount info */
@@ -215,7 +329,8 @@ try_mount (GVfsBackend *backend,
 static void
 g_vfs_backend_afp_init (GVfsBackendAfp *object)
 {
-   GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (object);
+  GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (object);
+  
   afp_backend->volume = NULL;
   afp_backend->user = NULL;
 
@@ -246,6 +361,7 @@ g_vfs_backend_afp_class_init (GVfsBackendAfpClass *klass)
 
 	backend_class->try_mount = try_mount;
   backend_class->mount = do_mount;
+  backend_class->try_query_info = try_query_info;
 }
 
 void
diff --git a/daemon/gvfsbackendafpbrowse.c b/daemon/gvfsbackendafpbrowse.c
index 4940361..2db0ce9 100644
--- a/daemon/gvfsbackendafpbrowse.c
+++ b/daemon/gvfsbackendafpbrowse.c
@@ -32,6 +32,7 @@
 #endif
 
 #include "gvfsjobmount.h"
+#include "gvfsjobqueryinfo.h"
 #include "gvfsjobenumerate.h"
 #include "gvfsjobmountmountable.h"
 #include "gmounttracker.h"
@@ -55,12 +56,27 @@ struct _GVfsBackendAfpBrowse
 
   GMountTracker      *mount_tracker;
   GVfsAfpServer      *server;
+
+  GSList *volumes;
 };
 
 
 G_DEFINE_TYPE (GVfsBackendAfpBrowse, g_vfs_backend_afp_browse, G_VFS_TYPE_BACKEND);
 
 
+typedef struct
+{
+  char *name;
+  guint16 flags;
+} VolumeData;
+
+static void
+volume_data_free (VolumeData *vol_data)
+{
+  g_free (vol_data->name);
+  g_slice_free (VolumeData, vol_data);
+}
+
 static gboolean
 is_root (const char *filename)
 {
@@ -72,37 +88,109 @@ is_root (const char *filename)
 
   return *p == 0;
 }
+typedef void (*UpdateCacheCb) (GVfsBackendAfpBrowse *afp_backend,
+                                 GError               *error,
+                                 gpointer              user_data);
+
+typedef struct
+{
+  GVfsBackendAfpBrowse *afp_backend;
+  gpointer user_data;
+  UpdateCacheCb cb;
+} UpdateCacheData;
 
 static void
-mount_get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
-                         GVfsAfpReply      *reply,
-                         GError            *error,
-                         gpointer           user_data)
+get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
+                   GVfsAfpReply      *reply,
+                   GError            *error,
+                   gpointer           user_data)
 {
-  GVfsJobMountMountable *job = G_VFS_JOB_MOUNT_MOUNTABLE (user_data);
-  GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (job->backend);
+  UpdateCacheData *data = (UpdateCacheData *)user_data;
 
   AfpResultCode res_code;
-  char *filename, *end;
-  guint len;
   guint8 num_volumes, i;
 
   if (!reply)
   {
-    g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+    data->cb (data->afp_backend, error, data->user_data);
+    g_slice_free (UpdateCacheData, data);
     return;
   }
 
   res_code = g_vfs_afp_reply_get_result_code (reply);
   if (res_code != AFP_RESULT_NO_ERROR)
   {
-    g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
-                              G_IO_ERROR_FAILED, _("Volume enumeration failed"));
+    GError *err;
+
+    err = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
+                               _("Retrieval of server parameters failed"));
+    data->cb (data->afp_backend, err, data->user_data);
+
+    g_error_free (err);
+    g_slice_free (UpdateCacheData, data);
     return;
   }
+  
+  /* server time */
+  (void)g_data_input_stream_read_int32 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
 
-  filename = job->filename;
+  g_slist_free_full (data->afp_backend->volumes, (GDestroyNotify) volume_data_free);
+  data->afp_backend->volumes = NULL;
   
+  num_volumes = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+  for (i = 0; i < num_volumes; i++)
+  {
+    guint8 flags;
+    char *vol_name;
+
+    VolumeData *volume_data;
+
+    flags = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
+    vol_name = g_vfs_afp_reply_read_pascal (reply);
+    if (!vol_name)
+      continue;
+
+    volume_data = g_slice_new (VolumeData);
+    volume_data->flags = flags;
+    volume_data->name = vol_name;
+
+    data->afp_backend->volumes = g_slist_prepend (data->afp_backend->volumes, volume_data);
+  }
+
+  data->cb (data->afp_backend, NULL, data->user_data);
+  g_slice_free (UpdateCacheData, data);
+}
+
+static void
+update_cache (GVfsBackendAfpBrowse *afp_backend, GCancellable *cancellable,
+              UpdateCacheCb cb, gpointer user_data)
+{
+  GVfsAfpCommand *comm;
+  UpdateCacheData *data;
+
+  data = g_slice_new (UpdateCacheData);
+  data->afp_backend = afp_backend;
+  data->cb = cb;
+  data->user_data = user_data;
+  
+  comm = g_vfs_afp_command_new (AFP_COMMAND_GET_SRVR_PARMS);
+  /* pad byte */
+  g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
+  
+  g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
+                                      get_srvr_parms_cb,
+                                      cancellable, data);
+  g_object_unref (comm); 
+}
+
+static VolumeData *
+find_volume (GVfsBackendAfpBrowse *afp_backend,
+             char *filename)
+{
+  char *end;
+  guint len;
+  GSList *l;
+
   while (*filename == '/')
     filename++;
 
@@ -115,59 +203,63 @@ mount_get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
       end++;
 
     if (*end != 0)
-      return;
+      return NULL;
   }
   else
     len = strlen (filename);
-  
-  /* server time */
-  (void)g_data_input_stream_read_int32 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
 
-  num_volumes = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
-  for (i = 0; i < num_volumes; i++)
+  for (l = afp_backend->volumes; l; l = g_slist_next (l))
   {
-    char *vol_name;
+    VolumeData *vol_data = (VolumeData *)l->data;
 
-    /* flags*/
-    g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
-    
-    vol_name = g_vfs_afp_reply_read_pascal (reply);
-    if (!vol_name)
-      continue;
+    if (strlen (vol_data->name) == len && strncmp (vol_data->name, filename, len) == 0)
+      return vol_data;
+  }
+
+  return NULL;
+}
+static void
+mount_mountable_cb (GVfsBackendAfpBrowse *afp_backend,
+                    GError *error,
+                    gpointer user_data)
+{
+  GVfsJobMountMountable *job = G_VFS_JOB_MOUNT_MOUNTABLE (user_data);
+
+  VolumeData *vol_data;
+  GMountSpec *mount_spec;
+  
+  if (error != NULL)
+  {
+    g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+    return;
+  }
 
-    if (strlen (vol_name) == len && strncmp (vol_name, filename, len) == 0)
-    {
-      GMountSpec *mount_spec;
-      
-      mount_spec = g_mount_spec_new ("afp-volume");
-      g_mount_spec_set (mount_spec, "host",
-                        g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr)));
-      g_mount_spec_set (mount_spec, "volume", vol_name);
-
-      g_vfs_job_mount_mountable_set_target (job, mount_spec, "/", TRUE);
-      g_mount_spec_unref (mount_spec);
-      
-      g_vfs_job_succeeded (G_VFS_JOB (job));
-
-      g_free (vol_name);
-      return;
-    }
-
-    g_free (vol_name);
+  vol_data = find_volume (afp_backend, job->filename);
+  if (!vol_data)
+  {
+    g_vfs_job_failed (G_VFS_JOB (job),  G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+                      _("File doesn't exist"));
+    return;
   }
 
-  g_vfs_job_failed (G_VFS_JOB (job),  G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-			 _("File doesn't exist"));
+  mount_spec = g_mount_spec_new ("afp-volume");
+  g_mount_spec_set (mount_spec, "host",
+                    g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr)));
+  g_mount_spec_set (mount_spec, "volume", vol_data->name);
+
+  g_vfs_job_mount_mountable_set_target (job, mount_spec, "/", TRUE);
+  g_mount_spec_unref (mount_spec);
+
+  g_vfs_job_succeeded (G_VFS_JOB (job));
 }
 
 static gboolean
 try_mount_mountable (GVfsBackend *backend,
-		     GVfsJobMountMountable *job,
-		     const char *filename,
-		     GMountSource *mount_source)
+                     GVfsJobMountMountable *job,
+                     const char *filename,
+                     GMountSource *mount_source)
 {
   GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend);
-  GVfsAfpCommand *comm;
   
   if (is_root (filename))
   {
@@ -177,108 +269,85 @@ try_mount_mountable (GVfsBackend *backend,
     return TRUE;
   }
 
-  comm = g_vfs_afp_command_new (AFP_COMMAND_GET_SRVR_PARMS);
-  /* pad byte */
-  g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
-
-  g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
-                                      mount_get_srvr_parms_cb,
-                                      G_VFS_JOB (job)->cancellable, job);
+  update_cache (afp_backend, G_VFS_JOB (job)->cancellable, mount_mountable_cb, job);
 
   return TRUE;
                                       
 }
 
 static void
-get_srvr_parms_cb (GVfsAfpConnection *afp_connection,
-                   GVfsAfpReply      *reply,
-                   GError            *error,
-                   gpointer           user_data)
+fill_info (GFileInfo *info, VolumeData *vol_data, GVfsBackendAfpBrowse *afp_backend)
 {
-  GVfsJobEnumerate *job = G_VFS_JOB_ENUMERATE (user_data);
-  GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (job->backend);
+  GIcon *icon;
+  GMountSpec *mount_spec;
+  char *uri;
 
-  AfpResultCode res_code;
-  guint8 num_volumes, i;
+  g_file_info_set_name (info, vol_data->name);
+  g_file_info_set_display_name (info, vol_data->name);
+  g_file_info_set_edit_name (info, vol_data->name);
+  g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
+  g_file_info_set_content_type (info, "inode/directory");
+  g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE);
 
-  if (!reply)
+  g_file_info_set_attribute_boolean (info, "afp::volume-password-protected", (vol_data->flags & 0x01));
+
+  icon = g_themed_icon_new_with_default_fallbacks ("folder-remote-afp");
+  g_file_info_set_icon (info, icon);
+  g_object_unref (icon);
+
+  mount_spec = g_mount_spec_new ("afp-volume");
+  g_mount_spec_set (mount_spec, "host",
+                    g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr)));
+  g_mount_spec_set (mount_spec, "volume", vol_data->name);
+
+  if (g_mount_tracker_has_mount_spec (afp_backend->mount_tracker, mount_spec))
   {
-    g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
-    return;
+    g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, FALSE);
+    g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, TRUE);
+  }
+  else
+  {
+    g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, TRUE);
+    g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, FALSE);
   }
+  g_mount_spec_unref (mount_spec);
+
+  uri = g_strdup_printf ("afp://%s/%s",
+                         g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr)),
+                         vol_data->name);
+  g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
+                                    uri);
+  g_free (uri);
+}
 
-  res_code = g_vfs_afp_reply_get_result_code (reply);
-  if (res_code != AFP_RESULT_NO_ERROR)
+static void
+enumerate_cache_updated_cb (GVfsBackendAfpBrowse *afp_backend,
+                            GError *error,
+                            gpointer user_data)
+{
+  GVfsJobEnumerate *job = G_VFS_JOB_ENUMERATE (user_data);
+
+  GSList *l;
+
+  if (error != NULL)
   {
-    g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
-                              G_IO_ERROR_FAILED, _("Volume enumeration failed"));
+    g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
     return;
   }
 
   g_vfs_job_succeeded (G_VFS_JOB (job));
   
-  /* server time */
-  (void)g_data_input_stream_read_int32 (G_DATA_INPUT_STREAM (reply), NULL, NULL);
-
-  num_volumes = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
-  for (i = 0; i < num_volumes; i++)
+  for (l = afp_backend->volumes; l; l = l->next)
   {
-    guint8 flags;
-    char *vol_name;
-
+    VolumeData *vol_data = l->data;
+    
     GFileInfo *info;
-    GIcon *icon;
-    GMountSpec *mount_spec;
-    char *uri;
 
-    flags = g_data_input_stream_read_byte (G_DATA_INPUT_STREAM (reply), NULL, NULL);
-    vol_name = g_vfs_afp_reply_read_pascal (reply);
-    if (!vol_name)
-      continue;
-    
     info = g_file_info_new ();
-    
-    g_file_info_set_name (info, vol_name);
-    g_file_info_set_display_name (info, vol_name);
-    g_file_info_set_edit_name (info, vol_name);
-    g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
-    g_file_info_set_content_type (info, "inode/directory");
-    g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE);
-
-    g_file_info_set_attribute_boolean (info, "afp::volume-password-protected", (flags & 0x01));
-
-    icon = g_themed_icon_new_with_default_fallbacks ("folder-remote-afp");
-    g_file_info_set_icon (info, icon);
-    g_object_unref (icon);
-    
-    mount_spec = g_mount_spec_new ("afp-volume");
-    g_mount_spec_set (mount_spec, "host",
-                      g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr)));
-    g_mount_spec_set (mount_spec, "volume", vol_name);
-
-    if (g_mount_tracker_has_mount_spec (afp_backend->mount_tracker, mount_spec))
-    {
-      g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, FALSE);
-      g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, TRUE);
-    }
-    else
-    {
-      g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT, TRUE);
-      g_file_info_set_attribute_boolean(info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT, FALSE);
-    }
-    g_mount_spec_unref (mount_spec);
-
-    uri = g_strdup_printf ("afp://%s/%s",
-                           g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr)),
-                           vol_name);
-    g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
-                                      uri);
-    g_free (uri);
-
+    fill_info (info, vol_data, afp_backend);
     g_vfs_job_enumerate_add_info (job, info);
+    
     g_object_unref (info);
-
-    g_free (vol_name);
   }
 
   g_vfs_job_enumerate_done (job);
@@ -293,8 +362,6 @@ try_enumerate (GVfsBackend *backend,
 {
   GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend);
 
-  GVfsAfpCommand *comm;
-  
   if (!is_root(filename))
   {
     g_vfs_job_failed (G_VFS_JOB (job),
@@ -303,16 +370,37 @@ try_enumerate (GVfsBackend *backend,
     return TRUE;
   }
 
-  comm = g_vfs_afp_command_new (AFP_COMMAND_GET_SRVR_PARMS);
-  /* pad byte */
-  g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), 0, NULL, NULL);
+  update_cache (afp_backend, G_VFS_JOB (job)->cancellable,
+                enumerate_cache_updated_cb, job);
+  
+  return TRUE;
+}
 
-  g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
-                                      get_srvr_parms_cb,
-                                      G_VFS_JOB (job)->cancellable, job);
-  g_object_unref (comm);
+static void
+query_info_cb (GVfsBackendAfpBrowse *afp_backend,
+               GError *error,
+               gpointer user_data)
+{
+  GVfsJobQueryInfo *job = G_VFS_JOB_QUERY_INFO (user_data);
 
-  return TRUE;
+  VolumeData *vol_data;
+
+  if (error != NULL)
+  {
+    g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+    return;
+  }
+
+  vol_data = find_volume (afp_backend, job->filename);
+  if (!vol_data)
+  {
+    g_vfs_job_failed (G_VFS_JOB (job),  G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+                      _("File doesn't exist"));
+    return;
+  }
+
+  fill_info (job->file_info, vol_data, afp_backend);
+  g_vfs_job_succeeded (G_VFS_JOB (job));
 }
 
 static gboolean
@@ -337,7 +425,8 @@ try_query_info (GVfsBackend *backend,
     g_vfs_job_succeeded (G_VFS_JOB (job));
   }
   else
-    g_vfs_job_succeeded (G_VFS_JOB (job));
+    update_cache (G_VFS_BACKEND_AFP_BROWSE (backend), G_VFS_JOB (job)->cancellable,
+                  query_info_cb, job);
   
   return TRUE;
 }
@@ -438,6 +527,8 @@ g_vfs_backend_afp_browse_init (GVfsBackendAfpBrowse *object)
 
   afp_backend->addr = NULL;
   afp_backend->user = NULL;
+
+  afp_backend->volumes = NULL;
 }
 
 static void
@@ -451,6 +542,8 @@ g_vfs_backend_afp_browse_finalize (GObject *object)
     g_object_unref (afp_backend->addr);
   
   g_free (afp_backend->user);
+
+  g_slist_free_full (afp_backend->volumes, (GDestroyNotify)volume_data_free);
   
 	G_OBJECT_CLASS (g_vfs_backend_afp_browse_parent_class)->finalize (object);
 }



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