Ticket #1535: SFTP support
[midnight-commander.git] / src / vfs / sftpfs / vfs_class.c
blobcc5795861c5c6d84c5332404a28e3598c59f2b51
1 /* Virtual File System: SFTP file system.
2 The VFS class functions
4 Copyright (C) 2011
5 The Free Software Foundation, Inc.
7 Written by:
8 Ilia Maslakov <il.smind@gmail.com>, 2011
9 Slava Zanko <slavazanko@gmail.com>, 2011, 2012
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <config.h>
28 #include <errno.h>
30 #include "lib/global.h"
31 #include "lib/vfs/gc.h"
32 #include "lib/tty/tty.h" /* tty_enable_interrupt_key () */
34 #include "internal.h"
36 /*** global variables ****************************************************************************/
38 struct vfs_class sftpfs_class;
40 /*** file scope macro definitions ****************************************************************/
42 /*** file scope type declarations ****************************************************************/
44 /*** file scope variables ************************************************************************/
46 /*** file scope functions ************************************************************************/
47 /* --------------------------------------------------------------------------------------------- */
48 /**
49 * Callback for VFS-class init action.
51 * @param me structure of VFS class
54 static int
55 sftpfs_cb_init (struct vfs_class *me)
57 (void) me;
59 if (libssh2_init (0) != 0)
60 return 0;
62 sftpfs_filename_buffer = g_string_new ("");
63 sftpfs_init_config_variables_patterns ();
64 return 1;
67 /* --------------------------------------------------------------------------------------------- */
68 /**
69 * Callback for VFS-class deinit action.
71 * @param me structure of VFS class
74 static void
75 sftpfs_cb_done (struct vfs_class *me)
77 (void) me;
79 sftpfs_deinit_config_variables_patterns ();
80 g_string_free (sftpfs_filename_buffer, TRUE);
81 libssh2_exit ();
84 /* --------------------------------------------------------------------------------------------- */
85 /**
86 * Callback for opening file.
88 * @param vpath path to file
89 * @param flags flags (see man 2 open)
90 * @param mode mode (see man 2 open)
91 * @return file data handler if success, NULL otherwise
94 static void *
95 sftpfs_cb_open (const vfs_path_t * vpath, int flags, mode_t mode)
97 vfs_file_handler_t *file_handler;
98 const vfs_path_element_t *path_element;
99 struct vfs_s_super *super;
100 const char *path_super;
101 struct vfs_s_inode *path_inode;
102 GError *error = NULL;
103 gboolean is_changed = FALSE;
105 path_element = vfs_path_get_by_index (vpath, -1);
107 path_super = vfs_s_get_path (vpath, &super, 0);
108 if (path_super == NULL)
109 return NULL;
111 path_inode = vfs_s_find_inode (path_element->class, super, path_super, LINK_FOLLOW, FL_NONE);
112 if (path_inode != NULL && ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)))
114 path_element->class->verrno = EEXIST;
115 return NULL;
118 if (path_inode == NULL)
120 char *dirname, *name;
121 struct vfs_s_entry *ent;
122 struct vfs_s_inode *dir;
124 dirname = g_path_get_dirname (path_super);
125 name = g_path_get_basename (path_super);
126 dir = vfs_s_find_inode (path_element->class, super, dirname, LINK_FOLLOW, FL_DIR);
127 if (dir == NULL)
129 g_free (dirname);
130 g_free (name);
131 return NULL;
133 ent = vfs_s_generate_entry (path_element->class, name, dir, 0755);
134 path_inode = ent->ino;
135 vfs_s_insert_entry (path_element->class, dir, ent);
136 g_free (dirname);
137 g_free (name);
138 is_changed = TRUE;
141 if (S_ISDIR (path_inode->st.st_mode))
143 path_element->class->verrno = EISDIR;
144 return NULL;
147 file_handler = g_new0 (vfs_file_handler_t, 1);
148 file_handler->pos = 0;
149 file_handler->ino = path_inode;
150 file_handler->handle = -1;
151 file_handler->changed = is_changed;
152 file_handler->linear = 0;
153 file_handler->data = NULL;
155 if (!sftpfs_open_file (file_handler, flags, mode, &error))
157 sftpfs_show_error (&error);
158 g_free (file_handler);
159 return NULL;
162 vfs_rmstamp (path_element->class, (vfsid) super);
163 super->fd_usage++;
164 file_handler->ino->st.st_nlink++;
165 return file_handler;
168 /* --------------------------------------------------------------------------------------------- */
170 * Callback for opening directory.
172 * @param vpath path to directory
173 * @return directory data handler if success, NULL otherwise
176 static void *
177 sftpfs_cb_opendir (const vfs_path_t * vpath)
179 GError *error = NULL;
180 void *ret_value;
182 /* reset interrupt flag */
183 tty_got_interrupt ();
185 ret_value = sftpfs_opendir (vpath, &error);
186 sftpfs_show_error (&error);
187 return ret_value;
190 /* --------------------------------------------------------------------------------------------- */
192 * Callback for reading directory entry.
194 * @param data directory data handler
195 * @return information about direntry if success, NULL otherwise
198 static void *
199 sftpfs_cb_readdir (void *data)
201 GError *error = NULL;
202 union vfs_dirent *sftpfs_dirent;
204 if (tty_got_interrupt ())
206 tty_disable_interrupt_key ();
207 return NULL;
210 sftpfs_dirent = sftpfs_readdir (data, &error);
211 if (!sftpfs_show_error (&error))
213 if (sftpfs_dirent != NULL)
214 vfs_print_message (_("sftp: (Ctrl-G break) Listing... %s"), sftpfs_dirent->dent.d_name);
215 else
216 vfs_print_message (_("sftp: Listing done."));
219 return sftpfs_dirent;
222 /* --------------------------------------------------------------------------------------------- */
224 * Callback for closing directory.
226 * @param data directory data handler
227 * @return 0 if sucess, negative value otherwise
230 static int
231 sftpfs_cb_closedir (void *data)
233 int rc;
234 GError *error = NULL;
236 rc = sftpfs_closedir (data, &error);
237 sftpfs_show_error (&error);
238 return rc;
241 /* --------------------------------------------------------------------------------------------- */
243 * Callback for lstat VFS-function.
245 * @param vpath path to file or directory
246 * @param buf buffer for store stat-info
247 * @return 0 if sucess, negative value otherwise
250 static int
251 sftpfs_cb_lstat (const vfs_path_t * vpath, struct stat *buf)
253 int rc;
254 GError *error = NULL;
256 rc = sftpfs_lstat (vpath, buf, &error);
257 sftpfs_show_error (&error);
258 return rc;
261 /* --------------------------------------------------------------------------------------------- */
263 * Callback for stat VFS-function.
265 * @param vpath path to file or directory
266 * @param buf buffer for store stat-info
267 * @return 0 if sucess, negative value otherwise
270 static int
271 sftpfs_cb_stat (const vfs_path_t * vpath, struct stat *buf)
273 int rc;
274 GError *error = NULL;
276 rc = sftpfs_stat (vpath, buf, &error);
277 sftpfs_show_error (&error);
278 return rc;
281 /* --------------------------------------------------------------------------------------------- */
283 * Callback for fstat VFS-function.
285 * @param data file data handler
286 * @param buf buffer for store stat-info
287 * @return 0 if sucess, negative value otherwise
290 static int
291 sftpfs_cb_fstat (void *data, struct stat *buf)
293 int rc;
294 GError *error = NULL;
296 rc = sftpfs_fstat (data, buf, &error);
297 sftpfs_show_error (&error);
298 return rc;
301 /* --------------------------------------------------------------------------------------------- */
303 * Callback for readlink VFS-function.
305 * @param vpath path to file or directory
306 * @param buf buffer for store stat-info
307 * @param size buffer size
308 * @return 0 if sucess, negative value otherwise
311 static int
312 sftpfs_cb_readlink (const vfs_path_t * vpath, char *buf, size_t size)
314 int rc;
315 GError *error = NULL;
317 rc = sftpfs_readlink (vpath, buf, size, &error);
318 sftpfs_show_error (&error);
319 return rc;
322 /* --------------------------------------------------------------------------------------------- */
324 * Callback for utime VFS-function.
326 * @param vpath unused
327 * @param times unused
328 * @return always 0
331 static int
332 sftpfs_cb_utime (const vfs_path_t * vpath, struct utimbuf *times)
334 (void) vpath;
335 (void) times;
337 return 0;
340 /* --------------------------------------------------------------------------------------------- */
342 * Callback for symlink VFS-function.
344 * @param vpath1 path to file or directory
345 * @param vpath2 path to symlink
346 * @return 0 if sucess, negative value otherwise
349 static int
350 sftpfs_cb_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
352 int rc;
353 GError *error = NULL;
355 rc = sftpfs_symlink (vpath1, vpath2, &error);
356 sftpfs_show_error (&error);
357 return rc;
360 /* --------------------------------------------------------------------------------------------- */
362 * Callback for symlink VFS-function.
364 * @param vpath unused
365 * @param mode unused
366 * @param dev unused
367 * @return always 0
370 static int
371 sftpfs_cb_mknod (const vfs_path_t * vpath, mode_t mode, dev_t dev)
373 (void) vpath;
374 (void) mode;
375 (void) dev;
377 return 0;
380 /* --------------------------------------------------------------------------------------------- */
382 * Callback for link VFS-function.
384 * @param vpath1 unused
385 * @param vpath2 unused
386 * @return always 0
389 static int
390 sftpfs_cb_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
392 (void) vpath1;
393 (void) vpath2;
395 return 0;
398 /* --------------------------------------------------------------------------------------------- */
400 * Callback for chown VFS-function.
402 * @param vpath unused
403 * @param owner unused
404 * @param group unused
405 * @return always 0
408 static int
409 sftpfs_cb_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
411 (void) vpath;
412 (void) owner;
413 (void) group;
415 return 0;
418 /* --------------------------------------------------------------------------------------------- */
420 * Callback for reading file content.
422 * @param data file data handler
423 * @param buffer buffer for data
424 * @param count data size
425 * @return 0 if sucess, negative value otherwise
428 static ssize_t
429 sftpfs_cb_read (void *data, char *buffer, size_t count)
431 int rc;
432 GError *error = NULL;
433 vfs_file_handler_t *fh = (vfs_file_handler_t *) data;
435 if (tty_got_interrupt ())
437 tty_disable_interrupt_key ();
438 return 0;
441 rc = sftpfs_read_file (fh, buffer, count, &error);
442 sftpfs_show_error (&error);
443 return rc;
446 /* --------------------------------------------------------------------------------------------- */
448 * Callback for writing file content.
450 * @param data file data handler
451 * @param buf buffer for data
452 * @param count data size
453 * @return 0 if sucess, negative value otherwise
456 static ssize_t
457 sftpfs_cb_write (void *data, const char *buf, size_t nbyte)
459 int rc;
460 GError *error = NULL;
461 vfs_file_handler_t *fh = (vfs_file_handler_t *) data;
463 rc = sftpfs_write_file (fh, buf, nbyte, &error);
464 sftpfs_show_error (&error);
465 return rc;
468 /* --------------------------------------------------------------------------------------------- */
470 * Callback for close file.
472 * @param data file data handler
473 * @return 0 if sucess, negative value otherwise
476 static int
477 sftpfs_cb_close (void *data)
479 int rc;
480 GError *error = NULL;
481 struct vfs_s_super *super;
482 vfs_file_handler_t *file_handler = (vfs_file_handler_t *) data;
484 super = file_handler->ino->super;
486 super->fd_usage--;
487 if (super->fd_usage == 0)
488 vfs_stamp_create (&sftpfs_class, super);
490 rc = sftpfs_close_file (file_handler, &error);
491 sftpfs_show_error (&error);
493 if (file_handler->handle != -1)
494 close (file_handler->handle);
496 vfs_s_free_inode (&sftpfs_class, file_handler->ino);
497 g_free (file_handler);
499 return rc;
502 /* --------------------------------------------------------------------------------------------- */
504 * Callback for chmod VFS-function.
506 * @param vpath path to file or directory
507 * @param mode mode (see man 2 open)
508 * @return 0 if sucess, negative value otherwise
511 static int
512 sftpfs_cb_chmod (const vfs_path_t * vpath, mode_t mode)
514 int rc;
515 GError *error = NULL;
517 rc = sftpfs_chmod (vpath, mode, &error);
518 sftpfs_show_error (&error);
519 return rc;
522 /* --------------------------------------------------------------------------------------------- */
524 * Callback for mkdir VFS-function.
526 * @param vpath path directory
527 * @param mode mode (see man 2 open)
528 * @return 0 if sucess, negative value otherwise
531 static int
532 sftpfs_cb_mkdir (const vfs_path_t * vpath, mode_t mode)
534 int rc;
535 GError *error = NULL;
537 rc = sftpfs_mkdir (vpath, mode, &error);
538 sftpfs_show_error (&error);
539 return rc;
542 /* --------------------------------------------------------------------------------------------- */
544 * Callback for rmdir VFS-function.
546 * @param vpath path directory
547 * @return 0 if sucess, negative value otherwise
550 static int
551 sftpfs_cb_rmdir (const vfs_path_t * vpath)
553 int rc;
554 GError *error = NULL;
556 rc = sftpfs_rmdir (vpath, &error);
557 sftpfs_show_error (&error);
558 return rc;
561 /* --------------------------------------------------------------------------------------------- */
563 * Callback for lseek VFS-function.
565 * @param data file data handler
566 * @param offset file offset
567 * @param whence method of seek (at begin, at current, at end)
568 * @return 0 if sucess, negative value otherwise
571 static off_t
572 sftpfs_cb_lseek (void *data, off_t offset, int whence)
574 off_t ret_offset;
575 vfs_file_handler_t *file_handler = (vfs_file_handler_t *) data;
576 GError *error = NULL;
578 ret_offset = sftpfs_lseek (file_handler, offset, whence, &error);
579 sftpfs_show_error (&error);
580 return ret_offset;
583 /* --------------------------------------------------------------------------------------------- */
585 * Callback for unlink VFS-function.
587 * @param vpath path to file or directory
588 * @return 0 if sucess, negative value otherwise
591 static int
592 sftpfs_cb_unlink (const vfs_path_t * vpath)
594 int rc;
595 GError *error = NULL;
597 rc = sftpfs_unlink (vpath, &error);
598 sftpfs_show_error (&error);
599 return rc;
602 /* --------------------------------------------------------------------------------------------- */
604 * Callback for rename VFS-function.
606 * @param vpath1 path to source file or directory
607 * @param vpath2 path to destination file or directory
608 * @return 0 if sucess, negative value otherwise
611 static int
612 sftpfs_cb_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
614 int rc;
615 GError *error = NULL;
617 rc = sftpfs_rename (vpath1, vpath2, &error);
618 sftpfs_show_error (&error);
619 return rc;
622 /* --------------------------------------------------------------------------------------------- */
624 * Callback for errno VFS-function.
626 * @param me unused
627 * @return value of errno global variable
630 static int
631 sftpfs_cb_errno (struct vfs_class *me)
633 (void) me;
634 return errno;
637 /* --------------------------------------------------------------------------------------------- */
638 /*** public functions ****************************************************************************/
639 /* --------------------------------------------------------------------------------------------- */
641 * Initialization of VFS class structure.
643 * @return the VFS class structure.
646 void
647 sftpfs_init_class (void)
649 memset (&sftpfs_class, 0, sizeof (struct vfs_class));
650 sftpfs_class.name = "sftpfs";
651 sftpfs_class.prefix = "sftp";
652 sftpfs_class.flags = VFSF_NOLINKS;
655 /* --------------------------------------------------------------------------------------------- */
657 * Initialization of VFS class callbacks.
660 void
661 sftpfs_init_class_callbacks (void)
663 sftpfs_class.init = sftpfs_cb_init;
664 sftpfs_class.done = sftpfs_cb_done;
666 sftpfs_class.opendir = sftpfs_cb_opendir;
667 sftpfs_class.readdir = sftpfs_cb_readdir;
668 sftpfs_class.closedir = sftpfs_cb_closedir;
669 sftpfs_class.mkdir = sftpfs_cb_mkdir;
670 sftpfs_class.rmdir = sftpfs_cb_rmdir;
672 sftpfs_class.stat = sftpfs_cb_stat;
673 sftpfs_class.lstat = sftpfs_cb_lstat;
674 sftpfs_class.fstat = sftpfs_cb_fstat;
675 sftpfs_class.readlink = sftpfs_cb_readlink;
676 sftpfs_class.symlink = sftpfs_cb_symlink;
677 sftpfs_class.link = sftpfs_cb_link;
678 sftpfs_class.utime = sftpfs_cb_utime;
679 sftpfs_class.mknod = sftpfs_cb_mknod;
680 sftpfs_class.chown = sftpfs_cb_chown;
681 sftpfs_class.chmod = sftpfs_cb_chmod;
683 sftpfs_class.open = sftpfs_cb_open;
684 sftpfs_class.read = sftpfs_cb_read;
685 sftpfs_class.write = sftpfs_cb_write;
686 sftpfs_class.close = sftpfs_cb_close;
687 sftpfs_class.lseek = sftpfs_cb_lseek;
688 sftpfs_class.unlink = sftpfs_cb_unlink;
689 sftpfs_class.rename = sftpfs_cb_rename;
690 sftpfs_class.ferrno = sftpfs_cb_errno;
693 /* --------------------------------------------------------------------------------------------- */