[patch] tar method won't open root directory of archive



I haven't seen any documentation in gnome-vfs to indicate how one should encode the root directory of an archive into a URI, but empirically, it looks like something like either "foo.tar#tar:" or "foo.tar#tar:/" should work (gnome-vfs expands the former to the latter before giving the uri to the module's method). The tar method doesn't handle either of these cases. The attached patch fixes this.

Try out something like "gnomevfs-ls /path-to-file/foo.tar#:" before and after the patch as a test case. No CVS access for me - can someone apply it if it passes review?

The problem's filed in bugzilla as well: http://bugzilla.gnome.org/show_bug.cgi?id=131959

- George

--- gnome-vfs-2.4.1/modules/tar-method.c.handle-root	2002-05-12 20:38:29.000000000 -0700
+++ gnome-vfs-2.4.1/modules/tar-method.c	2004-01-19 12:43:14.000000000 -0800
@@ -51,6 +51,7 @@
 	int current_index;
 	gchar *filename;
 	gboolean is_directory;
+	gboolean is_root;
 } FileHandle;
 
 #define TARPET_BLOCKSIZE (sizeof (union TARPET_block))
@@ -154,35 +155,42 @@
 	return ret;
 }
 
-static GNode*
-tree_lookup_entry (const GNode *tree, const gchar *name)
+static gboolean
+tree_lookup_entry (const GNode *tree, const gchar *name, GNode **node)
 {
-	GNode *ret;
 	char *root = g_strdup (name);
 	char *txt = root;
-	
-	if (txt[0] == '/')
-		txt++;
 
-	ret = real_lookup_entry (tree, txt, 1);
-	if (!ret && txt[strlen (txt) - 1] != '/')
+	if (txt[0] == '/')
+	{
+		if (txt[1] == '\0')
+		{
+			g_free (root);
+			return TRUE;
+		}
+		else
+			txt++;
+	}
+	
+	*node = real_lookup_entry (tree, txt, 1);
+	if (!*node && txt[strlen (txt) - 1] != '/')
 	{
 		txt = g_strconcat (txt, "/", NULL);
 		g_free (root);
 		root = txt;
-		ret = real_lookup_entry (tree, txt, 1);
+		*node = real_lookup_entry (tree, txt, 1);
 	}
 	g_free (root);
 
-	if (ret && ret != tree->children)
+	if (*node && *node != tree->children)
 	{
-		union TARPET_block *b = ret->data;
+		union TARPET_block *b = (*node)->data;
 		b--;
 		if (b->p.typeflag == TARPET_TYPE_LONGFILEN)
-			ret = ret->next;
+			*node = (*node)->next;
 	}
 
-	return ret;
+	return FALSE;
 }
 
 static TarFile* read_tar_file (GnomeVFSHandle *handle)
@@ -228,7 +236,7 @@
 		}
 		
 		split_name (ret->blocks[i].p.name, &dir, &rest);
-		node = tree_lookup_entry (ret->info_tree, dir);
+		tree_lookup_entry (ret->info_tree, dir, &node);
 		
 		if (!node)
 		{
@@ -322,7 +330,7 @@
 	tar = ensure_tarfile (uri);
 	if (!tar)
 		return GNOME_VFS_ERROR_BAD_FILE;
-	node = tree_lookup_entry (tar->info_tree, uri->text);
+	tree_lookup_entry (tar->info_tree, uri->text, &node);
 	if (!node)
 	{
 		tar_file_unref (tar);
@@ -468,13 +476,17 @@
 	union TARPET_block *start, *current;
 	GNode *node;
 	int i;
+	gboolean is_root;
 
 	if (!uri->parent)
 		return GNOME_VFS_ERROR_INVALID_URI;
 	tar = ensure_tarfile (uri);
 	if (uri->text)
 	{
-		node = tree_lookup_entry (tar->info_tree, uri->text);
+		is_root = tree_lookup_entry (tar->info_tree, uri->text, &node);
+	}
+	if (!is_root)
+	{
 		if (!node)
 		{
 			tar_file_unref (tar);
@@ -490,8 +502,11 @@
 		else
 			current = NULL;
 	}
-	else
+	if (is_root || !uri->text)
 	{
+		/* FIXME: gnome-vfs never seems to generate !uri->text 
+		   condition. Is it permissible by contract? */
+
 		node = tar->info_tree;
 		if (!node)
 		{
@@ -516,6 +531,7 @@
 			break;
 	new_handle->current_index = i;
 	new_handle->is_directory = TRUE;
+	new_handle->is_root = is_root;
 
 	*method_handle = (GnomeVFSMethodHandle*) new_handle;
 	
@@ -550,7 +566,7 @@
 	int i;
 
 	if (uri->text)
-		node = tree_lookup_entry (tar->info_tree, uri->text);
+		tree_lookup_entry (tar->info_tree, uri->text, &node);
 	else
 		node = tar->info_tree->children;
 	
@@ -635,15 +651,16 @@
 	GnomeVFSURI *uri;
 	gchar *str;
 	GNode *node;
-	
+	gboolean is_root;
+
 	if (!handle->current)
 		return GNOME_VFS_ERROR_EOF;
 
 	str = g_strconcat (handle->filename, "#tar:", handle->current->p.name, NULL);
 	uri = gnome_vfs_uri_new (str);
 	do_get_file_info (method, uri, file_info, 0, context);
-	node = tree_lookup_entry (handle->tar->info_tree, uri->text);
-	if (!node)
+	is_root = tree_lookup_entry (handle->tar->info_tree, uri->text, &node);
+	if (!node && !is_root)
 	{
 		gnome_vfs_uri_unref (uri);
 		return GNOME_VFS_ERROR_NOT_FOUND;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]