[PATCH 3/3] extensions: Add current OpenSSH extensions

Michel Kraus mkraus+sgo at demonsphere.de
Sat May 16 18:00:59 BST 2015


Adds the extensions:
posix-rename at openssh.com v1
statvfs at openssh.com      v2
fstatvfs at openssh.com     v2
hardlink at openssh.com     v1
fsync at openssh.com        v1

(f)statvfs at openssh.com is set to Linux only. May work on other systems.

Signed-off-by: Michel Kraus <mkraus+sgo at demonsphere.de>
---
 sftpserver.h | 26 +++++++++++++++++++
 v3.c         | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 v4.c         |  7 ++++++
 v5.c         |  7 ++++++
 v6.c         |  7 ++++++
 5 files changed, 129 insertions(+)

diff --git a/sftpserver.h b/sftpserver.h
index 5e51365..466f2a5 100644
--- a/sftpserver.h
+++ b/sftpserver.h
@@ -316,6 +316,18 @@ uint32_t sftp_vany_space_available(struct sftpjob *job);
  */
 uint32_t sftp_v6_version_select(struct sftpjob *job);
 
+/** @brief @c fsync at openssh.com extension implementation
+ * @param job Job
+ * @return Error code
+ */
+uint32_t sftp_vany_fsync(struct sftpjob *job);
+
+/** @brief @c hardlink at openssh.com extension implementation
+ * @param job Job
+ * @return Error code
+ */
+uint32_t sftp_vany_hardlink(struct sftpjob *job);
+
 /** @brief @c posix-rename at openssh.org extension implementation
  * @param job Job
  * @return Error code
@@ -328,6 +340,20 @@ uint32_t sftp_vany_posix_rename(struct sftpjob *job);
  */
 uint32_t sftp_vany_statfs(struct sftpjob *job);
 
+#ifdef __linux__
+/** @brief @c fstatvfs at openssh.com extension implementation
+ * @param job Job
+ * @return Error code
+ */
+uint32_t sftp_vany_fstatvfs(struct sftpjob *job);
+
+/** @brief @c statvfs at openssh.com extension implementation
+ * @param job Job
+ * @return Error code
+ */
+uint32_t sftp_vany_statvfs(struct sftpjob *job);
+#endif
+
 /** @brief Send an @ref SSH_FXP_STATUS message based on @c errno
  * @param job Job
  */
diff --git a/v3.c b/v3.c
index c62af57..26d52f3 100644
--- a/v3.c
+++ b/v3.c
@@ -751,6 +751,81 @@ uint32_t sftp_vany_statfs(struct sftpjob *job) {
   return HANDLER_RESPONDED;
 }
 
+#ifdef __linux__
+static uint32_t sftp_vany_statvfs_send(struct sftpjob *job, int rc, struct statvfs *fs) {
+  if (rc < 0)
+    return HANDLER_ERRNO;
+  sftp_send_begin(job->worker);
+  sftp_send_uint8(job->worker, SSH_FXP_EXTENDED_REPLY);
+  sftp_send_uint32(job->worker, job->id);
+  sftp_send_uint64(job->worker, fs->f_bsize);
+  sftp_send_uint64(job->worker, fs->f_frsize);
+  sftp_send_uint64(job->worker, fs->f_blocks);
+  sftp_send_uint64(job->worker, fs->f_bfree);
+  sftp_send_uint64(job->worker, fs->f_bavail);
+  sftp_send_uint64(job->worker, fs->f_files);
+  sftp_send_uint64(job->worker, fs->f_ffree);
+  sftp_send_uint64(job->worker, fs->f_favail);
+  sftp_send_uint64(job->worker, fs->f_fsid);
+  sftp_send_uint64(job->worker, (fs->f_flag & ST_RDONLY ? 1 : 0) | (fs->f_flag & ST_NOSUID ? 2 : 0));
+  sftp_send_uint64(job->worker, fs->f_namemax);
+  sftp_send_end(job->worker);
+  return HANDLER_RESPONDED;
+}
+
+uint32_t sftp_vany_statvfs(struct sftpjob *job) {
+  char *path;
+  struct statvfs fs;
+
+  pcheck(sftp_parse_path(job, &path));
+  D(("sftp_vany_statfs %s", path));
+  return sftp_vany_statvfs_send(job, statvfs(path, &fs), &fs);
+}
+
+uint32_t sftp_vany_fstatvfs(struct sftpjob *job) {
+  int fd;
+  struct handleid id;
+  struct statvfs fs;
+  uint32_t rc;
+
+  pcheck(sftp_parse_handle(job, &id));
+  D(("sftp_vany_fstatvfs %"PRIu32" %"PRIu32, id.id, id.tag));
+  if((rc = sftp_handle_get_fd(&id, &fd, 0)))
+    return rc;
+  return sftp_vany_statvfs_send(job, fstatvfs(fd, &fs), &fs);
+}
+
+
+#endif
+
+uint32_t sftp_vany_fsync(struct sftpjob *job) {
+  int fd;
+  struct handleid id;
+  uint32_t rc;
+
+  pcheck(sftp_parse_handle(job, &id));
+  D(("sftp_v3_fstat %"PRIu32" %"PRIu32, id.id, id.tag));
+  if((rc = sftp_handle_get_fd(&id, &fd, 0)))
+    return rc;
+  if (fsync(fd) < 0)
+    return HANDLER_ERRNO;
+  return SSH_FX_OK;
+}
+
+uint32_t sftp_vany_hardlink(struct sftpjob *job) {
+  char *oldpath, *newlinkpath;
+
+  /* See also comment in v3.c for SSH_FXP_SYMLINK */
+  if(readonly)
+    return SSH_FX_PERMISSION_DENIED;
+  pcheck(sftp_parse_path(job, &oldpath));    /* aka existing-path/target-paths */
+  pcheck(sftp_parse_path(job, &newlinkpath));
+  D(("sftp_hardlink %s %s", oldpath, newlinkpath));
+  if(link(oldpath, newlinkpath) < 0)
+    return HANDLER_ERRNO;
+  return SSH_FX_OK;
+}
+
 static const struct sftpcmd sftpv3tab[] = {
   { SSH_FXP_INIT, sftp_vany_already_init },
   { SSH_FXP_OPEN, sftp_v34_open },
@@ -775,9 +850,16 @@ static const struct sftpcmd sftpv3tab[] = {
 };
 
 static const struct sftpextension v3_extensions[] = {
+  { "fsync at openssh.com", "1", sftp_vany_fsync },
+  { "hardlink at openssh.com", "1", sftp_vany_hardlink },
+  { "posix-rename at openssh.com", "1", sftp_vany_posix_rename },
   { "posix-rename at openssh.org", "", sftp_vany_posix_rename },
   { "space-available", "", sftp_vany_space_available },
   { "statfs at openssh.org", "", sftp_vany_statfs },
+#ifdef __linux__
+  { "statvfs at openssh.com", "2", sftp_vany_statvfs },
+  { "fstatvfs at openssh.com", "2", sftp_vany_fstatvfs },
+#endif
 };
 
 const struct sftpprotocol sftp_v3 = {
diff --git a/v4.c b/v4.c
index b6adf2c..9eff40f 100644
--- a/v4.c
+++ b/v4.c
@@ -284,10 +284,17 @@ static const struct sftpcmd sftpv4tab[] = {
 };
 
 static const struct sftpextension v4_extensions[] = {
+  { "fsync at openssh.com", "1", sftp_vany_fsync },
+  { "hardlink at openssh.com", "1", sftp_vany_hardlink },
+  { "posix-rename at openssh.com", "1", sftp_vany_posix_rename },
   { "posix-rename at openssh.org", "", sftp_vany_posix_rename },
   { "space-available", "", sftp_vany_space_available },
   { "statfs at openssh.org", "", sftp_vany_statfs },
   { "text-seek", "", sftp_vany_text_seek },
+#ifdef __linux__
+  { "statvfs at openssh.com", "2", sftp_vany_statvfs },
+  { "fstatvfs at openssh.com", "2", sftp_vany_fstatvfs },
+#endif
 };
 
 const struct sftpprotocol sftp_v4 = {
diff --git a/v5.c b/v5.c
index 184df43..7b367b7 100644
--- a/v5.c
+++ b/v5.c
@@ -477,10 +477,17 @@ static const struct sftpcmd sftpv5tab[] = {
 };
 
 static const struct sftpextension sftp_v5_extensions[] = {
+  { "fsync at openssh.com", "1", sftp_vany_fsync },
+  { "hardlink at openssh.com", "1", sftp_vany_hardlink },
+  { "posix-rename at openssh.com", "1", sftp_vany_posix_rename },
   { "posix-rename at openssh.org", "", sftp_vany_posix_rename },
   { "space-available", "", sftp_vany_space_available },
   { "statfs at openssh.org", "", sftp_vany_statfs },
   { "text-seek", "", sftp_vany_text_seek },
+#ifdef __linux__
+  { "statvfs at openssh.com", "2", sftp_vany_statvfs },
+  { "fstatvfs at openssh.com", "2", sftp_vany_fstatvfs },
+#endif
 };
 
 const struct sftpprotocol sftp_v5 = {
diff --git a/v6.c b/v6.c
index 40ffd91..44d0013 100644
--- a/v6.c
+++ b/v6.c
@@ -184,11 +184,18 @@ static const struct sftpcmd sftpv6tab[] = {
 /* TODO: file locking */
 
 static const struct sftpextension sftp_v6_extensions[] = {
+  { "fsync at openssh.com", "1", sftp_vany_fsync },
+  { "hardlink at openssh.com", "1", sftp_vany_hardlink },
+  { "posix-rename at openssh.com", "1", sftp_vany_posix_rename },
   { "posix-rename at openssh.org", "", sftp_vany_posix_rename },
   { "space-available", "", sftp_vany_space_available },
   { "statfs at openssh.org", "", sftp_vany_statfs },
   { "text-seek", "", sftp_vany_text_seek },
   { "version-select", "", sftp_v6_version_select },
+#ifdef __linux__
+  { "statvfs at openssh.com", "2", sftp_vany_statvfs },
+  { "fstatvfs at openssh.com", "2", sftp_vany_fstatvfs },
+#endif
 };
 
 const struct sftpprotocol sftp_v6 = {
-- 
2.1.0




More information about the sgo-software-discuss mailing list