ssh-method patch



Attatched is a patch against CVS (HEAD IIRC*)
gnome-vfs/modules/ssh-method.c.

It basically brings it up to a usable state.
I've implemented unlink, mkdir, rmdir, and set_file_info.
I've also fixed buglets in much of the rest of it.
(Though it still has a problem with directories sometimes appearing
empty).

Known problems:
 * Running out of (remote) space will hang a copy to the remote location
 * it uses commands over an ssh link, which seems hacky to me.
   (that's how it was originally written, I don't know if there's a    
    libscp or anything).
 * it needs a vaguely bashish shell on the remote side (it runs 'ls -ld
[file] 2>&1' so it gets stderr as well as stdout).
 * I wrote it ;-P

But in any case, it's usable enough for me to copy MP3s to my linux iPAQ
:-D

Now: Could someone with CVS access please look the patch over and (if
good enough) commit it?

Thanks greatly;
mibus
 * whatever v-b-s pulls

-- 
Robert Mibus <mibus bigpond com>
"Bother," said Pooh.
"Eeyore, ready two photon torpedoes and lock phasers on the Heffalump;
 Piglet, meet me in transporter room three."
--- ssh-method.c.orig	Sat May  4 13:39:56 2002
+++ ssh-method.c	Sat May  4 22:13:53 2002
@@ -93,6 +93,21 @@
 					 GnomeVFSFileInfo *file_info,
 					 GnomeVFSFileInfoOptions options,
 					 GnomeVFSContext *context);
+static GnomeVFSResult do_make_directory (GnomeVFSMethod *method,
+					 GnomeVFSURI *uri,
+					 guint perm,
+					 GnomeVFSContext *context);
+static GnomeVFSResult do_remove_directory(GnomeVFSMethod *method,
+					  GnomeVFSURI *uri,
+					  GnomeVFSContext *context);
+static GnomeVFSResult do_unlink         (GnomeVFSMethod *method,
+					 GnomeVFSURI *uri,
+					 GnomeVFSContext *context);
+static GnomeVFSResult do_set_file_info  (GnomeVFSMethod *method,
+					 GnomeVFSURI *uri,
+					 const GnomeVFSFileInfo *info,
+					 GnomeVFSSetFileInfoMask mask,
+					 GnomeVFSContext *context);
 #if 0
 static GnomeVFSResult do_get_file_info_from_handle
                                         (GnomeVFSMethodHandle *method_handle,
@@ -118,11 +133,12 @@
         do_get_file_info,
 	NULL, /* get_file_info_from_handle */
         do_is_local,
-	NULL, /* make directory */
-        NULL, /* remove directory */
-	NULL, /* unlink */
+	do_make_directory, /* make directory */
+        do_remove_directory, /* remove directory */
+	NULL, /* move */
+	do_unlink, /* unlink */
 	NULL, /* check_same_fs */
-	NULL, /* set_file_info */
+	do_set_file_info, /* set_file_info */
 	NULL, /* truncate */
 	NULL, /* find_directory */
 	NULL /* create_symbolic_link */
@@ -175,7 +191,7 @@
 
 		if (status != 0) {
 			return gnome_vfs_result_from_errno ();
-		}*/
+		} */
 
 	}
 
@@ -210,8 +226,9 @@
 	   GnomeVFSFileSize *bytes_read)
 {
 	GnomeVFSFileSize my_read;
+
 	my_read = (GnomeVFSFileSize) read (handle->read_fd, buffer, 
-			(size_t) num_bytes);
+					   (size_t) num_bytes);
 
 	if (my_read == -1) {
 		return gnome_vfs_result_from_errno ();
@@ -229,8 +246,17 @@
 	   GnomeVFSFileSize *bytes_written)
 {
 	GnomeVFSFileSize written;
-	written = (GnomeVFSFileSize) write (handle->write_fd, buffer, 
-			(size_t) num_bytes);
+	int count=0;
+
+	do {
+		errno = 0;
+		written = (GnomeVFSFileSize) write (handle->write_fd, buffer, 
+						    (size_t) num_bytes);
+		if (written == -1 && errno == EINTR) {
+			count++;
+			usleep (10);
+		}
+	} while (written == -1 && errno == EINTR && count < 5);
 
 	if (written == -1) {
 		return gnome_vfs_result_from_errno ();
@@ -291,20 +317,27 @@
 	GnomeVFSResult result = GNOME_VFS_OK;
 	char *cmd;
 	SshHandle *handle = NULL;
+	char *name;
+
+	/* FIXME: escape for shell */
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
 
 	if (mode == GNOME_VFS_OPEN_READ) {
 		/* FIXME: escape for shell */
-		cmd = g_strdup_printf ("cat '%s'\n", uri->text);
+		cmd = g_strdup_printf ("cat '%s'", name);
 		result = ssh_connect (&handle, uri, cmd);
 		g_free (cmd);
 
 		if (result != GNOME_VFS_OK) {
+			g_free (name);
 			return result;
 		}
 
 	} else if (mode == GNOME_VFS_OPEN_WRITE) {
+		g_free (name);
 		return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
 	} else {
+		g_free (name);
 		return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
 	}
 	
@@ -312,6 +345,8 @@
 	handle->type = SSH_FILE;
 	*method_handle = (GnomeVFSMethodHandle *)handle;
 
+	g_free (name);
+
 	return result;
 }
 
@@ -327,18 +362,24 @@
 	SshHandle *handle = NULL;
 	char *cmd;
 	GnomeVFSResult result;
+	char *name;
+
+	/* FIXME: escape for shell */
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
 
 	if (mode != GNOME_VFS_OPEN_WRITE) {
+		g_free (name);
 		return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
 	}
 
 
 	/* FIXME: escape for shell */
-	cmd = g_strdup_printf ("cat > '%s'\n", uri->text);
+	cmd = g_strdup_printf ("cat > '%s'", name);
 	result = ssh_connect (&handle, uri, cmd);
 	g_free (cmd);
 
 	if (result != GNOME_VFS_OK) {
+		g_free (name);
 		return result;
 	}
 
@@ -348,6 +389,7 @@
 	handle->type = SSH_FILE;
 	*method_handle = (GnomeVFSMethodHandle *)handle;
 
+	g_free (name);
 	return result;
 }
 
@@ -396,10 +438,16 @@
 	SshHandle *handle = NULL;
 	char *cmd = NULL;
 	GnomeVFSResult result;
+	char *name;
 
 	/* FIXME: escape for shell */
-	cmd = g_strdup_printf ("ls -l '%s'", uri->text);
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
+	if (strlen (name))
+		cmd = g_strdup_printf ("ls -l '%s'", name);
+	else
+		cmd = g_strdup_printf ("ls -l '/'");
 	result = ssh_connect (&handle, uri, cmd);
+	g_free (name);
 	g_free (cmd);
 
 	if (result != GNOME_VFS_OK) {
@@ -436,16 +484,17 @@
 	int i=0;
 	GnomeVFSFileSize j;
 	struct stat st;
-	char *filename, *linkname;
+	char *tempfilename, *filename, *linkname;
 
 	for (;;) {
+		tempfilename = NULL;
 		filename = NULL;
 		linkname = NULL;
 		i = 0;
 		j = 0;
+
 		while (i<LINE_LENGTH) {
 			result = ssh_read ((SshHandle *)method_handle, &c, 1, &j);
-
 			if (j == 0 || c == '\r' || c == '\n') {
 				break;
 			}
@@ -459,15 +508,24 @@
 		}
 
 		line[i] = 0;
-
 		if (i == 0) {
 			return GNOME_VFS_ERROR_EOF;
 		}
 
-		if (!gnome_vfs_parse_ls_lga (line, &st, &filename, &linkname)) {
+		if (!gnome_vfs_parse_ls_lga (line, &st, &tempfilename, &linkname)) {
+			/* Maybe the file doesn't exist? */
+			if (strstr(line, "No such file or directory"))
+				return GNOME_VFS_ERROR_NOT_FOUND;
 			continue; /* skip to next line */
 		}
 
+		/* Get rid of the path */
+		if (strrchr(tempfilename, '/'))
+			filename = g_strdup(strrchr(tempfilename,'/')+1);
+		else
+			filename = g_strdup(tempfilename);
+		g_free (tempfilename);
+
 		gnome_vfs_stat_to_file_info (file_info, &st);
 		file_info->name = filename;
 		if (linkname) {
@@ -485,6 +543,10 @@
 		file_info->valid_fields &= 
 			~GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
 
+		/* Break out.
+		   We are in a loop so we get the first 'ls' line;
+		   often it starts with 'total 2213' etc.
+		*/
 		break;
 	}
 
@@ -501,11 +563,17 @@
 	SshHandle *handle = NULL;
 	char *cmd = NULL;
 	GnomeVFSResult result;
+	char *name;
 
 	/* FIXME: escape for shell */
-	cmd = g_strdup_printf ("ls -ld '%s'", uri->text);
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
+	if (strlen (name))
+		cmd = g_strdup_printf ("ls -ld '%s' 2>&1", name);
+	else
+		cmd = g_strdup_printf ("ls -ld '/' 2>&1");
 	result = ssh_connect (&handle, uri, cmd);
 	g_free (cmd);
+	g_free (name);
 
 	if (result != GNOME_VFS_OK) {
 		return result;
@@ -515,10 +583,164 @@
 	handle->type = SSH_LIST;
 
 	result = do_read_directory (method, (GnomeVFSMethodHandle *)handle,
-			file_info, context);
+				    file_info, context);
+
+	ssh_destroy (handle);
+
+	return (result == GNOME_VFS_ERROR_EOF ? GNOME_VFS_OK : result);
+}
+
+static GnomeVFSResult
+do_make_directory (GnomeVFSMethod *method,
+		   GnomeVFSURI *uri,
+		   guint perm,
+		   GnomeVFSContext *context)
+{
+	SshHandle *handle = NULL;
+	char *cmd = NULL;
+	GnomeVFSResult result;
+	char *name;
+
+	/* FIXME: escape for shell */
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
+
+	/* FIXME: escape for shell */
+	cmd = g_strdup_printf ("mkdir '%s'", name);
+	result = ssh_connect (&handle, uri, cmd);
+	g_free (cmd);
+	g_free (name);
+
+	if (result != GNOME_VFS_OK) {
+		return result;
+	}
 
 	ssh_destroy (handle);
 
+	return result;
+}
+
+static GnomeVFSResult
+do_remove_directory (GnomeVFSMethod *method,
+		     GnomeVFSURI *uri,
+		     GnomeVFSContext *context)
+{
+	SshHandle *handle = NULL;
+	char *cmd = NULL;
+	GnomeVFSResult result;
+	gchar *name;
+
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
+	if (name == NULL)
+		return GNOME_VFS_ERROR_INVALID_URI;
+
+	/* FIXME: escape for shell */
+	cmd = g_strdup_printf ("rm -rf '%s'", name);
+	result = ssh_connect (&handle, uri, cmd);
+	g_free (cmd);
+	g_free (name);
+
+	if (result != GNOME_VFS_OK) {
+		return result;
+	}
+
+	ssh_destroy (handle);
+
+	return result;
+}
+
+GnomeVFSResult
+do_unlink (GnomeVFSMethod *method,
+	   GnomeVFSURI *uri,
+	   GnomeVFSContext *contet)
+{
+	SshHandle *handle = NULL;
+	char *cmd = NULL;
+	GnomeVFSResult result;
+	gchar *name;
+
+	name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
+	if (name == NULL)
+		return GNOME_VFS_ERROR_INVALID_URI;
+
+	/* FIXME: escape for shell */
+	cmd = g_strdup_printf ("rm -rf '%s'", name);
+	result = ssh_connect (&handle, uri, cmd);
+	g_free (cmd);
+	g_free (name);
+
+	if (result != GNOME_VFS_OK) {
+		return result;
+	}
+
+	ssh_destroy (handle);
+
+	return result;
+}
+
+static GnomeVFSResult
+do_set_file_info (GnomeVFSMethod *method,
+		  GnomeVFSURI *uri,
+		  const GnomeVFSFileInfo *info,
+		  GnomeVFSSetFileInfoMask mask,
+		  GnomeVFSContext *context)
+{
+	SshHandle *handle = NULL;
+	char *cmd = NULL;
+	GnomeVFSResult result=GNOME_VFS_OK;
+	gchar *full_name;
+
+	full_name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
+	if (full_name == NULL)
+		return GNOME_VFS_ERROR_INVALID_URI;
+
+	if (mask & GNOME_VFS_SET_FILE_INFO_NAME) {
+		char *encoded_dir;
+		char *dir;
+		char *new_name;
+
+		encoded_dir = gnome_vfs_uri_extract_dirname (uri);
+		dir = gnome_vfs_unescape_string (encoded_dir, G_DIR_SEPARATOR_S);
+		g_free (encoded_dir);
+		g_assert (dir != NULL);
+
+		/* FIXME bugzilla.eazel.com 645: This needs to return
+		 * an error for incoming names with "/" characters in
+		 * them, instead of moving the file.
+		 */
+
+		if (dir[strlen(dir) - 1] != '/') {
+			new_name = g_strconcat (dir, "/", info->name, NULL);
+		} else {
+			new_name = g_strconcat (dir, info->name, NULL);
+		}
+
+		/* FIXME: escape for shell */
+		cmd = g_strdup_printf ("mv '%s' '%s'", full_name,
+				       new_name);
+		result = ssh_connect (&handle, uri, cmd);
+		g_free (cmd);
+		g_free (dir);
+		g_free (new_name);
+
+		/* Read all info from remote host */
+		while (1) {
+			char c;
+			GnomeVFSResult res;
+			GnomeVFSFileSize j;
+			res = ssh_read (handle, &c, 1, &j);
+			if (j == 0 || res != GNOME_VFS_OK)
+				break;
+		}
+
+		ssh_destroy (handle);
+
+		if (result != GNOME_VFS_OK) {
+			g_free (full_name);
+			return result;
+		}
+	}
+
+	g_free (full_name);
 	return result;
 }
 


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