diff options
-rw-r--r-- | daemon/gvfsafpconnection.h | 12 | ||||
-rw-r--r-- | daemon/gvfsbackendafp.c | 231 |
2 files changed, 239 insertions, 4 deletions
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h index 62f1aaa3..44cfb095 100644 --- a/daemon/gvfsafpconnection.h +++ b/daemon/gvfsafpconnection.h @@ -34,6 +34,16 @@ enum AFP_GET_USER_INFO_BITMAP_GET_UUID_BIT = 0x4 }; +typedef enum +{ + AFP_MAP_ID_FUNCTION_USER_ID_TO_NAME = 1, + AFP_MAP_ID_FUNCTION_GROUP_ID_TO_NAME = 2, + AFP_MAP_ID_FUNCTION_USER_ID_TO_UTF8_NAME = 3, + AFP_MAP_ID_FUNCTION_GROUP_ID_TO_UTF8_NAME = 4, + AFP_MAP_ID_FUNCTION_USER_UUID_TO_UTF8_NAME = 5, + AFP_MAP_ID_FUNCTION_GROUP_UUID_TO_UTF8_NAME = 6 +} AfpMapIDFunction; + enum { AFP_MAP_NAME_FUNCTION_NAME_TO_USER_ID = 1, @@ -190,6 +200,7 @@ typedef enum AFP_COMMAND_GET_VOL_PARMS = 17, AFP_COMMAND_LOGIN = 18, AFP_COMMAND_LOGIN_CONT = 19, + AFP_COMMAND_MAP_ID = 21, AFP_COMMAND_MAP_NAME = 22, AFP_COMMAND_MOVE_AND_RENAME = 23, AFP_COMMAND_OPEN_VOL = 24, @@ -221,6 +232,7 @@ typedef enum AFP_RESULT_EOF_ERR = -5009, AFP_RESULT_FILE_BUSY = -5010, AFP_RESULT_FLAT_VOL = -5011, + AFP_RESULT_ITEM_NOT_FOUND = -5012, AFP_RESULT_LOCK_ERR = -5013, AFP_RESULT_OBJECT_EXISTS = -5017, AFP_RESULT_OBJECT_NOT_FOUND = -5018, diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c index 71d2560c..3598760a 100644 --- a/daemon/gvfsbackendafp.c +++ b/daemon/gvfsbackendafp.c @@ -1253,6 +1253,141 @@ delete_finish (GVfsBackendAfp *afp_backend, return TRUE; } +typedef struct +{ + AfpMapIDFunction function; + char *name; +} MapIDData; + +static void +map_id_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GVfsAfpConnection *afp_conn = G_VFS_AFP_CONNECTION (source_object); + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + + GVfsAfpReply *reply; + GError *err = NULL; + + AfpResultCode res_code; + MapIDData *map_data; + + reply = g_vfs_afp_connection_send_command_finish (afp_conn, res, &err); + if (!reply) + { + g_simple_async_result_take_error (simple, err); + g_simple_async_result_complete (simple); + return; + } + + res_code = g_vfs_afp_reply_get_result_code (reply); + if (res_code != AFP_RESULT_NO_ERROR) + { + switch (res_code) + { + case AFP_RESULT_ITEM_NOT_FOUND: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + _("ID not found")); + break; + default: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Got error code: %d from server"), res_code); + break; + } + + g_simple_async_result_complete (simple); + return; + } + + map_data = g_simple_async_result_get_op_res_gpointer (simple); + + if (map_data->function == AFP_MAP_ID_FUNCTION_USER_UUID_TO_UTF8_NAME || + map_data->function == AFP_MAP_ID_FUNCTION_GROUP_UUID_TO_UTF8_NAME) + { + /* objType */ + g_vfs_afp_reply_read_uint32 (reply, NULL); + /* id */ + g_vfs_afp_reply_read_uint32 (reply, NULL); + } + + if (map_data->function == AFP_MAP_ID_FUNCTION_USER_ID_TO_NAME || + map_data->function == AFP_MAP_ID_FUNCTION_GROUP_ID_TO_NAME) + { + g_vfs_afp_reply_read_pascal (reply, &map_data->name); + } + else + { + GVfsAfpName *afp_name; + + g_vfs_afp_reply_read_afp_name (reply, FALSE, &afp_name); + map_data->name = g_vfs_afp_name_get_string (afp_name); + g_vfs_afp_name_unref (afp_name); + } + + g_simple_async_result_complete (simple); +} + +static void +map_id (GVfsBackendAfp *afp_backend, + AfpMapIDFunction map_function, + gint64 id, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GVfsAfpCommand *comm; + GSimpleAsyncResult *simple; + MapIDData *map_data; + + comm = g_vfs_afp_command_new (AFP_COMMAND_MAP_ID); + + /* SubFunction*/ + g_vfs_afp_command_put_byte (comm, map_function); + + /* ID */ + if (map_function == AFP_MAP_ID_FUNCTION_USER_ID_TO_NAME || + map_function == AFP_MAP_ID_FUNCTION_GROUP_ID_TO_NAME) + g_vfs_afp_command_put_int32 (comm, id); + else + g_vfs_afp_command_put_int64 (comm, id); + + simple = g_simple_async_result_new (G_OBJECT (afp_backend), callback, + user_data, map_id); + + map_data = g_new (MapIDData, 1); + map_data->function = map_function; + g_simple_async_result_set_op_res_gpointer (simple, map_data, g_free); + + g_vfs_afp_connection_send_command (afp_backend->server->conn, comm, map_id_cb, + cancellable, simple); + g_object_unref (comm); +} + +static char * +map_id_finish (GVfsBackendAfp *afp_backend, + GAsyncResult *res, + AfpMapIDFunction *map_function, + GError **error) +{ + GSimpleAsyncResult *simple; + MapIDData *map_data; + + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (afp_backend), + map_id), + NULL); + + simple = (GSimpleAsyncResult *)res; + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + map_data = g_simple_async_result_get_op_res_gpointer (simple); + + if (map_function) + *map_function = map_data->function; + + return map_data->name; +} + /* * Backend code */ @@ -2784,7 +2919,10 @@ create_filedir_bitmap (GVfsBackendAfp *afp_backend, GFileAttributeMatcher *match g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_UNIX_GID) || g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_READ) || g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) || - g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) + g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)|| + g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_OWNER_USER) || + g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_OWNER_USER_REAL) || + g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_OWNER_GROUP)) { if (afp_backend->vol_attrs_bitmap & AFP_VOLUME_ATTRIBUTES_BITMAP_SUPPORTS_UNIX_PRIVS) @@ -3215,7 +3353,8 @@ query_fs_info_get_vol_parms_cb (GObject *source_object, GAsyncResult *res, gpoin copy_file_info_into (info, job->file_info); g_object_unref (info); - + + g_vfs_job_succeeded (G_VFS_JOB (job)); } @@ -3254,6 +3393,48 @@ try_query_fs_info (GVfsBackend *backend, } static void +get_name_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); + + char *name; + AfpMapIDFunction map_function; + guint outstanding_requests; + + name = map_id_finish (afp_backend, res, &map_function, NULL); + if (name) + { + switch (map_function) + { + case AFP_MAP_ID_FUNCTION_USER_ID_TO_NAME: + g_file_info_set_attribute_string (job->file_info, G_FILE_ATTRIBUTE_OWNER_USER, + name); + break; + case AFP_MAP_ID_FUNCTION_USER_ID_TO_UTF8_NAME: + g_file_info_set_attribute_string (job->file_info, G_FILE_ATTRIBUTE_OWNER_USER_REAL, + name); + break; + case AFP_MAP_ID_FUNCTION_GROUP_ID_TO_NAME: + g_file_info_set_attribute_string (job->file_info, G_FILE_ATTRIBUTE_OWNER_GROUP, + name); + break; + + default: + g_assert_not_reached (); + } + + g_free (name); + } + + outstanding_requests = GPOINTER_TO_UINT (G_VFS_JOB (job)->backend_data); + if (--outstanding_requests == 0) + g_vfs_job_succeeded (G_VFS_JOB (job)); + + G_VFS_JOB (job)->backend_data = GUINT_TO_POINTER (outstanding_requests); +} + +static void query_info_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object); @@ -3263,6 +3444,9 @@ query_info_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res, gpoi GFileInfo *info; GError *err = NULL; + GFileAttributeMatcher *matcher; + guint outstanding_requests; + info = get_filedir_parms_finish (afp_backend, res, &err); if (!info) { @@ -3271,10 +3455,49 @@ query_info_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res, gpoi return; } + outstanding_requests = 0; + matcher = job->attribute_matcher; + + if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID)) + { + guint32 uid; + + uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID); + + if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_OWNER_USER)) + { + map_id (afp_backend, AFP_MAP_ID_FUNCTION_USER_ID_TO_NAME, uid, + G_VFS_JOB (job)->cancellable, get_name_cb, job); + outstanding_requests++; + } + + if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_OWNER_USER_REAL)) + { + map_id (afp_backend, AFP_MAP_ID_FUNCTION_USER_ID_TO_UTF8_NAME, uid, + G_VFS_JOB (job)->cancellable, get_name_cb, job); + outstanding_requests++; + } + } + + if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID) && + g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_OWNER_GROUP)) + { + guint32 gid; + + gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID); + + map_id (afp_backend, AFP_MAP_ID_FUNCTION_GROUP_ID_TO_NAME, gid, + G_VFS_JOB (job)->cancellable, get_name_cb, job); + outstanding_requests++; + } + + G_VFS_JOB (job)->backend_data = GUINT_TO_POINTER (outstanding_requests); + copy_file_info_into (info, job->file_info); g_object_unref (info); - - g_vfs_job_succeeded (G_VFS_JOB (job)); + + if (outstanding_requests == 0) + g_vfs_job_succeeded (G_VFS_JOB (job)); } static void |