summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2011-07-16 00:57:47 +0200
committerChristian Kellner <gicmo@gnome.org>2011-08-25 21:19:51 +0200
commit85403f7672a940dc8a9deceee0435c96466c85e4 (patch)
treeb582fc6fca8d65ffba8d298e9fbbba9e76ee606c /daemon
parent4c8c936ec7c965424cd304a3bb8a24ac0574ea60 (diff)
downloadgvfs-85403f7672a940dc8a9deceee0435c96466c85e4.tar.gz
afp: implement query_fs_info
also split out volume parameter fetching into an utility funciton
Diffstat (limited to 'daemon')
-rw-r--r--daemon/gvfsafpconnection.h18
-rw-r--r--daemon/gvfsbackendafp.c354
2 files changed, 316 insertions, 56 deletions
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
index 4b8d40dd..3eed6a50 100644
--- a/daemon/gvfsafpconnection.h
+++ b/daemon/gvfsafpconnection.h
@@ -111,6 +111,24 @@ enum
enum
{
+ AFP_VOLUME_ATTRIBUTES_BITMAP_READ_ONLY = 0x1,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_HAS_VOLUME_PASSWORD = 0x2,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_FILE_IDS = 0x4,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_CAT_SEARCH = 0x8,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_BLANK_ACCESS_PRIVS = 0x10,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_UNIX_PRIVS = 0x20,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_UTF8_NAMES = 0x40,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_NO_NETWORK_USER_IDS = 0x80,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_DEFUALT_PRIVS_FROM_PARENT = 0x100,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_NO_EXCHANGE_FILES = 0x200,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_EXT_ATTRS = 0x400,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_ACL = 0x800,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_CASE_SENSITIVE = 0x1000,
+ AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_TM_LOCK_STEAL = 0x2000
+};
+
+enum
+{
AFP_VOLUME_BITMAP_ATTRIBUTE_BIT = 0x1,
AFP_VOLUME_BITMAP_SIGNATURE_BIT = 0x2,
AFP_VOLUME_BITMAP_CREATE_DATE_BIT = 0x4,
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index ac593881..d77ef48d 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -34,6 +34,7 @@
#include "gvfsjobmount.h"
#include "gvfsjobenumerate.h"
#include "gvfsjobqueryinfo.h"
+#include "gvfsjobqueryfsinfo.h"
#include "gvfsjobopenforread.h"
#include "gvfsjobcloseread.h"
#include "gvfsjobread.h"
@@ -92,6 +93,25 @@ is_root (const char *filename)
return *p == 0;
}
+static void
+copy_file_info_into (GFileInfo *src, GFileInfo *dest)
+{
+ char **attrs;
+ gint i;
+
+ attrs = g_file_info_list_attributes (src, NULL);
+
+ for (i = 0; attrs[i]; i++)
+ {
+ GFileAttributeType type;
+ gpointer value;
+
+ g_file_info_get_attribute_data (src, attrs[i], &type, &value, NULL);
+ g_file_info_set_attribute (dest, attrs[i], type, value);
+ }
+
+ g_strfreev (attrs);
+}
static GVfsAfpName *
filename_to_afp_pathname (const char *filename)
@@ -584,7 +604,138 @@ get_fork_parms_finish (GVfsBackendAfp *afp_backend,
}
+static void
+get_vol_parms_cb (GVfsAfpConnection *afp_connection,
+ GVfsAfpReply *reply,
+ GError *error,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+
+ AfpResultCode res_code;
+ guint16 vol_bitmap;
+ GFileInfo *info;
+
+ if (!reply)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ return;
+ }
+
+ res_code = g_vfs_afp_reply_get_result_code (reply);
+ if (res_code != AFP_RESULT_NO_ERROR)
+ {
+ g_object_unref (reply);
+
+ g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Got error code: %d from server"), res_code);
+ g_simple_async_result_complete (simple);
+ return;
+ }
+
+ g_vfs_afp_reply_read_uint16 (reply, &vol_bitmap);
+
+ info = g_file_info_new ();
+
+ if (vol_bitmap & AFP_VOLUME_BITMAP_ATTRIBUTE_BIT)
+ {
+ guint16 vol_attrs_bitmap;
+
+ g_vfs_afp_reply_read_uint16 (reply, &vol_attrs_bitmap);
+
+ g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY,
+ vol_attrs_bitmap & AFP_VOLUME_ATTRIBUTES_BITMAP_READ_ONLY);
+ }
+
+ if (vol_bitmap & AFP_VOLUME_BITMAP_CREATE_DATE_BIT)
+ {
+ gint32 create_date;
+
+ g_vfs_afp_reply_read_int32 (reply, &create_date);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED,
+ create_date + afp_backend->time_diff);
+ }
+ if (vol_bitmap & AFP_VOLUME_BITMAP_MOD_DATE_BIT)
+ {
+ gint32 mod_date;
+
+ g_vfs_afp_reply_read_int32 (reply, &mod_date);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ mod_date + afp_backend->time_diff);
+ }
+
+ if (vol_bitmap & AFP_VOLUME_BITMAP_EXT_BYTES_FREE_BIT)
+ {
+ guint64 bytes_free;
+
+ g_vfs_afp_reply_read_uint64 (reply, &bytes_free);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
+ bytes_free);
+ }
+
+ if (vol_bitmap & AFP_VOLUME_BITMAP_EXT_BYTES_TOTAL_BIT)
+ {
+ guint64 bytes_total;
+
+ g_vfs_afp_reply_read_uint64 (reply, &bytes_total);
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,
+ bytes_total);
+ }
+
+ g_simple_async_result_set_op_res_gpointer (simple, info, g_object_unref);
+ g_simple_async_result_complete (simple);
+}
+
+static void
+get_vol_parms (GVfsBackendAfp *afp_backend,
+ guint16 vol_bitmap,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GVfsAfpCommand *comm;
+ GSimpleAsyncResult *simple;
+
+ comm = g_vfs_afp_command_new (AFP_COMMAND_GET_VOL_PARMS);
+ /* pad byte */
+ g_vfs_afp_command_put_byte (comm, 0);
+ /* Volume ID */
+ g_vfs_afp_command_put_uint16 (comm, afp_backend->volume_id);
+ /* Volume Bitmap */
+ g_vfs_afp_command_put_uint16 (comm, vol_bitmap);
+
+ simple = g_simple_async_result_new (G_OBJECT (afp_backend), callback, user_data,
+ get_vol_parms);
+
+
+ g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
+ get_vol_parms_cb, cancellable,
+ simple);
+ g_object_unref (comm);
+}
+
+static GFileInfo *
+get_vol_parms_finish (GVfsBackendAfp *afp_backend,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (afp_backend),
+ get_vol_parms),
+ NULL);
+
+ simple = (GSimpleAsyncResult *)result;
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
/*
* Backend code
@@ -1605,6 +1756,81 @@ try_create (GVfsBackend *backend,
}
static void
+append_to_get_fork_parms_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
+ GVfsJobOpenForWrite *job = G_VFS_JOB_OPEN_FOR_WRITE (user_data);
+ AfpHandle *afp_handle = (AfpHandle *)job->backend_handle;
+
+ GFileInfo *info;
+ GError *err = NULL;
+ goffset size;
+
+ info = get_fork_parms_finish (afp_backend, res, &err);
+ if (!info)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
+ g_error_free (err);
+ afp_handle_free (afp_handle);
+ return;
+ }
+
+ size = g_file_info_get_size (info);
+ g_object_unref (info);
+
+ afp_handle->offset = size;
+ g_vfs_job_open_for_write_set_initial_offset (job, size);
+ g_vfs_job_open_for_write_set_can_seek (job, TRUE);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+append_to_open_fork_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
+ GVfsJobOpenForWrite *job = G_VFS_JOB_OPEN_FOR_WRITE (user_data);
+
+ AfpHandle *afp_handle;
+ GError *err = NULL;
+
+ afp_handle = open_fork_finish (afp_backend, res, &err);
+ if (!afp_handle)
+ {
+ /* Create file if it doesn't exist */
+ if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ try_create (G_VFS_BACKEND (afp_backend), job, job->filename, job->flags);
+
+ else
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
+
+ g_error_free (err);
+ return;
+ }
+
+ afp_handle->type = AFP_HANDLE_TYPE_APPEND_TO_FILE;
+ g_vfs_job_open_for_write_set_handle (job, (GVfsBackendHandle) afp_handle);
+
+ get_fork_parms (afp_backend, afp_handle->fork_refnum,
+ AFP_FILE_BITMAP_EXT_DATA_FORK_LEN_BIT,
+ G_VFS_JOB (job)->cancellable, append_to_get_fork_parms_cb,
+ job);
+}
+
+static gboolean
+try_append_to (GVfsBackend *backend,
+ GVfsJobOpenForWrite *job,
+ const char *filename,
+ GFileCreateFlags flags)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
+
+ open_fork (afp_backend, job->filename, AFP_ACCESS_MODE_WRITE_BIT,
+ G_VFS_JOB (job)->cancellable, append_to_open_fork_cb, job);
+ return TRUE;
+}
+
+static void
read_open_fork_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
@@ -1641,7 +1867,6 @@ try_open_for_read (GVfsBackend *backend,
return TRUE;
}
-
static guint16
create_filedir_bitmap (GFileAttributeMatcher *matcher)
{
@@ -1837,6 +2062,63 @@ try_enumerate (GVfsBackend *backend,
}
static void
+query_fs_info_get_vol_parms_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
+ GVfsJobQueryFsInfo *job = G_VFS_JOB_QUERY_FS_INFO (user_data);
+
+ GError *err = NULL;
+ GFileInfo *info;
+
+ info = get_vol_parms_finish (afp_backend, res, &err);
+ if (!info)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
+ g_error_free (err);
+ return;
+ }
+
+ copy_file_info_into (info, job->file_info);
+ g_object_unref (info);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static gboolean
+try_query_fs_info (GVfsBackend *backend,
+ GVfsJobQueryFsInfo *job,
+ const char *filename,
+ GFileInfo *info,
+ GFileAttributeMatcher *matcher)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
+
+ guint16 vol_bitmap = 0;
+
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "afp");
+
+
+ if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE))
+ vol_bitmap |= AFP_VOLUME_BITMAP_EXT_BYTES_TOTAL_BIT;
+
+ if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
+ vol_bitmap |= AFP_VOLUME_BITMAP_EXT_BYTES_FREE_BIT;
+
+ if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))
+ vol_bitmap |= AFP_VOLUME_BITMAP_ATTRIBUTE_BIT;
+
+ if (vol_bitmap != 0)
+ {
+ get_vol_parms (afp_backend, vol_bitmap, G_VFS_JOB (job)->cancellable,
+ query_fs_info_get_vol_parms_cb, job);
+ }
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+
+ return TRUE;
+}
+
+static void
get_filedir_parms_cb (GVfsAfpConnection *afp_connection,
GVfsAfpReply *reply,
GError *error,
@@ -1889,54 +2171,25 @@ get_filedir_parms_cb (GVfsAfpConnection *afp_connection,
}
static void
-get_vol_parms_cb (GVfsAfpConnection *afp_connection,
- GVfsAfpReply *reply,
- GError *error,
- gpointer user_data)
+query_info_get_vol_parms_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
GVfsJobQueryInfo *job = G_VFS_JOB_QUERY_INFO (user_data);
- GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (job->backend);
- AfpResultCode res_code;
+ GError *err = NULL;
GFileInfo *info;
- guint16 vol_bitmap;
-
- 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)
+ info = get_vol_parms_finish (afp_backend, res, &err);
+ if (!info)
{
- g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
- G_IO_ERROR_FAILED, _("Retrieval of volume parameters failed"));
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), err);
+ g_error_free (err);
return;
}
- info = job->file_info;
-
- g_vfs_afp_reply_read_uint16 (reply, &vol_bitmap);
+ copy_file_info_into (info, job->file_info);
+ g_object_unref (info);
- if (vol_bitmap & AFP_VOLUME_BITMAP_CREATE_DATE_BIT)
- {
- gint32 create_date;
-
- g_vfs_afp_reply_read_int32 (reply, &create_date);
- g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED,
- create_date + afp_backend->time_diff);
- }
-
- if (vol_bitmap & AFP_VOLUME_BITMAP_MOD_DATE_BIT)
- {
- gint32 mod_date;
-
- g_vfs_afp_reply_read_int32 (reply, &mod_date);
- g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED,
- mod_date + afp_backend->time_diff);
- }
-
g_vfs_job_succeeded (G_VFS_JOB (job));
}
@@ -1972,24 +2225,11 @@ try_query_info (GVfsBackend *backend,
if (vol_bitmap != 0)
{
- GVfsAfpCommand *comm;
-
- comm = g_vfs_afp_command_new (AFP_COMMAND_GET_VOL_PARMS);
- /* pad byte */
- g_vfs_afp_command_put_byte (comm, 0);
- /* Volume ID */
- g_vfs_afp_command_put_uint16 (comm, afp_backend->volume_id);
- /* Volume Bitmap */
- g_vfs_afp_command_put_uint16 (comm, vol_bitmap);
-
- g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
- get_vol_parms_cb, G_VFS_JOB (job)->cancellable,
- job);
- g_object_unref (comm);
- return TRUE;
+ get_vol_parms (afp_backend, vol_bitmap, G_VFS_JOB (job)->cancellable,
+ query_info_get_vol_parms_cb, job);
}
-
- g_vfs_job_succeeded (G_VFS_JOB (job));
+ else
+ g_vfs_job_succeeded (G_VFS_JOB (job));
}
else {
@@ -2249,11 +2489,13 @@ 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;
+ backend_class->try_query_fs_info = try_query_fs_info;
backend_class->try_enumerate = try_enumerate;
backend_class->try_open_for_read = try_open_for_read;
backend_class->try_close_read = try_close_read;
backend_class->try_read = try_read;
backend_class->try_seek_on_read = try_seek_on_read;
+ backend_class->try_append_to = try_append_to;
backend_class->try_create = try_create;
backend_class->try_replace = try_replace;
backend_class->try_write = try_write;