summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2008-05-19 14:53:33 +1000
committerDamien Miller <djm@mindrot.org>2008-05-19 14:53:33 +1000
commitd671e5a978efd5ba949d3fdcd03f728dcd68c636 (patch)
treef63127fe29690fbe2c00f7b50d7807dc24288e29 /sftp-client.c
parent354c48c641e7fbdc273ee8e1239ff71d73a1ec3e (diff)
- djm@cvs.openbsd.org 2008/04/18 12:32:11
[sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c sftp.h] introduce sftp extension methods statvfs@openssh.com and fstatvfs@openssh.com that implement statvfs(2)-like operations, based on a patch from miklos AT szeredi.hu (bz#1399) also add a "df" command to the sftp client that uses the statvfs@openssh.com to produce a df(1)-like display of filesystem space and inode utilisation ok markus@
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c120
1 files changed, 117 insertions, 3 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 69c637785..1e54348b7 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.81 2008/03/23 12:54:01 djm Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.82 2008/04/18 12:32:11 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -24,6 +24,7 @@
24 24
25#include <sys/types.h> 25#include <sys/types.h>
26#include <sys/param.h> 26#include <sys/param.h>
27#include <sys/statvfs.h>
27#include "openbsd-compat/sys-queue.h" 28#include "openbsd-compat/sys-queue.h"
28#ifdef HAVE_SYS_STAT_H 29#ifdef HAVE_SYS_STAT_H
29# include <sys/stat.h> 30# include <sys/stat.h>
@@ -65,7 +66,9 @@ struct sftp_conn {
65 u_int num_requests; 66 u_int num_requests;
66 u_int version; 67 u_int version;
67 u_int msg_id; 68 u_int msg_id;
68#define SFTP_EXT_POSIX_RENAME 1 69#define SFTP_EXT_POSIX_RENAME 0x00000001
70#define SFTP_EXT_STATVFS 0x00000002
71#define SFTP_EXT_FSTATVFS 0x00000004
69 u_int exts; 72 u_int exts;
70}; 73};
71 74
@@ -238,6 +241,56 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
238 return(a); 241 return(a);
239} 242}
240 243
244static int
245get_decode_statvfs(int fd, struct statvfs *st, u_int expected_id, int quiet)
246{
247 Buffer msg;
248 u_int type, id, flag;
249
250 buffer_init(&msg);
251 get_msg(fd, &msg);
252
253 type = buffer_get_char(&msg);
254 id = buffer_get_int(&msg);
255
256 debug3("Received statvfs reply T:%u I:%u", type, id);
257 if (id != expected_id)
258 fatal("ID mismatch (%u != %u)", id, expected_id);
259 if (type == SSH2_FXP_STATUS) {
260 int status = buffer_get_int(&msg);
261
262 if (quiet)
263 debug("Couldn't statvfs: %s", fx2txt(status));
264 else
265 error("Couldn't statvfs: %s", fx2txt(status));
266 buffer_free(&msg);
267 return -1;
268 } else if (type != SSH2_FXP_EXTENDED_REPLY) {
269 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
270 SSH2_FXP_EXTENDED_REPLY, type);
271 }
272
273 bzero(st, sizeof(*st));
274 st->f_bsize = buffer_get_int(&msg);
275 st->f_frsize = buffer_get_int(&msg);
276 st->f_blocks = buffer_get_int64(&msg);
277 st->f_bfree = buffer_get_int64(&msg);
278 st->f_bavail = buffer_get_int64(&msg);
279 st->f_files = buffer_get_int64(&msg);
280 st->f_ffree = buffer_get_int64(&msg);
281 st->f_favail = buffer_get_int64(&msg);
282 st->f_fsid = buffer_get_int(&msg);
283 flag = buffer_get_int(&msg);
284 st->f_namemax = buffer_get_int(&msg);
285
286 st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
287 st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
288
289 buffer_free(&msg);
290
291 return 0;
292}
293
241struct sftp_conn * 294struct sftp_conn *
242do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) 295do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
243{ 296{
@@ -272,8 +325,15 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
272 char *value = buffer_get_string(&msg, NULL); 325 char *value = buffer_get_string(&msg, NULL);
273 326
274 debug2("Init extension: \"%s\"", name); 327 debug2("Init extension: \"%s\"", name);
275 if (strcmp(name, "posix-rename@openssh.com") == 0) 328 if (strcmp(name, "posix-rename@openssh.com") == 0 &&
329 strcmp(value, "1") == 0)
276 exts |= SFTP_EXT_POSIX_RENAME; 330 exts |= SFTP_EXT_POSIX_RENAME;
331 if (strcmp(name, "statvfs@openssh.com") == 0 &&
332 strcmp(value, "1") == 0)
333 exts |= SFTP_EXT_STATVFS;
334 if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
335 strcmp(value, "1") == 0)
336 exts |= SFTP_EXT_FSTATVFS;
277 xfree(name); 337 xfree(name);
278 xfree(value); 338 xfree(value);
279 } 339 }
@@ -749,6 +809,60 @@ do_readlink(struct sftp_conn *conn, char *path)
749} 809}
750#endif 810#endif
751 811
812int
813do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st,
814 int quiet)
815{
816 Buffer msg;
817 u_int id;
818
819 if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
820 error("Server does not support statvfs@openssh.com extension");
821 return -1;
822 }
823
824 id = conn->msg_id++;
825
826 buffer_init(&msg);
827 buffer_clear(&msg);
828 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
829 buffer_put_int(&msg, id);
830 buffer_put_cstring(&msg, "statvfs@openssh.com");
831 buffer_put_cstring(&msg, path);
832 send_msg(conn->fd_out, &msg);
833 buffer_free(&msg);
834
835 return get_decode_statvfs(conn->fd_in, st, id, quiet);
836}
837
838#ifdef notyet
839int
840do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
841 struct statvfs *st, int quiet)
842{
843 Buffer msg;
844 u_int id;
845
846 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
847 error("Server does not support fstatvfs@openssh.com extension");
848 return -1;
849 }
850
851 id = conn->msg_id++;
852
853 buffer_init(&msg);
854 buffer_clear(&msg);
855 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
856 buffer_put_int(&msg, id);
857 buffer_put_cstring(&msg, "fstatvfs@openssh.com");
858 buffer_put_string(&msg, handle, handle_len);
859 send_msg(conn->fd_out, &msg);
860 buffer_free(&msg);
861
862 return get_decode_statvfs(conn->fd_in, st, id, quiet);
863}
864#endif
865
752static void 866static void
753send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, 867send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
754 char *handle, u_int handle_len) 868 char *handle, u_int handle_len)