1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* ssh-method.c - VFS Access to the GConf configuration database.
4 Copyright (C) 1999 Free Software Foundation
6 The Gnome Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The Gnome Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the Gnome Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Author: Ian McKellar <yakk@yakk.net> */
26 #include <glib/gstrfuncs.h>
27 #include <libgnomevfs/gnome-vfs-cancellation.h>
28 #include <libgnomevfs/gnome-vfs-context.h>
29 #include <libgnomevfs/gnome-vfs-mime.h>
30 #include <libgnomevfs/gnome-vfs-module-shared.h>
31 #include <libgnomevfs/gnome-vfs-module.h>
32 #include <libgnomevfs/gnome-vfs-parse-ls.h>
33 #include <libgnomevfs/gnome-vfs-utils.h>
35 #include <sys/types.h>
39 #include <sys/signal.h>
43 /* #define D(x) g_print x */
45 #define LINE_LENGTH 4096 /* max line length we'll grok */
46 #define SLEEP_TIME 300000 /* time we'll wait for the process to finish */
49 GnomeVFSMethodHandle method_handle;
55 GnomeVFSOpenMode open_mode;
60 GnomeVFSFileInfoOptions info_opts;
63 static GnomeVFSResult ssh_read_error (int error_fd,
65 GnomeVFSFileSize num_bytes,
66 GnomeVFSFileSize *bytes_read);
67 static GnomeVFSResult do_open (GnomeVFSMethod *method,
68 GnomeVFSMethodHandle **method_handle,
70 GnomeVFSOpenMode mode,
71 GnomeVFSContext *context);
72 static GnomeVFSResult do_create (GnomeVFSMethod *method,
73 GnomeVFSMethodHandle **method_handle,
75 GnomeVFSOpenMode mode,
78 GnomeVFSContext *context);
79 static GnomeVFSResult do_close (GnomeVFSMethod *method,
80 GnomeVFSMethodHandle *method_handle,
81 GnomeVFSContext *context);
82 static GnomeVFSResult do_read (GnomeVFSMethod *method,
83 GnomeVFSMethodHandle *method_handle,
85 GnomeVFSFileSize num_bytes,
86 GnomeVFSFileSize *bytes_read,
87 GnomeVFSContext *context);
88 static GnomeVFSResult do_write (GnomeVFSMethod *method,
89 GnomeVFSMethodHandle *method_handle,
91 GnomeVFSFileSize num_bytes,
92 GnomeVFSFileSize *bytes_written,
93 GnomeVFSContext *context);
94 static GnomeVFSResult do_open_directory (GnomeVFSMethod *method,
95 GnomeVFSMethodHandle **method_handle,
97 GnomeVFSFileInfoOptions options,
98 GnomeVFSContext *context);
99 static GnomeVFSResult do_close_directory(GnomeVFSMethod *method,
100 GnomeVFSMethodHandle *method_handle,
101 GnomeVFSContext *context);
102 static GnomeVFSResult do_read_directory (GnomeVFSMethod *method,
103 GnomeVFSMethodHandle *method_handle,
104 GnomeVFSFileInfo *file_info,
105 GnomeVFSContext *context);
106 static GnomeVFSResult do_get_file_info (GnomeVFSMethod *method,
108 GnomeVFSFileInfo *file_info,
109 GnomeVFSFileInfoOptions options,
110 GnomeVFSContext *context);
111 static GnomeVFSResult do_make_directory (GnomeVFSMethod *method,
114 GnomeVFSContext *context);
115 static GnomeVFSResult do_remove_directory(GnomeVFSMethod *method,
117 GnomeVFSContext *context);
118 static GnomeVFSResult do_move (GnomeVFSMethod *method,
119 GnomeVFSURI *old_uri,
120 GnomeVFSURI *new_uri,
121 gboolean force_replace,
122 GnomeVFSContext *context);
123 static GnomeVFSResult do_unlink (GnomeVFSMethod *method,
125 GnomeVFSContext *context);
126 static GnomeVFSResult do_check_same_fs (GnomeVFSMethod *method,
129 gboolean *same_fs_return,
130 GnomeVFSContext *context);
131 static GnomeVFSResult do_set_file_info (GnomeVFSMethod *method,
133 const GnomeVFSFileInfo *info,
134 GnomeVFSSetFileInfoMask mask,
135 GnomeVFSContext *context);
137 static GnomeVFSResult do_get_file_info_from_handle
138 (GnomeVFSMethodHandle *method_handle,
139 GnomeVFSFileInfo *file_info,
140 GnomeVFSFileInfoOptions options);
142 static gboolean do_is_local (GnomeVFSMethod *method,
143 const GnomeVFSURI *uri);
145 static GnomeVFSMethod method = {
146 sizeof (GnomeVFSMethod),
148 do_create, /* create */
151 do_write, /* write */
159 NULL, /* get_file_info_from_handle */
161 do_make_directory, /* make directory */
162 do_remove_directory, /* remove directory */
164 do_unlink, /* unlink */
166 do_set_file_info, /* set_file_info */
168 NULL, /* find_directory */
169 NULL /* create_symbolic_link */
172 /* FIXME: does this like FDs? */
173 static GnomeVFSResult
174 ssh_connect (SshHandle **handle_return,
175 GnomeVFSURI *uri, const char *command)
179 char *command_line, *host_port;
180 const gchar *username, *hostname;
182 GError *gerror = NULL;
183 GnomeVFSFileSize bytes_read;
184 char buffer[LINE_LENGTH];
187 /* We do support ssh:/// as ssh://localhost/ */
188 hostname = gnome_vfs_uri_get_host_name (uri);
189 if (hostname == NULL) {
190 hostname = "localhost";
193 username = gnome_vfs_uri_get_user_name(uri);
194 if (username == NULL) {
195 username = g_get_user_name();
198 host_port = g_strdup_printf("%d", gnome_vfs_uri_get_host_port(uri) ?
199 gnome_vfs_uri_get_host_port(uri) : 22);
201 command_line = g_strconcat ("ssh -oBatchMode=yes -x -l ",
206 "\"LC_ALL=C; echo READY > /dev/stderr;",
207 command, "; echo DONE > /dev/stderr\"",
211 D(("ssh_connect () command: %s\n", command_line));
213 g_shell_parse_argv (command_line, &argc, &argv, &gerror);
215 g_free (command_line);
217 g_warning (gerror->message);
218 return GNOME_VFS_ERROR_BAD_PARAMETERS;
221 handle = g_new0 (SshHandle, 1);
224 g_spawn_async_with_pipes (NULL, argv, NULL,
227 (gint *)&handle->pid, &handle->write_fd,
228 &handle->read_fd, &handle->error_fd,
233 g_warning (gerror->message);
235 return GNOME_VFS_ERROR_GENERIC;
238 gnome_vfs_uri_ref (handle->uri);
240 *handle_return = handle;
242 /* You can add more error checking here */
243 memset (buffer, '\0', LINE_LENGTH);
244 res = ssh_read_error (handle->error_fd, &buffer,
245 LINE_LENGTH, &bytes_read);
247 if (bytes_read != 0 && res == GNOME_VFS_OK) {
248 if (strncmp ("READY", buffer, strlen ("READY")) == 0) {
250 } else if (strncmp ("Permission denied", buffer,
251 strlen("Permission denied")) == 0) {
252 res = GNOME_VFS_ERROR_LOGIN_FAILED;
253 } else if (strncmp ("Host key verification failed", buffer,
254 strlen("Host key verification failed"))
256 res = GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE;
257 } else if (strstr (buffer, "Connection refused") != NULL) {
258 res = GNOME_VFS_ERROR_ACCESS_DENIED;
265 static GnomeVFSResult
266 ssh_destroy (SshHandle *handle)
268 close (handle->read_fd);
269 close (handle->write_fd);
270 close (handle->error_fd);
271 gnome_vfs_uri_unref (handle->uri);
272 kill (handle->pid, SIGINT);
278 static GnomeVFSResult
279 ssh_read (SshHandle *handle,
281 GnomeVFSFileSize num_bytes,
282 GnomeVFSFileSize *bytes_read)
284 GnomeVFSFileSize my_read;
286 my_read = (GnomeVFSFileSize) read (handle->read_fd, buffer,
290 return gnome_vfs_result_from_errno ();
293 *bytes_read = my_read;
298 static GnomeVFSResult
299 ssh_read_error (int error_fd,
301 GnomeVFSFileSize num_bytes,
302 GnomeVFSFileSize *bytes_read)
304 GnomeVFSFileSize my_read;
306 my_read = (GnomeVFSFileSize) read (error_fd, buffer,
310 return gnome_vfs_result_from_errno ();
313 *bytes_read = my_read;
318 static GnomeVFSResult
319 ssh_check_for_done (SshHandle *handle)
321 char buffer[LINE_LENGTH];
323 GnomeVFSFileSize bytes_read;
325 memset (buffer, '\0', LINE_LENGTH);
326 res = ssh_read_error (handle->error_fd, &buffer,
327 LINE_LENGTH, &bytes_read);
329 if (bytes_read != 0 && res == GNOME_VFS_OK) {
330 if (strncmp ("DONE", buffer, strlen ("DONE")) == 0) {
335 return GNOME_VFS_ERROR_GENERIC;
338 static GnomeVFSResult
339 ssh_write (SshHandle *handle,
340 gconstpointer buffer,
341 GnomeVFSFileSize num_bytes,
342 GnomeVFSFileSize *bytes_written)
344 GnomeVFSFileSize written;
349 written = (GnomeVFSFileSize) write (handle->write_fd, buffer,
351 if (written == -1 && errno == EINTR) {
355 } while (written == -1 && errno == EINTR && count < 5);
358 return gnome_vfs_result_from_errno ();
361 *bytes_written = written;
366 static GnomeVFSResult
367 ssh_wait_and_destroy (SshHandle *handle, GnomeVFSContext *context)
371 /* That's 30 seconds */
372 for (i = 0; i < 100 && kill (handle->pid, 0) != -1; i++) {
373 if (gnome_vfs_context_check_cancellation (context) == TRUE) {
379 return ssh_destroy (handle);
384 static GnomeVFSResult
385 ssh_send (SshHandle *handle,
388 GnomeVFSFileSize len, written;
389 GnomeVFSResult result = GNOME_VFS_OK;
391 len = strlen (string);
393 while (len > 0 && result == GNOME_VFS_OK) {
394 result = ssh_write (handle, string, len, &written);
403 static GnomeVFSResult
404 do_open (GnomeVFSMethod *method,
405 GnomeVFSMethodHandle **method_handle,
407 GnomeVFSOpenMode mode,
408 GnomeVFSContext *context)
410 GnomeVFSResult result = GNOME_VFS_OK;
412 SshHandle *handle = NULL;
414 if (mode == GNOME_VFS_OPEN_READ) {
417 name = gnome_vfs_unescape_string (uri->text,
420 return GNOME_VFS_ERROR_INVALID_URI;
422 quoted_name = g_shell_quote (name);
425 cmd = g_strdup_printf ("cat %s", quoted_name);
426 result = ssh_connect (&handle, uri, cmd);
428 g_free (quoted_name);
429 if (result != GNOME_VFS_OK) {
433 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
436 handle->open_mode = mode;
437 handle->type = SSH_FILE;
438 *method_handle = (GnomeVFSMethodHandle *)handle;
443 static GnomeVFSResult
444 do_create (GnomeVFSMethod *method,
445 GnomeVFSMethodHandle **method_handle,
447 GnomeVFSOpenMode mode,
450 GnomeVFSContext *context)
452 SshHandle *handle = NULL;
454 GnomeVFSResult result;
458 if (mode != GNOME_VFS_OPEN_WRITE) {
459 return GNOME_VFS_ERROR_INVALID_OPEN_MODE;
462 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
464 return GNOME_VFS_ERROR_INVALID_URI;
466 quoted_name = g_shell_quote (name);
468 cmd = g_strdup_printf ("cat > %s", quoted_name);
469 result = ssh_connect (&handle, uri, cmd);
472 g_free (quoted_name);
474 if (result != GNOME_VFS_OK) {
478 /* FIXME: set perm */
480 handle->open_mode = mode;
481 handle->type = SSH_FILE;
482 *method_handle = (GnomeVFSMethodHandle *)handle;
487 static GnomeVFSResult
488 do_close (GnomeVFSMethod *method,
489 GnomeVFSMethodHandle *method_handle,
490 GnomeVFSContext *context)
492 return ssh_wait_and_destroy ((SshHandle *)method_handle, context);
495 static GnomeVFSResult
496 do_read (GnomeVFSMethod *method,
497 GnomeVFSMethodHandle *method_handle,
499 GnomeVFSFileSize num_bytes,
500 GnomeVFSFileSize *bytes_read,
501 GnomeVFSContext *context)
503 GnomeVFSResult result, res_secondary;
505 result = ssh_read ((SshHandle *)method_handle, buffer, num_bytes,
507 if (result != GNOME_VFS_OK) {
511 if (*bytes_read == 0) {
512 res_secondary = ssh_check_for_done ((SshHandle *)method_handle);
513 if (res_secondary != GNOME_VFS_OK) {
514 result = res_secondary;
516 result = GNOME_VFS_ERROR_EOF;
523 * dd bs=1 conv=notrunc count=5 seek=60 of=/tmp/foo-test
525 static GnomeVFSResult
526 do_write (GnomeVFSMethod *method,
527 GnomeVFSMethodHandle *method_handle,
528 gconstpointer buffer,
529 GnomeVFSFileSize num_bytes,
530 GnomeVFSFileSize *bytes_written,
531 GnomeVFSContext *context)
533 return ssh_write ((SshHandle *)method_handle, buffer, num_bytes,
537 static GnomeVFSResult
538 do_open_directory (GnomeVFSMethod *method,
539 GnomeVFSMethodHandle **method_handle,
541 GnomeVFSFileInfoOptions options,
542 GnomeVFSContext *context)
544 SshHandle *handle = NULL;
546 GnomeVFSResult result;
550 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
552 return GNOME_VFS_ERROR_NOT_FOUND;
555 quoted_name = g_shell_quote (name);
558 cmd = g_strdup_printf ("ls -l %s", quoted_name);
560 cmd = g_strdup_printf ("ls -l '/'");
563 result = ssh_connect (&handle, uri, cmd);
564 g_free (quoted_name);
568 if (result != GNOME_VFS_OK) {
571 handle->info_opts = options;
572 handle->open_mode = GNOME_VFS_OPEN_NONE;
573 handle->type = SSH_LIST;
574 *method_handle = (GnomeVFSMethodHandle *)handle;
579 static GnomeVFSResult
580 do_close_directory (GnomeVFSMethod *method,
581 GnomeVFSMethodHandle *method_handle,
582 GnomeVFSContext *context)
584 return ssh_destroy ((SshHandle *)method_handle);
588 get_access_info (GnomeVFSURI *uri, GnomeVFSFileInfo *file_info)
595 GnomeVFSFilePermissions perm;
597 struct param params[2] = {{'r', GNOME_VFS_PERM_ACCESS_READABLE},
598 {'w', GNOME_VFS_PERM_ACCESS_WRITABLE}};
600 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
605 if ( *name == '\0' ) {
606 quoted_name = g_shell_quote ("/");
608 quoted_name = g_shell_quote (name);
612 for (i = 0; i<2; i++) {
616 GnomeVFSFileSize bytes_read;
617 GnomeVFSResult result;
619 cmd = g_strdup_printf ("test -%c %s && echo $?",
620 params[i].c, quoted_name);
621 result = ssh_connect (&handle, uri, cmd);
624 if (result != GNOME_VFS_OK) {
629 result = ssh_read (handle, &c, 1, &bytes_read);
630 if ((bytes_read > 0) && (c == '0')) {
631 file_info->permissions |= params[i].perm;
633 file_info->permissions &= ~params[i].perm;
636 ssh_destroy (handle);
639 file_info->permissions &= ~GNOME_VFS_PERM_ACCESS_EXECUTABLE;
640 file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_ACCESS;
645 static GnomeVFSResult
646 do_read_directory (GnomeVFSMethod *method,
647 GnomeVFSMethodHandle *method_handle,
648 GnomeVFSFileInfo *file_info,
649 GnomeVFSContext *context)
651 GnomeVFSResult result = GNOME_VFS_OK, res_secondary;
652 char line[LINE_LENGTH+1];
655 GnomeVFSFileSize bytes_read;
657 char *tempfilename, *filename, *linkname;
658 SshHandle *handle = (SshHandle *)method_handle;
659 const char *mime_type;
660 char *target_name, *parent;
661 GnomeVFSFileInfo *target_info;
662 GnomeVFSURI *target_uri;
671 while (i<LINE_LENGTH) {
672 result = ssh_read (handle, &c,
673 sizeof(char), &bytes_read);
674 if (bytes_read == 0 || c == '\r' || c == '\n') {
678 if (result != GNOME_VFS_OK) {
679 res_secondary = ssh_check_for_done (handle);
680 if (res_secondary != GNOME_VFS_OK) {
681 result = res_secondary;
690 /* Here we can have i == LINE_LENGTH which explains
691 * why the size of line is LINE_LENGTH+1
695 return GNOME_VFS_ERROR_EOF;
698 if (!gnome_vfs_parse_ls_lga (line, &st, &tempfilename, &linkname)) {
699 /* Maybe the file doesn't exist? */
700 if (strstr (line, "No such file or directory"))
701 return GNOME_VFS_ERROR_NOT_FOUND;
702 continue; /* skip to next line */
705 /* Get rid of the path */
706 if (strrchr (tempfilename, '/') != NULL) {
707 filename = g_strdup (strrchr (tempfilename,'/') + 1);
709 filename = g_strdup (tempfilename);
711 g_free (tempfilename);
713 gnome_vfs_stat_to_file_info (file_info, &st);
714 file_info->name = filename;
716 GNOME_VFS_FILE_INFO_SET_SYMLINK (file_info, TRUE);
717 file_info->valid_fields
718 |= GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME;
719 file_info->symlink_name = linkname;
720 D(("symlink: %s\n", file_info->symlink_name));
723 /* FIXME: support symlinks to directories correctly */
725 if (file_info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK) {
726 parent = gnome_vfs_uri_to_string
729 gnome_vfs_make_uri_full_from_relative
730 (parent, file_info->symlink_name);
732 if ((handle->info_opts
733 & GNOME_VFS_FILE_INFO_FOLLOW_LINKS) == 0) {
734 mime_type = "x-special/symlink";
736 target_uri = gnome_vfs_uri_new (target_name);
737 mime_type = gnome_vfs_get_file_mime_type
738 (target_name, NULL, FALSE);
739 D(("Looking up mime-type for '%s'\n\n",
741 target_info = gnome_vfs_file_info_new ();
742 do_get_file_info (method, target_uri,
743 target_info, handle->info_opts,
745 file_info->type = target_info->type;
746 gnome_vfs_file_info_unref (target_info);
747 gnome_vfs_uri_unref (target_uri);
750 g_free (target_name);
753 mime_type = (gnome_vfs_get_file_mime_type
754 (filename, &st, FALSE));
757 if (handle->info_opts & GNOME_VFS_FILE_INFO_GET_MIME_TYPE) {
758 file_info->mime_type = g_strdup (mime_type);
759 file_info->valid_fields
760 |= GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
763 file_info->valid_fields &=
764 ~GNOME_VFS_FILE_INFO_FIELDS_BLOCK_COUNT;
765 file_info->valid_fields &=
766 ~GNOME_VFS_FILE_INFO_FIELDS_IO_BLOCK_SIZE;
767 if (handle->info_opts & GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS) {
768 get_access_info (handle->uri, file_info);
772 We are in a loop so we get the first 'ls' line;
773 often it starts with 'total 2213' etc.
782 do_get_file_info (GnomeVFSMethod *method,
784 GnomeVFSFileInfo *file_info,
785 GnomeVFSFileInfoOptions options,
786 GnomeVFSContext *context)
788 SshHandle *handle = NULL;
790 GnomeVFSResult result;
794 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
796 return GNOME_VFS_ERROR_INVALID_URI;
799 quoted_name = g_shell_quote (name);
802 cmd = g_strdup_printf ("ls -ld %s 2>&1", quoted_name);
804 cmd = g_strdup_printf ("ls -ld '/' 2>&1");
807 result = ssh_connect (&handle, uri, cmd);
810 g_free (quoted_name);
812 if (result != GNOME_VFS_OK) {
815 handle->info_opts = options;
816 handle->open_mode = GNOME_VFS_OPEN_NONE;
817 handle->type = SSH_LIST;
819 result = do_read_directory (method, (GnomeVFSMethodHandle *)handle,
822 ssh_destroy (handle);
824 return (result == GNOME_VFS_ERROR_EOF ? GNOME_VFS_OK : result);
827 static GnomeVFSResult
828 do_make_directory (GnomeVFSMethod *method,
831 GnomeVFSContext *context)
833 SshHandle *handle = NULL;
835 GnomeVFSResult result;
839 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
841 return GNOME_VFS_ERROR_INVALID_URI;
843 quoted_name = g_shell_quote (name);
845 cmd = g_strdup_printf ("mkdir %s", quoted_name);
846 result = ssh_connect (&handle, uri, cmd);
849 g_free (quoted_name);
851 if (result != GNOME_VFS_OK) {
855 ssh_wait_and_destroy (handle, context);
860 static GnomeVFSResult
861 do_remove_directory (GnomeVFSMethod *method,
863 GnomeVFSContext *context)
865 SshHandle *handle = NULL;
867 GnomeVFSResult result;
871 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
873 return GNOME_VFS_ERROR_INVALID_URI;
875 quoted_name = g_shell_quote (name);
877 cmd = g_strdup_printf ("rm -rf %s", quoted_name);
878 result = ssh_connect (&handle, uri, cmd);
881 g_free (quoted_name);
883 if (result != GNOME_VFS_OK) {
887 ssh_wait_and_destroy (handle, context);
892 static GnomeVFSResult
893 do_move (GnomeVFSMethod *method,
894 GnomeVFSURI *old_uri,
895 GnomeVFSURI *new_uri,
896 gboolean force_replace,
897 GnomeVFSContext *context)
899 SshHandle *handle = NULL;
902 char *old_name, *new_name;
903 char *quoted_old_name, *quoted_new_name;
906 res = do_check_same_fs (method, old_uri, new_uri, &same_fs, context);
907 if (res != GNOME_VFS_OK) {
911 old_name = gnome_vfs_unescape_string (old_uri->text, G_DIR_SEPARATOR_S);
912 new_name = gnome_vfs_unescape_string (new_uri->text, G_DIR_SEPARATOR_S);
914 if ((old_name == NULL) || (new_name == NULL)) {
917 return GNOME_VFS_ERROR_INVALID_URI;
919 quoted_old_name = g_shell_quote (old_name);
920 quoted_new_name = g_shell_quote (new_name);
922 cmd = g_strdup_printf ("mv %s %s", quoted_old_name, quoted_new_name);
923 res = ssh_connect (&handle, old_uri, cmd);
927 g_free (quoted_old_name);
928 g_free (quoted_new_name);
930 if (res != GNOME_VFS_OK) {
934 ssh_wait_and_destroy (handle, context);
940 do_unlink (GnomeVFSMethod *method,
942 GnomeVFSContext *context)
944 SshHandle *handle = NULL;
946 GnomeVFSResult result;
950 name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
952 return GNOME_VFS_ERROR_INVALID_URI;
954 quoted_name = g_shell_quote (name);
956 cmd = g_strdup_printf ("rm -rf %s", quoted_name);
957 result = ssh_connect (&handle, uri, cmd);
960 g_free (quoted_name);
962 if (result != GNOME_VFS_OK) {
966 ssh_wait_and_destroy (handle, context);
971 static GnomeVFSResult
972 do_check_same_fs (GnomeVFSMethod *method,
975 gboolean *same_fs_return,
976 GnomeVFSContext *context)
978 const gchar *a_host_name, *b_host_name;
979 const gchar *a_user_name, *b_user_name;
981 g_return_val_if_fail (a != NULL, GNOME_VFS_ERROR_INTERNAL);
982 g_return_val_if_fail (b != NULL, GNOME_VFS_ERROR_INTERNAL);
984 a_host_name = gnome_vfs_uri_get_host_name (a);
985 b_host_name = gnome_vfs_uri_get_host_name (b);
986 a_user_name = gnome_vfs_uri_get_user_name (a);
987 b_user_name = gnome_vfs_uri_get_user_name (b);
989 g_return_val_if_fail (a_host_name != NULL, GNOME_VFS_ERROR_INVALID_URI); g_return_val_if_fail (b_host_name != NULL, GNOME_VFS_ERROR_INVALID_URI);
990 if (a_user_name == NULL) {
991 a_user_name = g_get_user_name ();
993 if (b_user_name == NULL) {
994 b_user_name = g_get_user_name ();
997 if (same_fs_return != NULL) {
999 ((!strcmp (a_host_name, b_host_name))
1000 && (!strcmp (a_user_name, b_user_name)));
1003 return GNOME_VFS_OK;
1006 static GnomeVFSResult
1007 do_set_file_info (GnomeVFSMethod *method,
1009 const GnomeVFSFileInfo *info,
1010 GnomeVFSSetFileInfoMask mask,
1011 GnomeVFSContext *context)
1013 SshHandle *handle = NULL;
1015 GnomeVFSResult result=GNOME_VFS_OK;
1018 full_name = gnome_vfs_unescape_string (uri->text, G_DIR_SEPARATOR_S);
1019 if (full_name == NULL) {
1020 return GNOME_VFS_ERROR_INVALID_URI;
1023 if (mask & GNOME_VFS_SET_FILE_INFO_NAME) {
1027 char *quoted_full_name;
1028 char *quoted_new_name;
1030 encoded_dir = gnome_vfs_uri_extract_dirname (uri);
1031 dir = gnome_vfs_unescape_string (encoded_dir, G_DIR_SEPARATOR_S);
1032 g_free (encoded_dir);
1033 g_assert (dir != NULL);
1035 /* FIXME bugzilla.eazel.com 645: This needs to return
1036 * an error for incoming names with "/" characters in
1037 * them, instead of moving the file.
1040 if (dir[strlen (dir) - 1] != '/') {
1041 new_name = g_strconcat (dir, "/", info->name, NULL);
1043 new_name = g_strconcat (dir, info->name, NULL);
1046 /* FIXME: escape for shell */
1047 quoted_new_name = g_shell_quote (new_name);
1048 quoted_full_name = g_shell_quote (full_name);
1049 cmd = g_strdup_printf ("mv %s %s", quoted_full_name,
1051 result = ssh_connect (&handle, uri, cmd);
1055 g_free (quoted_new_name);
1056 g_free (quoted_full_name);
1059 if (result != GNOME_VFS_OK) {
1063 /* Read all info from remote host */
1067 GnomeVFSFileSize bytes_read;
1068 res = ssh_read (handle, &c, 1, &bytes_read);
1069 if (bytes_read == 0 || res != GNOME_VFS_OK)
1073 ssh_wait_and_destroy (handle, context);
1080 static GnomeVFSResult
1081 do_get_file_info_from_handle (GnomeVFSMethodHandle *method_handle,
1082 GnomeVFSFileInfo *file_info,
1083 GnomeVFSFileInfoOptions options)
1085 return GNOME_VFS_ERROR_WRONG_FORMAT;
1090 do_is_local (GnomeVFSMethod *method, const GnomeVFSURI *uri)
1096 vfs_module_init (const char *method_name, const char *args)
1102 vfs_module_shutdown (GnomeVFSMethod *method)