1 /* Virtual File System: SFTP file system.
2 The VFS class functions
5 The 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/vfs/gc.h"
32 #include "lib/tty/tty.h" /* tty_enable_interrupt_key () */
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 /* --------------------------------------------------------------------------------------------- */
49 * Callback for VFS-class init action.
51 * @param me structure of VFS class
55 sftpfs_cb_init (struct vfs_class
*me
)
59 if (libssh2_init (0) != 0)
62 sftpfs_filename_buffer
= g_string_new ("");
63 sftpfs_init_config_variables_patterns ();
67 /* --------------------------------------------------------------------------------------------- */
69 * Callback for VFS-class deinit action.
71 * @param me structure of VFS class
75 sftpfs_cb_done (struct vfs_class
*me
)
79 sftpfs_deinit_config_variables_patterns ();
80 g_string_free (sftpfs_filename_buffer
, TRUE
);
84 /* --------------------------------------------------------------------------------------------- */
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
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
)
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
;
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
);
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
);
141 if (S_ISDIR (path_inode
->st
.st_mode
))
143 path_element
->class->verrno
= EISDIR
;
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
);
162 vfs_rmstamp (path_element
->class, (vfsid
) super
);
164 file_handler
->ino
->st
.st_nlink
++;
168 /* --------------------------------------------------------------------------------------------- */
170 * Callback for opening directory.
172 * @param vpath path to directory
173 * @return directory data handler if success, NULL otherwise
177 sftpfs_cb_opendir (const vfs_path_t
* vpath
)
179 GError
*error
= NULL
;
182 /* reset interrupt flag */
183 tty_got_interrupt ();
185 ret_value
= sftpfs_opendir (vpath
, &error
);
186 sftpfs_show_error (&error
);
190 /* --------------------------------------------------------------------------------------------- */
192 * Callback for reading directory entry.
194 * @param data directory data handler
195 * @return information about direntry if success, NULL otherwise
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 ();
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
);
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
231 sftpfs_cb_closedir (void *data
)
234 GError
*error
= NULL
;
236 rc
= sftpfs_closedir (data
, &error
);
237 sftpfs_show_error (&error
);
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
251 sftpfs_cb_lstat (const vfs_path_t
* vpath
, struct stat
*buf
)
254 GError
*error
= NULL
;
256 rc
= sftpfs_lstat (vpath
, buf
, &error
);
257 sftpfs_show_error (&error
);
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
271 sftpfs_cb_stat (const vfs_path_t
* vpath
, struct stat
*buf
)
274 GError
*error
= NULL
;
276 rc
= sftpfs_stat (vpath
, buf
, &error
);
277 sftpfs_show_error (&error
);
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
291 sftpfs_cb_fstat (void *data
, struct stat
*buf
)
294 GError
*error
= NULL
;
296 rc
= sftpfs_fstat (data
, buf
, &error
);
297 sftpfs_show_error (&error
);
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
312 sftpfs_cb_readlink (const vfs_path_t
* vpath
, char *buf
, size_t size
)
315 GError
*error
= NULL
;
317 rc
= sftpfs_readlink (vpath
, buf
, size
, &error
);
318 sftpfs_show_error (&error
);
322 /* --------------------------------------------------------------------------------------------- */
324 * Callback for utime VFS-function.
326 * @param vpath unused
327 * @param times unused
332 sftpfs_cb_utime (const vfs_path_t
* vpath
, struct utimbuf
*times
)
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
350 sftpfs_cb_symlink (const vfs_path_t
* vpath1
, const vfs_path_t
* vpath2
)
353 GError
*error
= NULL
;
355 rc
= sftpfs_symlink (vpath1
, vpath2
, &error
);
356 sftpfs_show_error (&error
);
360 /* --------------------------------------------------------------------------------------------- */
362 * Callback for symlink VFS-function.
364 * @param vpath unused
371 sftpfs_cb_mknod (const vfs_path_t
* vpath
, mode_t mode
, dev_t dev
)
380 /* --------------------------------------------------------------------------------------------- */
382 * Callback for link VFS-function.
384 * @param vpath1 unused
385 * @param vpath2 unused
390 sftpfs_cb_link (const vfs_path_t
* vpath1
, const vfs_path_t
* vpath2
)
398 /* --------------------------------------------------------------------------------------------- */
400 * Callback for chown VFS-function.
402 * @param vpath unused
403 * @param owner unused
404 * @param group unused
409 sftpfs_cb_chown (const vfs_path_t
* vpath
, uid_t owner
, gid_t group
)
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
429 sftpfs_cb_read (void *data
, char *buffer
, size_t count
)
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 ();
441 rc
= sftpfs_read_file (fh
, buffer
, count
, &error
);
442 sftpfs_show_error (&error
);
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
457 sftpfs_cb_write (void *data
, const char *buf
, size_t nbyte
)
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
);
468 /* --------------------------------------------------------------------------------------------- */
470 * Callback for close file.
472 * @param data file data handler
473 * @return 0 if sucess, negative value otherwise
477 sftpfs_cb_close (void *data
)
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
;
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
);
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
512 sftpfs_cb_chmod (const vfs_path_t
* vpath
, mode_t mode
)
515 GError
*error
= NULL
;
517 rc
= sftpfs_chmod (vpath
, mode
, &error
);
518 sftpfs_show_error (&error
);
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
532 sftpfs_cb_mkdir (const vfs_path_t
* vpath
, mode_t mode
)
535 GError
*error
= NULL
;
537 rc
= sftpfs_mkdir (vpath
, mode
, &error
);
538 sftpfs_show_error (&error
);
542 /* --------------------------------------------------------------------------------------------- */
544 * Callback for rmdir VFS-function.
546 * @param vpath path directory
547 * @return 0 if sucess, negative value otherwise
551 sftpfs_cb_rmdir (const vfs_path_t
* vpath
)
554 GError
*error
= NULL
;
556 rc
= sftpfs_rmdir (vpath
, &error
);
557 sftpfs_show_error (&error
);
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
572 sftpfs_cb_lseek (void *data
, off_t offset
, int whence
)
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
);
583 /* --------------------------------------------------------------------------------------------- */
585 * Callback for unlink VFS-function.
587 * @param vpath path to file or directory
588 * @return 0 if sucess, negative value otherwise
592 sftpfs_cb_unlink (const vfs_path_t
* vpath
)
595 GError
*error
= NULL
;
597 rc
= sftpfs_unlink (vpath
, &error
);
598 sftpfs_show_error (&error
);
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
612 sftpfs_cb_rename (const vfs_path_t
* vpath1
, const vfs_path_t
* vpath2
)
615 GError
*error
= NULL
;
617 rc
= sftpfs_rename (vpath1
, vpath2
, &error
);
618 sftpfs_show_error (&error
);
622 /* --------------------------------------------------------------------------------------------- */
624 * Callback for errno VFS-function.
627 * @return value of errno global variable
631 sftpfs_cb_errno (struct vfs_class
*me
)
637 /* --------------------------------------------------------------------------------------------- */
638 /*** public functions ****************************************************************************/
639 /* --------------------------------------------------------------------------------------------- */
641 * Initialization of VFS class structure.
643 * @return the VFS class structure.
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.
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 /* --------------------------------------------------------------------------------------------- */