summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--daemon/gvfsafpconnection.c2
-rw-r--r--daemon/gvfsafpconnection.h1
-rw-r--r--daemon/gvfsafpserver.c30
-rw-r--r--daemon/gvfsbackendafp.c130
-rw-r--r--daemon/gvfsbackendafpbrowse.c371
5 files changed, 376 insertions, 158 deletions
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
index 88998fd8..f9caeb4e 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 365464b5..14b55021 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 334efabf..aebedd59 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 c7f8dc4f..d8d3412b 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 4940361e..2db0ce91 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);
}