[gvfs] afp: work on file enumeration
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] afp: work on file enumeration
- Date: Thu, 25 Aug 2011 19:22:47 +0000 (UTC)
commit d38d13dfd156cfe0e43eb1d03462a176298ce256
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date: Tue Jun 21 00:35:18 2011 +0200
afp: work on file enumeration
daemon/gvfsafpconnection.c | 42 ++++++----
daemon/gvfsafpconnection.h | 31 +++++--
daemon/gvfsafpserver.c | 1 +
daemon/gvfsafpserver.h | 2 +-
daemon/gvfsbackendafp.c | 208 +++++++++++++++++++++++++++++++++++++++++---
5 files changed, 246 insertions(+), 38 deletions(-)
---
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
index a10eea6..8fc623d 100644
--- a/daemon/gvfsafpconnection.c
+++ b/daemon/gvfsafpconnection.c
@@ -53,13 +53,7 @@ g_vfs_afp_name_ref (GVfsAfpName *afp_name)
char *
g_vfs_afp_name_get_string (GVfsAfpName *afp_name)
{
- char *str;
-
- str = g_malloc (afp_name->len + 1);
- memcpy (str, afp_name->str, afp_name->len);
- str[afp_name->len] = 0;
-
- return str;
+ return g_strndup (afp_name->str, afp_name->len);
}
GVfsAfpName *
@@ -102,12 +96,12 @@ g_vfs_afp_name_new_from_gstring (guint32 text_encoding, GString *string)
*/
struct _GVfsAfpReplyClass
{
- GDataInputStreamClass parent_class;
+ GObjectClass parent_class;
};
struct _GVfsAfpReply
{
- GDataInputStream parent_instance;
+ GObject parent_instance;
AfpResultCode result_code;
@@ -262,11 +256,7 @@ g_vfs_afp_reply_read_pascal (GVfsAfpReply *reply, char **str)
}
if (str)
- {
- *str = g_malloc (strsize + 1);
- memcpy (*str, reply->data + reply->pos, strsize);
- (*str)[strsize] = '\0';
- }
+ *str = g_strndup (reply->data + reply->pos, strsize);
reply->pos += strsize;
@@ -356,6 +346,12 @@ g_vfs_afp_reply_skip_to_even (GVfsAfpReply *reply)
return TRUE;
}
+gint
+g_vfs_afp_reply_get_pos (GVfsAfpReply *reply)
+{
+ return reply->pos;
+}
+
AfpResultCode
g_vfs_afp_reply_get_result_code (GVfsAfpReply *reply)
{
@@ -410,14 +406,28 @@ g_vfs_afp_command_put_pascal (GVfsAfpCommand *command, const char *str)
{
size_t len;
- len = strlen (str);
- len = (len <= 256) ? len : 256;
+ len = MIN (strlen (str), 256);
g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (command), len, NULL, NULL);
g_output_stream_write (G_OUTPUT_STREAM (command), str, len, NULL, NULL);
}
void
+g_vfs_afp_command_put_afp_name (GVfsAfpCommand *command, GVfsAfpName *afp_name)
+{
+#if 0
+ g_data_output_stream_put_uint32 (G_DATA_OUTPUT_STREAM (command),
+ afp_name->text_encoding, NULL, NULL);
+#endif
+
+ g_data_output_stream_put_uint16 (G_DATA_OUTPUT_STREAM (command),
+ afp_name->len, NULL, NULL);
+
+ g_output_stream_write_all (G_OUTPUT_STREAM (command), afp_name->str,
+ afp_name->len, NULL, NULL, NULL);
+}
+
+void
g_vfs_afp_command_pad_to_even (GVfsAfpCommand *command)
{
if (g_vfs_afp_command_get_size (command) % 2 == 1)
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
index 3f92c9b..f922460 100644
--- a/daemon/gvfsafpconnection.h
+++ b/daemon/gvfsafpconnection.h
@@ -133,6 +133,13 @@ enum {
typedef enum
{
+ AFP_PATH_TYPE_SHORT_NAME = 1,
+ AFP_PATH_TYPE_LONG_NAME = 2,
+ AFP_PATH_TYPE_UTF8_NAME = 3
+} AfpPathType;
+
+typedef enum
+{
AFP_DIR_BITMAP_ATTRIBUTE_BIT = 0x1,
AFP_DIR_BITMAP_PARENT_DIR_ID_BIT = 0x2,
AFP_DIR_BITMAP_CREATE_DATE_BIT = 0x4,
@@ -203,10 +210,13 @@ typedef enum
typedef enum
{
- AFP_RESULT_NO_ERROR = 0,
- AFP_RESULT_USER_NOT_AUTH = -5023,
- AFP_RESULT_AUTH_CONTINUE = -5001,
- AFP_RESULT_NO_MORE_SESSIONS = -1068
+ AFP_RESULT_NO_ERROR = 0,
+ AFP_RESULT_NO_MORE_SESSIONS = -1068,
+ AFP_RESULT_ACCESS_DENIED = -5000,
+ AFP_RESULT_AUTH_CONTINUE = -5001,
+ AFP_RESULT_OBJECT_NOT_FOUND = -5018,
+ AFP_RESULT_PARAM_ERR = -5019,
+ AFP_RESULT_USER_NOT_AUTH = -5023
} AfpResultCode;
/*
@@ -262,6 +272,7 @@ gboolean g_vfs_afp_reply_seek (GVfsAfpReply *reply, gint off
gboolean g_vfs_afp_reply_skip_to_even (GVfsAfpReply *reply);
AfpResultCode g_vfs_afp_reply_get_result_code (GVfsAfpReply *reply);
+gint g_vfs_afp_reply_get_pos (GVfsAfpReply *reply);
GType g_vfs_afp_reply_get_type (void) G_GNUC_CONST;
@@ -280,13 +291,15 @@ typedef struct _GVfsAfpCommandClass GVfsAfpCommandClass;
typedef struct _GVfsAfpCommand GVfsAfpCommand;
-GVfsAfpCommand* g_vfs_afp_command_new (AfpCommandType type);
+GVfsAfpCommand* g_vfs_afp_command_new (AfpCommandType type);
+
+void g_vfs_afp_command_put_pascal (GVfsAfpCommand *command, const char *str);
+void g_vfs_afp_command_put_afp_name (GVfsAfpCommand *command, GVfsAfpName *afp_name);
-void g_vfs_afp_command_put_pascal (GVfsAfpCommand *command, const char *str);
-void g_vfs_afp_command_pad_to_even (GVfsAfpCommand *command);
+void g_vfs_afp_command_pad_to_even (GVfsAfpCommand *command);
-gsize g_vfs_afp_command_get_size (GVfsAfpCommand *command);
-char* g_vfs_afp_command_get_data (GVfsAfpCommand *command);
+gsize g_vfs_afp_command_get_size (GVfsAfpCommand *command);
+char* g_vfs_afp_command_get_data (GVfsAfpCommand *command);
GType g_vfs_afp_command_get_type (void) G_GNUC_CONST;
diff --git a/daemon/gvfsafpserver.c b/daemon/gvfsafpserver.c
index d76b8f0..1cd8745 100644
--- a/daemon/gvfsafpserver.c
+++ b/daemon/gvfsafpserver.c
@@ -315,6 +315,7 @@ dhx2_login (GVfsAfpServer *afp_serv,
res = g_vfs_afp_connection_send_command_sync (afp_serv->conn, comm,
cancellable, error);
+ g_object_unref (comm);
if (!res)
goto error;
diff --git a/daemon/gvfsafpserver.h b/daemon/gvfsafpserver.h
index 545997a..2ec5325 100644
--- a/daemon/gvfsafpserver.h
+++ b/daemon/gvfsafpserver.h
@@ -34,7 +34,7 @@ typedef enum
{
AFP_VERSION_INVALID,
AFP_VERSION_3_0,
- AFP_VERSIOM_3_1,
+ AFP_VERSION_3_1,
AFP_VERSION_3_2,
AFP_VERSION_3_3
} AfpVersion;
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index b17a029..bf0d7ae 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -40,6 +40,8 @@
#include "gvfsbackendafp.h"
+static const gint16 ENUMERATE_REQ_COUNT = G_MAXINT16;
+
struct _GVfsBackendAfpClass
{
GVfsBackendClass parent_class;
@@ -73,20 +75,22 @@ is_root (const char *filename)
return *p == 0;
}
-# if 0
-static GString *
+
+static GVfsAfpName *
filename_to_afp_pathname (const char *filename)
{
GString *pathname;
pathname = g_string_new (NULL);
+
+ g_string_append_c (pathname, 0);
- while (filename && *filename == '/')
+ while (*filename == '/')
filename++;
- while (filename)
+ while (*filename != 0)
{
- char *end;
+ const char *end;
end = strchr (filename, '/');
if (!end)
@@ -95,13 +99,192 @@ filename_to_afp_pathname (const char *filename)
g_string_append_c (pathname, 0);
g_string_append_len (pathname, filename, end - filename);
- while (filename && *filename == '/')
+ filename = end;
+ while (*filename == '/')
filename++;
}
- return pathname;
+ return g_vfs_afp_name_new_from_gstring (kTextEncodingUnicodeV3_0,
+ pathname);
+}
+
+static void
+enumerate_ext2_cb (GVfsAfpConnection *afp_connection,
+ GVfsAfpReply *reply,
+ GError *error,
+ gpointer user_data)
+{
+ GVfsJobEnumerate *job = G_VFS_JOB_ENUMERATE (user_data);
+
+ AfpResultCode res_code;
+ guint16 file_bitmap;
+ guint16 dir_bitmap;
+ gint16 count, i;
+
+ 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_OBJECT_NOT_FOUND)
+ {
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_vfs_job_enumerate_done (job);
+ return;
+ }
+ else if (res_code != AFP_RESULT_NO_ERROR)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_FAILED, _("Enumeration of files failed"));
+ return;
+ }
+
+ g_vfs_afp_reply_read_uint16 (reply, &file_bitmap);
+ g_vfs_afp_reply_read_uint16 (reply, &dir_bitmap);
+
+ g_vfs_afp_reply_read_int16 (reply, &count);
+ for (i = 0; i < count; i++)
+ {
+ gint start_pos;
+ guint16 struct_length;
+ guint8 FileDir;
+
+ start_pos = g_vfs_afp_reply_get_pos (reply);
+
+ g_vfs_afp_reply_read_uint16 (reply, &struct_length);
+ g_vfs_afp_reply_read_byte (reply, &FileDir);
+ /* pad byte */
+ g_vfs_afp_reply_read_byte (reply, NULL);
+
+ /* Directory */
+ if (FileDir & 0x80)
+ {
+ if (dir_bitmap & AFP_FILE_BITMAP_UTF8_NAME_BIT)
+ {
+ guint16 UTF8Name_offset;
+ gint old_pos;
+ GVfsAfpName *afp_name;
+ char *utf8_name;
+
+ g_vfs_afp_reply_read_uint16 (reply, &UTF8Name_offset);
+
+ old_pos = g_vfs_afp_reply_get_pos (reply);
+ g_vfs_afp_reply_seek (reply, start_pos + UTF8Name_offset + 4, G_SEEK_SET);
+
+ g_vfs_afp_reply_read_afp_name (reply, TRUE, &afp_name);
+ utf8_name = g_vfs_afp_name_get_string (afp_name);
+ g_debug ("Directory: %s\n", utf8_name);
+
+ g_vfs_afp_name_unref (afp_name);
+ g_free (utf8_name);
+
+ g_vfs_afp_reply_seek (reply, old_pos, G_SEEK_SET);
+ }
+ }
+
+ /* File */
+ else
+ {
+ if (file_bitmap & AFP_FILE_BITMAP_UTF8_NAME_BIT)
+ {
+ guint16 UTF8Name_offset;
+ gint old_pos;
+ GVfsAfpName *afp_name;
+ char *utf8_name;
+
+ g_vfs_afp_reply_read_uint16 (reply, &UTF8Name_offset);
+
+ old_pos = g_vfs_afp_reply_get_pos (reply);
+ g_vfs_afp_reply_seek (reply, start_pos + UTF8Name_offset + 4, G_SEEK_SET);
+
+ g_vfs_afp_reply_read_afp_name (reply, TRUE, &afp_name);
+ utf8_name = g_vfs_afp_name_get_string (afp_name);
+ g_debug ("File: %s\n", utf8_name);
+
+ g_vfs_afp_name_unref (afp_name);
+ g_free (utf8_name);
+
+ g_vfs_afp_reply_seek (reply, old_pos, G_SEEK_SET);
+ }
+ }
+
+ g_vfs_afp_reply_seek (reply, start_pos + struct_length, G_SEEK_SET);
+ }
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+ g_vfs_job_enumerate_done (job);
+}
+
+static gboolean
+try_enumerate (GVfsBackend *backend,
+ GVfsJobEnumerate *job,
+ const char *filename,
+ GFileAttributeMatcher *attribute_matcher,
+ GFileQueryInfoFlags flags)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
+
+ if (afp_backend->server->version >= AFP_VERSION_3_1)
+ {
+ GVfsAfpCommand *comm;
+ AfpFileBitmap file_bitmap;
+ AfpDirBitmap dir_bitmap;
+ GVfsAfpName *Pathname;
+
+ comm = g_vfs_afp_command_new (AFP_COMMAND_ENUMERATE_EXT2);
+ /* 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);
+
+ /* Directory ID 2 == / */
+ g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (comm), 2, NULL, NULL);
+
+ /* File Bitmap */
+ file_bitmap = AFP_FILE_BITMAP_UTF8_NAME_BIT;
+ g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), file_bitmap,
+ NULL, NULL);
+ /* Dir Bitmap */
+ dir_bitmap = AFP_DIR_BITMAP_UTF8_NAME_BIT;
+ g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), dir_bitmap,
+ NULL, NULL);
+
+ /* Req Count */
+ g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), ENUMERATE_REQ_COUNT,
+ NULL, NULL);
+ /* StartIndex */
+ g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (comm), 1,
+ NULL, NULL);
+ /* MaxReplySize */
+ g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (comm), G_MAXINT32,
+ NULL, NULL);
+
+ /* PathType */
+ g_data_output_stream_put_byte (G_DATA_OUTPUT_STREAM (comm), AFP_PATH_TYPE_UTF8_NAME,
+ NULL, NULL);
+
+ Pathname = filename_to_afp_pathname (filename);
+ g_vfs_afp_command_put_afp_name (comm, Pathname);
+ g_vfs_afp_name_unref (Pathname);
+
+ g_vfs_afp_connection_queue_command (afp_backend->server->conn, comm,
+ enumerate_ext2_cb,
+ G_VFS_JOB (job)->cancellable, job);
+ g_object_unref (comm);
+ }
+
+ else
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Enumeration not supported for AFP_VERSION_3_0 yet");
+ }
+
+ return TRUE;
}
-#endif
static void
get_vol_parms_cb (GVfsAfpConnection *afp_connection,
@@ -157,8 +340,6 @@ try_query_info (GVfsBackend *backend,
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
- g_debug ("filename: %s\n", filename);
-
if (is_root (filename))
{
GIcon *icon;
@@ -181,8 +362,8 @@ try_query_info (GVfsBackend *backend,
/* 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);
+ g_data_output_stream_put_int16 (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);
@@ -190,6 +371,7 @@ try_query_info (GVfsBackend *backend,
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;
}
@@ -249,6 +431,7 @@ do_mount (GVfsBackend *backend,
res = g_vfs_afp_connection_send_command_sync (afp_backend->server->conn,
comm, G_VFS_JOB (job)->cancellable,
&err);
+ g_object_unref (comm);
if (!res)
goto error;
@@ -397,6 +580,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;
+ backend_class->try_enumerate = try_enumerate;
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]