1 /* Virtual File System: SFTP file system.
2 The VFS class functions
4 Copyright (C) 2011-2018
5 Free Software Foundation, Inc.
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/>.
30 #include "lib/global.h"
31 #include "lib/widget.h"
32 #include "lib/vfs/gc.h"
33 #include "lib/tty/tty.h" /* tty_enable_interrupt_key () */
37 /*** global variables ****************************************************************************/
39 struct vfs_class sftpfs_class
;
41 /*** file scope macro definitions ****************************************************************/
43 /*** file scope type declarations ****************************************************************/
45 /*** file scope variables ************************************************************************/
47 /*** file scope functions ************************************************************************/
48 /* --------------------------------------------------------------------------------------------- */
50 * Callback for VFS-class init action.
52 * @param me structure of VFS class
56 sftpfs_cb_init (struct vfs_class
*me
)
60 if (libssh2_init (0) != 0)
63 sftpfs_filename_buffer
= g_string_new ("");
64 sftpfs_init_config_variables_patterns ();
68 /* --------------------------------------------------------------------------------------------- */
70 * Callback for VFS-class deinit action.
72 * @param me structure of VFS class
76 sftpfs_cb_done (struct vfs_class
*me
)
80 sftpfs_deinit_config_variables_patterns ();
81 g_string_free (sftpfs_filename_buffer
, TRUE
);
85 /* --------------------------------------------------------------------------------------------- */
87 * Callback for opening file.
89 * @param vpath path to file
90 * @param flags flags (see man 2 open)
91 * @param mode mode (see man 2 open)
92 * @return file data handler if success, NULL otherwise
96 sftpfs_cb_open (const vfs_path_t
* vpath
, int flags
, mode_t mode
)
98 vfs_file_handler_t
*file_handler
;
99 const vfs_path_element_t
*path_element
;
100 struct vfs_s_super
*super
;
101 const char *path_super
;
102 struct vfs_s_inode
*path_inode
;
103 GError
*mcerror
= NULL
;
104 gboolean is_changed
= FALSE
;
106 path_element
= vfs_path_get_by_index (vpath
, -1);
108 path_super
= vfs_s_get_path (vpath
, &super
, 0);
109 if (path_super
== NULL
)
112 path_inode
= vfs_s_find_inode (path_element
->class, super
, path_super
, LINK_FOLLOW
, FL_NONE
);
113 if (path_inode
!= NULL
&& ((flags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
)))
115 path_element
->class->verrno
= EEXIST
;
119 if (path_inode
== NULL
)
121 char *dirname
, *name
;
122 struct vfs_s_entry
*ent
;
123 struct vfs_s_inode
*dir
;
125 dirname
= g_path_get_dirname (path_super
);
126 name
= g_path_get_basename (path_super
);
127 dir
= vfs_s_find_inode (path_element
->class, super
, dirname
, LINK_FOLLOW
, FL_DIR
);
134 ent
= vfs_s_generate_entry (path_element
->class, name
, dir
, 0755);
135 path_inode
= ent
->ino
;
136 vfs_s_insert_entry (path_element
->class, dir
, ent
);
142 if (S_ISDIR (path_inode
->st
.st_mode
))
144 path_element
->class->verrno
= EISDIR
;
148 file_handler
= g_new0 (vfs_file_handler_t
, 1);
149 file_handler
->pos
= 0;
150 file_handler
->ino
= path_inode
;
151 file_handler
->handle
= -1;
152 file_handler
->changed
= is_changed
;
153 file_handler
->linear
= LS_NOT_LINEAR
;
154 file_handler
->data
= NULL
;
156 if (!sftpfs_open_file (file_handler
, flags
, mode
, &mcerror
))
158 mc_error_message (&mcerror
, NULL
);
159 g_free (file_handler
);
163 vfs_rmstamp (path_element
->class, (vfsid
) super
);
165 file_handler
->ino
->st
.st_nlink
++;
169 /* --------------------------------------------------------------------------------------------- */
171 * Callback for opening directory.
173 * @param vpath path to directory
174 * @return directory data handler if success, NULL otherwise
178 sftpfs_cb_opendir (const vfs_path_t
* vpath
)
180 GError
*mcerror
= NULL
;
183 /* reset interrupt flag */
184 tty_got_interrupt ();
186 ret_value
= sftpfs_opendir (vpath
, &mcerror
);
187 mc_error_message (&mcerror
, NULL
);
191 /* --------------------------------------------------------------------------------------------- */
193 * Callback for reading directory entry.
195 * @param data directory data handler
196 * @return information about direntry if success, NULL otherwise
200 sftpfs_cb_readdir (void *data
)
202 GError
*mcerror
= NULL
;
203 union vfs_dirent
*sftpfs_dirent
;
205 if (tty_got_interrupt ())
207 tty_disable_interrupt_key ();
211 sftpfs_dirent
= sftpfs_readdir (data
, &mcerror
);
212 if (!mc_error_message (&mcerror
, NULL
))
214 if (sftpfs_dirent
!= NULL
)
215 vfs_print_message (_("sftp: (Ctrl-G break) Listing... %s"), sftpfs_dirent
->dent
.d_name
);
217 vfs_print_message ("%s", _("sftp: Listing done."));
220 return sftpfs_dirent
;
223 /* --------------------------------------------------------------------------------------------- */
225 * Callback for closing directory.
227 * @param data directory data handler
228 * @return 0 if success, negative value otherwise
232 sftpfs_cb_closedir (void *data
)
235 GError
*mcerror
= NULL
;
237 rc
= sftpfs_closedir (data
, &mcerror
);
238 mc_error_message (&mcerror
, NULL
);
242 /* --------------------------------------------------------------------------------------------- */
244 * Callback for lstat VFS-function.
246 * @param vpath path to file or directory
247 * @param buf buffer for store stat-info
248 * @return 0 if success, negative value otherwise
252 sftpfs_cb_lstat (const vfs_path_t
* vpath
, struct stat
*buf
)
255 GError
*mcerror
= NULL
;
257 rc
= sftpfs_lstat (vpath
, buf
, &mcerror
);
258 mc_error_message (&mcerror
, NULL
);
262 /* --------------------------------------------------------------------------------------------- */
264 * Callback for stat VFS-function.
266 * @param vpath path to file or directory
267 * @param buf buffer for store stat-info
268 * @return 0 if success, negative value otherwise
272 sftpfs_cb_stat (const vfs_path_t
* vpath
, struct stat
*buf
)
275 GError
*mcerror
= NULL
;
277 rc
= sftpfs_stat (vpath
, buf
, &mcerror
);
278 mc_error_message (&mcerror
, NULL
);
282 /* --------------------------------------------------------------------------------------------- */
284 * Callback for fstat VFS-function.
286 * @param data file data handler
287 * @param buf buffer for store stat-info
288 * @return 0 if success, negative value otherwise
292 sftpfs_cb_fstat (void *data
, struct stat
*buf
)
295 GError
*mcerror
= NULL
;
297 rc
= sftpfs_fstat (data
, buf
, &mcerror
);
298 mc_error_message (&mcerror
, NULL
);
302 /* --------------------------------------------------------------------------------------------- */
304 * Callback for readlink VFS-function.
306 * @param vpath path to file or directory
307 * @param buf buffer for store stat-info
308 * @param size buffer size
309 * @return 0 if success, negative value otherwise
313 sftpfs_cb_readlink (const vfs_path_t
* vpath
, char *buf
, size_t size
)
316 GError
*mcerror
= NULL
;
318 rc
= sftpfs_readlink (vpath
, buf
, size
, &mcerror
);
319 mc_error_message (&mcerror
, NULL
);
323 /* --------------------------------------------------------------------------------------------- */
325 * Callback for utime VFS-function.
327 * @param vpath path to file or directory
328 * @param times access and modification time to set
329 * @return 0 if success, negative value otherwise
333 sftpfs_cb_utime (const vfs_path_t
* vpath
, mc_timesbuf_t
* times
)
336 GError
*mcerror
= NULL
;
337 #ifdef HAVE_UTIMENSAT
338 time_t atime
= (*times
)[0].tv_sec
;
339 time_t mtime
= (*times
)[1].tv_sec
;
341 time_t atime
= times
->actime
;
342 time_t mtime
= times
->modtime
;
345 rc
= sftpfs_utime (vpath
, atime
, mtime
, &mcerror
);
346 mc_error_message (&mcerror
, NULL
);
350 /* --------------------------------------------------------------------------------------------- */
352 * Callback for symlink VFS-function.
354 * @param vpath1 path to file or directory
355 * @param vpath2 path to symlink
356 * @return 0 if success, negative value otherwise
360 sftpfs_cb_symlink (const vfs_path_t
* vpath1
, const vfs_path_t
* vpath2
)
363 GError
*mcerror
= NULL
;
365 rc
= sftpfs_symlink (vpath1
, vpath2
, &mcerror
);
366 mc_error_message (&mcerror
, NULL
);
370 /* --------------------------------------------------------------------------------------------- */
372 * Callback for symlink VFS-function.
374 * @param vpath unused
381 sftpfs_cb_mknod (const vfs_path_t
* vpath
, mode_t mode
, dev_t dev
)
390 /* --------------------------------------------------------------------------------------------- */
392 * Callback for link VFS-function.
394 * @param vpath1 unused
395 * @param vpath2 unused
400 sftpfs_cb_link (const vfs_path_t
* vpath1
, const vfs_path_t
* vpath2
)
408 /* --------------------------------------------------------------------------------------------- */
410 * Callback for chown VFS-function.
412 * @param vpath unused
413 * @param owner unused
414 * @param group unused
419 sftpfs_cb_chown (const vfs_path_t
* vpath
, uid_t owner
, gid_t group
)
428 /* --------------------------------------------------------------------------------------------- */
430 * Callback for reading file content.
432 * @param data file data handler
433 * @param buffer buffer for data
434 * @param count data size
435 * @return 0 if success, negative value otherwise
439 sftpfs_cb_read (void *data
, char *buffer
, size_t count
)
442 GError
*mcerror
= NULL
;
443 vfs_file_handler_t
*fh
= (vfs_file_handler_t
*) data
;
445 if (tty_got_interrupt ())
447 tty_disable_interrupt_key ();
451 rc
= sftpfs_read_file (fh
, buffer
, count
, &mcerror
);
452 mc_error_message (&mcerror
, NULL
);
456 /* --------------------------------------------------------------------------------------------- */
458 * Callback for writing file content.
460 * @param data file data handler
461 * @param buf buffer for data
462 * @param count data size
463 * @return 0 if success, negative value otherwise
467 sftpfs_cb_write (void *data
, const char *buf
, size_t nbyte
)
470 GError
*mcerror
= NULL
;
471 vfs_file_handler_t
*fh
= (vfs_file_handler_t
*) data
;
473 rc
= sftpfs_write_file (fh
, buf
, nbyte
, &mcerror
);
474 mc_error_message (&mcerror
, NULL
);
478 /* --------------------------------------------------------------------------------------------- */
480 * Callback for close file.
482 * @param data file data handler
483 * @return 0 if success, negative value otherwise
487 sftpfs_cb_close (void *data
)
490 GError
*mcerror
= NULL
;
491 struct vfs_s_super
*super
;
492 vfs_file_handler_t
*file_handler
= (vfs_file_handler_t
*) data
;
494 super
= file_handler
->ino
->super
;
497 if (super
->fd_usage
== 0)
498 vfs_stamp_create (&sftpfs_class
, super
);
500 rc
= sftpfs_close_file (file_handler
, &mcerror
);
501 mc_error_message (&mcerror
, NULL
);
503 if (file_handler
->handle
!= -1)
504 close (file_handler
->handle
);
506 vfs_s_free_inode (&sftpfs_class
, file_handler
->ino
);
507 g_free (file_handler
);
512 /* --------------------------------------------------------------------------------------------- */
514 * Callback for chmod VFS-function.
516 * @param vpath path to file or directory
517 * @param mode mode (see man 2 open)
518 * @return 0 if success, negative value otherwise
522 sftpfs_cb_chmod (const vfs_path_t
* vpath
, mode_t mode
)
525 GError
*mcerror
= NULL
;
527 rc
= sftpfs_chmod (vpath
, mode
, &mcerror
);
528 mc_error_message (&mcerror
, NULL
);
532 /* --------------------------------------------------------------------------------------------- */
534 * Callback for mkdir VFS-function.
536 * @param vpath path directory
537 * @param mode mode (see man 2 open)
538 * @return 0 if success, negative value otherwise
542 sftpfs_cb_mkdir (const vfs_path_t
* vpath
, mode_t mode
)
545 GError
*mcerror
= NULL
;
547 rc
= sftpfs_mkdir (vpath
, mode
, &mcerror
);
548 mc_error_message (&mcerror
, NULL
);
552 /* --------------------------------------------------------------------------------------------- */
554 * Callback for rmdir VFS-function.
556 * @param vpath path directory
557 * @return 0 if success, negative value otherwise
561 sftpfs_cb_rmdir (const vfs_path_t
* vpath
)
564 GError
*mcerror
= NULL
;
566 rc
= sftpfs_rmdir (vpath
, &mcerror
);
567 mc_error_message (&mcerror
, NULL
);
571 /* --------------------------------------------------------------------------------------------- */
573 * Callback for lseek VFS-function.
575 * @param data file data handler
576 * @param offset file offset
577 * @param whence method of seek (at begin, at current, at end)
578 * @return 0 if success, negative value otherwise
582 sftpfs_cb_lseek (void *data
, off_t offset
, int whence
)
585 vfs_file_handler_t
*file_handler
= (vfs_file_handler_t
*) data
;
586 GError
*mcerror
= NULL
;
588 ret_offset
= sftpfs_lseek (file_handler
, offset
, whence
, &mcerror
);
589 mc_error_message (&mcerror
, NULL
);
593 /* --------------------------------------------------------------------------------------------- */
595 * Callback for unlink VFS-function.
597 * @param vpath path to file or directory
598 * @return 0 if success, negative value otherwise
602 sftpfs_cb_unlink (const vfs_path_t
* vpath
)
605 GError
*mcerror
= NULL
;
607 rc
= sftpfs_unlink (vpath
, &mcerror
);
608 mc_error_message (&mcerror
, NULL
);
612 /* --------------------------------------------------------------------------------------------- */
614 * Callback for rename VFS-function.
616 * @param vpath1 path to source file or directory
617 * @param vpath2 path to destination file or directory
618 * @return 0 if success, negative value otherwise
622 sftpfs_cb_rename (const vfs_path_t
* vpath1
, const vfs_path_t
* vpath2
)
625 GError
*mcerror
= NULL
;
627 rc
= sftpfs_rename (vpath1
, vpath2
, &mcerror
);
628 mc_error_message (&mcerror
, NULL
);
632 /* --------------------------------------------------------------------------------------------- */
634 * Callback for errno VFS-function.
637 * @return value of errno global variable
641 sftpfs_cb_errno (struct vfs_class
*me
)
647 /* --------------------------------------------------------------------------------------------- */
649 * Callback for fill_names VFS function.
650 * Add SFTP connections to the 'Active VFS connections' list
653 * @param func callback function for adding SFTP-connection to list of active connections
657 sftpfs_cb_fill_names (struct vfs_class
*me
, fill_names_f func
)
663 for (iter
= sftpfs_subclass
.supers
; iter
!= NULL
; iter
= g_list_next (iter
))
665 const struct vfs_s_super
*super
= (const struct vfs_s_super
*) iter
->data
;
668 name
= vfs_path_element_build_pretty_path_str (super
->path_element
);
675 /* --------------------------------------------------------------------------------------------- */
676 /*** public functions ****************************************************************************/
677 /* --------------------------------------------------------------------------------------------- */
679 * Initialization of VFS class structure.
681 * @return the VFS class structure.
685 sftpfs_init_class (void)
687 memset (&sftpfs_class
, 0, sizeof (sftpfs_class
));
688 sftpfs_class
.name
= "sftpfs";
689 sftpfs_class
.prefix
= "sftp";
690 sftpfs_class
.flags
= VFSF_NOLINKS
;
693 /* --------------------------------------------------------------------------------------------- */
695 * Initialization of VFS class callbacks.
699 sftpfs_init_class_callbacks (void)
701 sftpfs_class
.init
= sftpfs_cb_init
;
702 sftpfs_class
.done
= sftpfs_cb_done
;
704 sftpfs_class
.fill_names
= sftpfs_cb_fill_names
;
706 sftpfs_class
.opendir
= sftpfs_cb_opendir
;
707 sftpfs_class
.readdir
= sftpfs_cb_readdir
;
708 sftpfs_class
.closedir
= sftpfs_cb_closedir
;
709 sftpfs_class
.mkdir
= sftpfs_cb_mkdir
;
710 sftpfs_class
.rmdir
= sftpfs_cb_rmdir
;
712 sftpfs_class
.stat
= sftpfs_cb_stat
;
713 sftpfs_class
.lstat
= sftpfs_cb_lstat
;
714 sftpfs_class
.fstat
= sftpfs_cb_fstat
;
715 sftpfs_class
.readlink
= sftpfs_cb_readlink
;
716 sftpfs_class
.symlink
= sftpfs_cb_symlink
;
717 sftpfs_class
.link
= sftpfs_cb_link
;
718 sftpfs_class
.utime
= sftpfs_cb_utime
;
719 sftpfs_class
.mknod
= sftpfs_cb_mknod
;
720 sftpfs_class
.chown
= sftpfs_cb_chown
;
721 sftpfs_class
.chmod
= sftpfs_cb_chmod
;
723 sftpfs_class
.open
= sftpfs_cb_open
;
724 sftpfs_class
.read
= sftpfs_cb_read
;
725 sftpfs_class
.write
= sftpfs_cb_write
;
726 sftpfs_class
.close
= sftpfs_cb_close
;
727 sftpfs_class
.lseek
= sftpfs_cb_lseek
;
728 sftpfs_class
.unlink
= sftpfs_cb_unlink
;
729 sftpfs_class
.rename
= sftpfs_cb_rename
;
730 sftpfs_class
.ferrno
= sftpfs_cb_errno
;
733 /* --------------------------------------------------------------------------------------------- */