[gvfs] afp: get basic file browsing working
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] afp: get basic file browsing working
- Date: Thu, 25 Aug 2011 19:22:52 +0000 (UTC)
commit 6ff326715eea874c3a2ff557acf3db8f44b05a53
Author: Carl-Anton Ingmarsson <ca ingmarsson gmail com>
Date: Tue Jun 21 17:11:55 2011 +0200
afp: get basic file browsing working
daemon/gvfsafpconnection.c | 31 +----
daemon/gvfsafpconnection.h | 39 ++++--
daemon/gvfsbackendafp.c | 267 ++++++++++++++++++++++++++++-------------
daemon/gvfsbackendafpbrowse.c | 4 +-
4 files changed, 215 insertions(+), 126 deletions(-)
---
diff --git a/daemon/gvfsafpconnection.c b/daemon/gvfsafpconnection.c
index 8fc623d..cb38044 100644
--- a/daemon/gvfsafpconnection.c
+++ b/daemon/gvfsafpconnection.c
@@ -57,7 +57,7 @@ g_vfs_afp_name_get_string (GVfsAfpName *afp_name)
}
GVfsAfpName *
-g_vfs_afp_name_new (guint32 text_encoding, const gchar *str, gsize len)
+g_vfs_afp_name_new (guint32 text_encoding, gchar *str, gsize len)
{
GVfsAfpName *afp_name;
@@ -65,29 +65,10 @@ g_vfs_afp_name_new (guint32 text_encoding, const gchar *str, gsize len)
afp_name->ref_count = 1;
afp_name->text_encoding = text_encoding;
-
- afp_name->str = g_malloc (len);
- memcpy (afp_name->str, str, len);
-
- afp_name->len = len;
-
- return afp_name;
-}
-
-GVfsAfpName *
-g_vfs_afp_name_new_from_gstring (guint32 text_encoding, GString *string)
-{
- GVfsAfpName *afp_name;
- afp_name = g_slice_new (GVfsAfpName);
- afp_name->ref_count = 1;
-
- afp_name->text_encoding = text_encoding;
- afp_name->str = string->str;
- afp_name->len = string->len;
+ afp_name->str = str;
+ afp_name->len = len;
- g_string_free (string, FALSE);
-
return afp_name;
}
@@ -281,7 +262,7 @@ g_vfs_afp_reply_read_afp_name (GVfsAfpReply *reply, gboolean read_text_encoding,
return FALSE;
}
else
- text_encoding = kTextEncodingUnicodeDefault;
+ text_encoding = kTextEncodingMacRoman;
if (!g_vfs_afp_reply_read_uint16 (reply, &len))
{
@@ -296,7 +277,7 @@ g_vfs_afp_reply_read_afp_name (GVfsAfpReply *reply, gboolean read_text_encoding,
}
if (afp_name)
- *afp_name = g_vfs_afp_name_new (text_encoding, str, len);
+ *afp_name = g_vfs_afp_name_new (text_encoding, g_strndup (str, len), len);
return TRUE;
@@ -415,10 +396,8 @@ g_vfs_afp_command_put_pascal (GVfsAfpCommand *command, const char *str)
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);
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h
index f922460..930e8e3 100644
--- a/daemon/gvfsafpconnection.h
+++ b/daemon/gvfsafpconnection.h
@@ -138,6 +138,21 @@ typedef enum
AFP_PATH_TYPE_UTF8_NAME = 3
} AfpPathType;
+enum
+{
+ AFP_FILEDIR_BITMAP_ATTRIBUTE_BIT = 0x1,
+ AFP_FILEDIR_BITMAP_PARENT_DIR_ID_BIT = 0x2,
+ AFP_FILEDIR_BITMAP_CREATE_DATE_BIT = 0x4,
+ AFP_FILEDIR_BITMAP_MOD_DATE_BIT = 0x8,
+ AFP_FILEDIR_BITMAP_BACKUP_DATE_BIT = 0x10,
+ AFP_FILEDIR_BITMAP_FINDER_INFO_BIT = 0x20,
+ AFP_FILEDIR_BITMAP_LONG_NAME_BIT = 0x40,
+ AFP_FILEDIR_BITMAP_SHORT_NAME_BIT = 0x80,
+ AFP_FILEDIR_BITMAP_NODE_ID_BIT = 0x100,
+ AFP_FILEDIR_BITMAP_UTF8_NAME_BIT = 0x2000,
+ AFP_FILEDIR_BITMAP_UNIX_PRIVS_BIT = 0x8000,
+};
+
typedef enum
{
AFP_DIR_BITMAP_ATTRIBUTE_BIT = 0x1,
@@ -196,16 +211,17 @@ typedef enum
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,
- AFP_COMMAND_WRITE = 33,
- AFP_COMMAND_WRITE_EXT = 61,
- AFP_COMMAND_ENUMERATE_EXT = 66,
- AFP_COMMAND_ENUMERATE_EXT2 = 68
+ 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,
+ AFP_COMMAND_WRITE = 33,
+ AFP_COMMAND_GET_FILE_DIR_PARMS = 34,
+ AFP_COMMAND_WRITE_EXT = 61,
+ AFP_COMMAND_ENUMERATE_EXT = 66,
+ AFP_COMMAND_ENUMERATE_EXT2 = 68
} AfpCommandType;
typedef enum
@@ -233,8 +249,7 @@ struct _GVfsAfpName
gint ref_count;
};
-GVfsAfpName* g_vfs_afp_name_new (guint32 text_encoding, const gchar *str, gsize len);
-GVfsAfpName* g_vfs_afp_name_new_from_gstring (guint32 text_encoding, GString *string);
+GVfsAfpName* g_vfs_afp_name_new (guint32 text_encoding, gchar *str, gsize len);
void g_vfs_afp_name_unref (GVfsAfpName *afp_name);
void g_vfs_afp_name_ref (GVfsAfpName *afp_name);
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index bf0d7ae..25b271f 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -79,33 +79,86 @@ is_root (const char *filename)
static GVfsAfpName *
filename_to_afp_pathname (const char *filename)
{
- GString *pathname;
+ gsize len;
+ char *str;
+ gint i;
- pathname = g_string_new (NULL);
-
- g_string_append_c (pathname, 0);
-
while (*filename == '/')
- filename++;
+ filename++;
- while (*filename != 0)
+ len = strlen (filename);
+
+ str = g_malloc (len);
+
+ for (i = 0; i < len; i++)
{
- const char *end;
+ if (filename[i] == '/')
+ str[i] = '\0';
+ else
+ str[i] = filename[i];
+ }
+
+
+ return g_vfs_afp_name_new (0x08000103, str, len);
+}
+
+static gint16
+create_file_bitmap (GFileAttributeMatcher *matcher)
+{
+ return AFP_FILE_BITMAP_UTF8_NAME_BIT;
+}
+
+static gint16
+create_dir_bitmap (GFileAttributeMatcher *matcher)
+{
+ return AFP_DIR_BITMAP_UTF8_NAME_BIT;
+}
- end = strchr (filename, '/');
- if (!end)
- end = filename + strlen (filename);
+static void fill_info (GFileInfo *info, GVfsAfpReply *reply,
+ gboolean directory, gint16 bitmap)
+{
+ gint start_pos;
- g_string_append_c (pathname, 0);
- g_string_append_len (pathname, filename, end - filename);
+ if (directory)
+ {
+ GIcon *icon;
+
+ g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_content_type (info, "inode/directory");
- filename = end;
- while (*filename == '/')
- filename++;
+ icon = g_themed_icon_new ("folder");
+ g_file_info_set_icon (info, icon);
+ g_object_unref (icon);
}
+ else
+ g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
+
+
+ start_pos = g_vfs_afp_reply_get_pos (reply);
+
+ if (bitmap & AFP_FILEDIR_BITMAP_UTF8_NAME_BIT)
+ {
+ guint16 UTF8Name_offset;
+ gint old_pos;
+ GVfsAfpName *afp_name;
+ char *utf8_name;
- return g_vfs_afp_name_new_from_gstring (kTextEncodingUnicodeV3_0,
- pathname);
+ 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, 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_vfs_afp_name_unref (afp_name);
+
+ g_file_info_set_name (info, utf8_name);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ utf8_name);
+ g_free (utf8_name);
+
+ g_vfs_afp_reply_seek (reply, old_pos, G_SEEK_SET);
+ }
}
static void
@@ -117,8 +170,8 @@ enumerate_ext2_cb (GVfsAfpConnection *afp_connection,
GVfsJobEnumerate *job = G_VFS_JOB_ENUMERATE (user_data);
AfpResultCode res_code;
- guint16 file_bitmap;
- guint16 dir_bitmap;
+ gint16 file_bitmap;
+ gint16 dir_bitmap;
gint16 count, i;
if (!reply)
@@ -141,8 +194,8 @@ enumerate_ext2_cb (GVfsAfpConnection *afp_connection,
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, &file_bitmap);
+ g_vfs_afp_reply_read_int16 (reply, &dir_bitmap);
g_vfs_afp_reply_read_int16 (reply, &count);
for (i = 0; i < count; i++)
@@ -150,6 +203,10 @@ enumerate_ext2_cb (GVfsAfpConnection *afp_connection,
gint start_pos;
guint16 struct_length;
guint8 FileDir;
+
+ gboolean directory;
+ guint16 bitmap;
+ GFileInfo *info;
start_pos = g_vfs_afp_reply_get_pos (reply);
@@ -157,58 +214,14 @@ enumerate_ext2_cb (GVfsAfpConnection *afp_connection,
g_vfs_afp_reply_read_byte (reply, &FileDir);
/* pad byte */
g_vfs_afp_reply_read_byte (reply, NULL);
+
+ directory = (FileDir & 0x80);
+ bitmap = directory ? dir_bitmap : file_bitmap;
- /* 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);
- }
- }
+ info = g_file_info_new ();
+ fill_info (info, reply, directory, bitmap);
+ g_vfs_job_enumerate_add_info (job, info);
+ g_object_unref (info);
g_vfs_afp_reply_seek (reply, start_pos + struct_length, G_SEEK_SET);
}
@@ -216,12 +229,12 @@ enumerate_ext2_cb (GVfsAfpConnection *afp_connection,
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,
+ GFileAttributeMatcher *matcher,
GFileQueryInfoFlags flags)
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
@@ -229,8 +242,7 @@ try_enumerate (GVfsBackend *backend,
if (afp_backend->server->version >= AFP_VERSION_3_1)
{
GVfsAfpCommand *comm;
- AfpFileBitmap file_bitmap;
- AfpDirBitmap dir_bitmap;
+ gint16 file_bitmap, dir_bitmap;
GVfsAfpName *Pathname;
comm = g_vfs_afp_command_new (AFP_COMMAND_ENUMERATE_EXT2);
@@ -245,11 +257,11 @@ try_enumerate (GVfsBackend *backend,
g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (comm), 2, NULL, NULL);
/* File Bitmap */
- file_bitmap = AFP_FILE_BITMAP_UTF8_NAME_BIT;
+ file_bitmap = create_file_bitmap (matcher);
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;
+ dir_bitmap = create_dir_bitmap (matcher);
g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), dir_bitmap,
NULL, NULL);
@@ -263,6 +275,7 @@ try_enumerate (GVfsBackend *backend,
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);
@@ -287,6 +300,55 @@ try_enumerate (GVfsBackend *backend,
}
static void
+get_filedir_parms_cb (GVfsAfpConnection *afp_connection,
+ GVfsAfpReply *reply,
+ GError *error,
+ gpointer user_data)
+{
+ GVfsJobQueryInfo *job = G_VFS_JOB_QUERY_INFO (user_data);
+
+ AfpResultCode res_code;
+ gint16 file_bitmap, dir_bitmap, bitmap;
+ guint8 FileDir;
+ gboolean directory;
+
+ if (!reply)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ return;
+ }
+
+ res_code = g_vfs_afp_reply_get_result_code (reply);
+ g_debug ("res_code: %d\n", res_code);
+ if (res_code == AFP_RESULT_OBJECT_NOT_FOUND)
+ {
+ g_object_unref (reply);
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
+ 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, _("Retrieval of file/directory parameters failed"));
+ return;
+ }
+
+ g_vfs_afp_reply_read_int16 (reply, &file_bitmap);
+ g_vfs_afp_reply_read_int16 (reply, &dir_bitmap);
+
+ g_vfs_afp_reply_read_byte (reply, &FileDir);
+
+ directory = (FileDir & 0x80);
+ bitmap = directory ? dir_bitmap : file_bitmap;
+
+ fill_info (job->file_info, reply, directory, bitmap);
+
+ g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
get_vol_parms_cb (GVfsAfpConnection *afp_connection,
GVfsAfpReply *reply,
GError *error,
@@ -309,7 +371,7 @@ get_vol_parms_cb (GVfsAfpConnection *afp_connection,
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"));
+ G_IO_ERROR_FAILED, _("Retrieval of volume parameters failed"));
return;
}
@@ -339,6 +401,8 @@ try_query_info (GVfsBackend *backend,
GFileAttributeMatcher *matcher)
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
+
+ g_debug ("filename: %s\n", filename);
if (is_root (filename))
{
@@ -362,8 +426,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_int16 (G_DATA_OUTPUT_STREAM (comm),
- afp_backend->volume_id, NULL, NULL);
+ 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);
@@ -376,13 +440,44 @@ try_query_info (GVfsBackend *backend,
}
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;
+ GVfsAfpCommand *comm;
+
+ gint16 file_bitmap, dir_bitmap;
+ GVfsAfpName *Pathname;
+
+ comm = g_vfs_afp_command_new (AFP_COMMAND_GET_FILE_DIR_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);
+ /* Directory ID */
+ g_data_output_stream_put_int32 (G_DATA_OUTPUT_STREAM (comm), 2, NULL, NULL);
+
+ file_bitmap = create_file_bitmap (matcher);
+ g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), file_bitmap,
+ NULL, NULL);
+
+ dir_bitmap = create_dir_bitmap (matcher);
+ g_data_output_stream_put_int16 (G_DATA_OUTPUT_STREAM (comm), dir_bitmap,
+ 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,
+ get_filedir_parms_cb,
+ G_VFS_JOB (job)->cancellable, job);
}
+
+ return TRUE;
}
static void
diff --git a/daemon/gvfsbackendafpbrowse.c b/daemon/gvfsbackendafpbrowse.c
index db9ed62..3f2b709 100644
--- a/daemon/gvfsbackendafpbrowse.c
+++ b/daemon/gvfsbackendafpbrowse.c
@@ -394,8 +394,8 @@ query_info_cb (GVfsBackendAfpBrowse *afp_backend,
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"));
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("File doesn't exist"));
return;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]