root/src/vfs/sftpfs/dir.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. sftpfs_opendir
  2. sftpfs_readdir
  3. sftpfs_closedir
  4. sftpfs_mkdir
  5. sftpfs_rmdir

   1 /* Virtual File System: SFTP file system.
   2    The internal functions: dirs
   3 
   4    Copyright (C) 2011-2025
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Ilia Maslakov <il.smind@gmail.com>, 2011
   9    Slava Zanko <slavazanko@gmail.com>, 2011, 2012
  10 
  11    This file is part of the Midnight Commander.
  12 
  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.
  17 
  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.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include <config.h>
  28 
  29 #include <libssh2.h>
  30 #include <libssh2_sftp.h>
  31 
  32 #include "lib/global.h"
  33 #include "lib/util.h"
  34 
  35 #include "internal.h"
  36 
  37 /*** global variables ****************************************************************************/
  38 
  39 /*** file scope macro definitions ****************************************************************/
  40 
  41 /*** file scope type declarations ****************************************************************/
  42 
  43 typedef struct
  44 {
  45     LIBSSH2_SFTP_HANDLE *handle;
  46     sftpfs_super_t *super;
  47 } sftpfs_dir_data_t;
  48 
  49 /*** file scope variables ************************************************************************/
  50 
  51 /*** file scope functions ************************************************************************/
  52 /* --------------------------------------------------------------------------------------------- */
  53 
  54 /* --------------------------------------------------------------------------------------------- */
  55 /*** public functions ****************************************************************************/
  56 /* --------------------------------------------------------------------------------------------- */
  57 /**
  58  * Open a directory stream corresponding to the directory name.
  59  *
  60  * @param vpath   path to directory
  61  * @param mcerror pointer to the error handler
  62  * @return directory data handler if success, NULL otherwise
  63  */
  64 
  65 void *
  66 sftpfs_opendir (const vfs_path_t *vpath, GError **mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
  67 {
  68     sftpfs_dir_data_t *sftpfs_dir;
  69     sftpfs_super_t *sftpfs_super;
  70     const vfs_path_element_t *path_element;
  71     LIBSSH2_SFTP_HANDLE *handle = NULL;
  72     const GString *fixfname;
  73 
  74     if (!sftpfs_op_init (&sftpfs_super, &path_element, vpath, mcerror))
  75         return NULL;
  76 
  77     fixfname = sftpfs_fix_filename (path_element->path);
  78 
  79     while (TRUE)
  80     {
  81         int libssh_errno;
  82 
  83         handle = libssh2_sftp_open_ex (sftpfs_super->sftp_session, fixfname->str, fixfname->len, 0,
  84                                        0, LIBSSH2_SFTP_OPENDIR);
  85         if (handle != NULL)
  86             break;
  87 
  88         libssh_errno = libssh2_session_last_errno (sftpfs_super->session);
  89         if (!sftpfs_waitsocket (sftpfs_super, libssh_errno, mcerror))
  90             return NULL;
  91     }
  92 
  93     sftpfs_dir = g_new0 (sftpfs_dir_data_t, 1);
  94     sftpfs_dir->handle = handle;
  95     sftpfs_dir->super = sftpfs_super;
  96 
  97     return (void *) sftpfs_dir;
  98 }
  99 
 100 /* --------------------------------------------------------------------------------------------- */
 101 /**
 102  * Get a pointer to a structure representing the next directory entry.
 103  *
 104  * @param data    directory data handler
 105  * @param mcerror pointer to the error handler
 106  * @return information about direntry if success, NULL otherwise
 107  */
 108 
 109 struct vfs_dirent *
 110 sftpfs_readdir (void *data, GError **mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 111 {
 112     char mem[BUF_MEDIUM];
 113     LIBSSH2_SFTP_ATTRIBUTES attrs;
 114     sftpfs_dir_data_t *sftpfs_dir = (sftpfs_dir_data_t *) data;
 115     int rc;
 116 
 117     mc_return_val_if_error (mcerror, NULL);
 118 
 119     do
 120     {
 121         rc = libssh2_sftp_readdir (sftpfs_dir->handle, mem, sizeof (mem), &attrs);
 122         if (rc >= 0)
 123             break;
 124 
 125         if (!sftpfs_waitsocket (sftpfs_dir->super, rc, mcerror))
 126             return NULL;
 127     }
 128     while (rc == LIBSSH2_ERROR_EAGAIN);
 129 
 130     return (rc != 0 ? vfs_dirent_init (NULL, mem, 0) : NULL);  // FIXME: inode
 131 }
 132 
 133 /* --------------------------------------------------------------------------------------------- */
 134 /**
 135  * Close the directory stream.
 136  *
 137  * @param data    directory data handler
 138  * @param mcerror pointer to the error handler
 139  * @return 0 if success, negative value otherwise
 140  */
 141 
 142 int
 143 sftpfs_closedir (void *data, GError **mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 144 {
 145     int rc;
 146     sftpfs_dir_data_t *sftpfs_dir = (sftpfs_dir_data_t *) data;
 147 
 148     mc_return_val_if_error (mcerror, -1);
 149 
 150     rc = libssh2_sftp_closedir (sftpfs_dir->handle);
 151     g_free (sftpfs_dir);
 152     return rc;
 153 }
 154 
 155 /* --------------------------------------------------------------------------------------------- */
 156 /**
 157  * Create a new directory.
 158  *
 159  * @param vpath   path directory
 160  * @param mode    mode (see man 2 open)
 161  * @param mcerror pointer to the error handler
 162  * @return 0 if success, negative value otherwise
 163  */
 164 
 165 int
 166 sftpfs_mkdir (const vfs_path_t *vpath, mode_t mode, GError **mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 167 {
 168     int res;
 169     sftpfs_super_t *sftpfs_super;
 170     const vfs_path_element_t *path_element;
 171     const GString *fixfname;
 172 
 173     if (!sftpfs_op_init (&sftpfs_super, &path_element, vpath, mcerror))
 174         return -1;
 175 
 176     fixfname = sftpfs_fix_filename (path_element->path);
 177 
 178     do
 179     {
 180         res =
 181             libssh2_sftp_mkdir_ex (sftpfs_super->sftp_session, fixfname->str, fixfname->len, mode);
 182         if (res >= 0)
 183             break;
 184 
 185         if (!sftpfs_waitsocket (sftpfs_super, res, mcerror))
 186             return -1;
 187     }
 188     while (res == LIBSSH2_ERROR_EAGAIN);
 189 
 190     return res;
 191 }
 192 
 193 /* --------------------------------------------------------------------------------------------- */
 194 /**
 195  * Remove a directory.
 196  *
 197  * @param vpath   path directory
 198  * @param mcerror pointer to the error handler
 199  * @return 0 if success, negative value otherwise
 200  */
 201 
 202 int
 203 sftpfs_rmdir (const vfs_path_t *vpath, GError **mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 204 {
 205     int res;
 206     sftpfs_super_t *sftpfs_super;
 207     const vfs_path_element_t *path_element;
 208     const GString *fixfname;
 209 
 210     if (!sftpfs_op_init (&sftpfs_super, &path_element, vpath, mcerror))
 211         return -1;
 212 
 213     fixfname = sftpfs_fix_filename (path_element->path);
 214 
 215     do
 216     {
 217         res = libssh2_sftp_rmdir_ex (sftpfs_super->sftp_session, fixfname->str, fixfname->len);
 218         if (res >= 0)
 219             break;
 220 
 221         if (!sftpfs_waitsocket (sftpfs_super, res, mcerror))
 222             return -1;
 223     }
 224     while (res == LIBSSH2_ERROR_EAGAIN);
 225 
 226     return res;
 227 }
 228 
 229 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */