summaryrefslogtreecommitdiff
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
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@
-rw-r--r--ChangeLog11
-rw-r--r--sftp-client.c120
-rw-r--r--sftp-client.h6
-rw-r--r--sftp-server.c75
-rw-r--r--sftp.124
-rw-r--r--sftp.c112
-rw-r--r--sftp.h6
7 files changed, 339 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index b32f93f0c..eba49fee6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -21,6 +21,15 @@
21 Use arc4random_uniform() when the desired random number upper bound 21 Use arc4random_uniform() when the desired random number upper bound
22 is not a power of two 22 is not a power of two
23 ok deraadt@ millert@ 23 ok deraadt@ millert@
24 - djm@cvs.openbsd.org 2008/04/18 12:32:11
25 [sftp-client.c sftp-client.h sftp-server.c sftp.1 sftp.c sftp.h]
26 introduce sftp extension methods statvfs@openssh.com and
27 fstatvfs@openssh.com that implement statvfs(2)-like operations,
28 based on a patch from miklos AT szeredi.hu (bz#1399)
29 also add a "df" command to the sftp client that uses the
30 statvfs@openssh.com to produce a df(1)-like display of filesystem
31 space and inode utilisation
32 ok markus@
24 33
2520080403 3420080403
26 - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile- 35 - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile-
@@ -3881,4 +3890,4 @@
3881 OpenServer 6 and add osr5bigcrypt support so when someone migrates 3890 OpenServer 6 and add osr5bigcrypt support so when someone migrates
3882 passwords between UnixWare and OpenServer they will still work. OK dtucker@ 3891 passwords between UnixWare and OpenServer they will still work. OK dtucker@
3883 3892
3884$Id: ChangeLog,v 1.4910 2008/05/19 04:50:00 djm Exp $ 3893$Id: ChangeLog,v 1.4911 2008/05/19 04:53:33 djm Exp $
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)
diff --git a/sftp-client.h b/sftp-client.h
index fd0630e9a..b102e1180 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.h,v 1.15 2008/01/11 07:22:28 chl Exp $ */ 1/* $OpenBSD: sftp-client.h,v 1.16 2008/04/18 12:32:11 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 4 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -70,6 +70,10 @@ int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
70/* Canonicalise 'path' - caller must free result */ 70/* Canonicalise 'path' - caller must free result */
71char *do_realpath(struct sftp_conn *, char *); 71char *do_realpath(struct sftp_conn *, char *);
72 72
73/* Get statistics for filesystem hosting file at "path" */
74struct statvfs;
75int do_statvfs(struct sftp_conn *, const char *, struct statvfs *, int);
76
73/* Rename 'oldpath' to 'newpath' */ 77/* Rename 'oldpath' to 'newpath' */
74int do_rename(struct sftp_conn *, char *, char *); 78int do_rename(struct sftp_conn *, char *, char *);
75 79
diff --git a/sftp-server.c b/sftp-server.c
index d9549f5bc..300fd5cfd 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-server.c,v 1.78 2008/02/27 20:21:15 djm Exp $ */ 1/* $OpenBSD: sftp-server.c,v 1.79 2008/04/18 12:32:11 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
4 * 4 *
@@ -23,6 +23,8 @@
23#ifdef HAVE_SYS_TIME_H 23#ifdef HAVE_SYS_TIME_H
24# include <sys/time.h> 24# include <sys/time.h>
25#endif 25#endif
26#include <sys/mount.h>
27#include <sys/statvfs.h>
26 28
27#include <dirent.h> 29#include <dirent.h>
28#include <errno.h> 30#include <errno.h>
@@ -475,6 +477,33 @@ send_attrib(u_int32_t id, const Attrib *a)
475 buffer_free(&msg); 477 buffer_free(&msg);
476} 478}
477 479
480static void
481send_statvfs(u_int32_t id, struct statvfs *st)
482{
483 Buffer msg;
484 u_int64_t flag;
485
486 flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
487 flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
488
489 buffer_init(&msg);
490 buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY);
491 buffer_put_int(&msg, id);
492 buffer_put_int(&msg, st->f_bsize);
493 buffer_put_int(&msg, st->f_frsize);
494 buffer_put_int64(&msg, st->f_blocks);
495 buffer_put_int64(&msg, st->f_bfree);
496 buffer_put_int64(&msg, st->f_bavail);
497 buffer_put_int64(&msg, st->f_files);
498 buffer_put_int64(&msg, st->f_ffree);
499 buffer_put_int64(&msg, st->f_favail);
500 buffer_put_int(&msg, st->f_fsid);
501 buffer_put_int(&msg, flag);
502 buffer_put_int(&msg, st->f_namemax);
503 send_msg(&msg);
504 buffer_free(&msg);
505}
506
478/* parse incoming */ 507/* parse incoming */
479 508
480static void 509static void
@@ -490,6 +519,10 @@ process_init(void)
490 /* POSIX rename extension */ 519 /* POSIX rename extension */
491 buffer_put_cstring(&msg, "posix-rename@openssh.com"); 520 buffer_put_cstring(&msg, "posix-rename@openssh.com");
492 buffer_put_cstring(&msg, "1"); /* version */ 521 buffer_put_cstring(&msg, "1"); /* version */
522 buffer_put_cstring(&msg, "statvfs@openssh.com");
523 buffer_put_cstring(&msg, "1"); /* version */
524 buffer_put_cstring(&msg, "fstatvfs@openssh.com");
525 buffer_put_cstring(&msg, "1"); /* version */
493 send_msg(&msg); 526 send_msg(&msg);
494 buffer_free(&msg); 527 buffer_free(&msg);
495} 528}
@@ -1100,6 +1133,42 @@ process_extended_posix_rename(u_int32_t id)
1100} 1133}
1101 1134
1102static void 1135static void
1136process_extended_statvfs(u_int32_t id)
1137{
1138 char *path;
1139 struct statvfs st;
1140
1141 path = get_string(NULL);
1142 debug3("request %u: statfs", id);
1143 logit("statfs \"%s\"", path);
1144
1145 if (statvfs(path, &st) != 0)
1146 send_status(id, errno_to_portable(errno));
1147 else
1148 send_statvfs(id, &st);
1149 xfree(path);
1150}
1151
1152static void
1153process_extended_fstatvfs(u_int32_t id)
1154{
1155 int handle, fd;
1156 struct statvfs st;
1157
1158 handle = get_handle();
1159 debug("request %u: fstatvfs \"%s\" (handle %u)",
1160 id, handle_to_name(handle), handle);
1161 if ((fd = handle_to_fd(handle)) < 0) {
1162 send_status(id, SSH2_FX_FAILURE);
1163 return;
1164 }
1165 if (fstatvfs(fd, &st) != 0)
1166 send_status(id, errno_to_portable(errno));
1167 else
1168 send_statvfs(id, &st);
1169}
1170
1171static void
1103process_extended(void) 1172process_extended(void)
1104{ 1173{
1105 u_int32_t id; 1174 u_int32_t id;
@@ -1109,6 +1178,10 @@ process_extended(void)
1109 request = get_string(NULL); 1178 request = get_string(NULL);
1110 if (strcmp(request, "posix-rename@openssh.com") == 0) 1179 if (strcmp(request, "posix-rename@openssh.com") == 0)
1111 process_extended_posix_rename(id); 1180 process_extended_posix_rename(id);
1181 else if (strcmp(request, "statvfs@openssh.com") == 0)
1182 process_extended_statvfs(id);
1183 else if (strcmp(request, "fstatvfs@openssh.com") == 0)
1184 process_extended_fstatvfs(id);
1112 else 1185 else
1113 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ 1186 send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
1114 xfree(request); 1187 xfree(request);
diff --git a/sftp.1 b/sftp.1
index 1f517a40a..f34f58856 100644
--- a/sftp.1
+++ b/sftp.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: sftp.1,v 1.64 2007/05/31 19:20:16 jmc Exp $ 1.\" $OpenBSD: sftp.1,v 1.65 2008/04/18 12:32:11 djm Exp $
2.\" 2.\"
3.\" Copyright (c) 2001 Damien Miller. All rights reserved. 3.\" Copyright (c) 2001 Damien Miller. All rights reserved.
4.\" 4.\"
@@ -22,7 +22,7 @@
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\" 24.\"
25.Dd $Mdocdate: May 31 2007 $ 25.Dd $Mdocdate: April 18 2008 $
26.Dt SFTP 1 26.Dt SFTP 1
27.Os 27.Os
28.Sh NAME 28.Sh NAME
@@ -112,7 +112,7 @@ will abort if any of the following
112commands fail: 112commands fail:
113.Ic get , put , rename , ln , 113.Ic get , put , rename , ln ,
114.Ic rm , mkdir , chdir , ls , 114.Ic rm , mkdir , chdir , ls ,
115.Ic lchdir , chmod , chown , chgrp , lpwd 115.Ic lchdir , chmod , chown , chgrp , lpwd, df,
116and 116and
117.Ic lmkdir . 117.Ic lmkdir .
118Termination on error can be suppressed on a command by command basis by 118Termination on error can be suppressed on a command by command basis by
@@ -272,6 +272,24 @@ may contain
272characters and may match multiple files. 272characters and may match multiple files.
273.Ar own 273.Ar own
274must be a numeric UID. 274must be a numeric UID.
275.It Xo Ic df
276.Op Fl hi
277.Op Ar path
278.Xc
279Display usage information for the filesystem holding the current directory
280(or
281.Ar path
282if specified).
283If the
284.Fl h
285flag is specified, the capacity information will be displayed using
286"human-readable" suffixes.
287The
288.Fl i
289flag requests display of inode information in addition to capacity information.
290This command is only supported on servers that implement the
291.Dq statvfs@openssh.com
292extension.
275.It Ic exit 293.It Ic exit
276Quit 294Quit
277.Nm sftp . 295.Nm sftp .
diff --git a/sftp.c b/sftp.c
index 861c3db05..0745baf08 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.99 2008/01/20 00:38:30 djm Exp $ */ 1/* $OpenBSD: sftp.c,v 1.100 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 *
@@ -25,6 +25,7 @@
25#include <sys/param.h> 25#include <sys/param.h>
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h> 27#include <sys/wait.h>
28#include <sys/statvfs.h>
28 29
29#include <ctype.h> 30#include <ctype.h>
30#include <errno.h> 31#include <errno.h>
@@ -42,6 +43,7 @@ typedef void EditLine;
42#include <stdio.h> 43#include <stdio.h>
43#include <string.h> 44#include <string.h>
44#include <unistd.h> 45#include <unistd.h>
46#include <util.h>
45#include <stdarg.h> 47#include <stdarg.h>
46 48
47#include "xmalloc.h" 49#include "xmalloc.h"
@@ -104,6 +106,7 @@ extern char *__progname;
104#define I_CHGRP 2 106#define I_CHGRP 2
105#define I_CHMOD 3 107#define I_CHMOD 3
106#define I_CHOWN 4 108#define I_CHOWN 4
109#define I_DF 24
107#define I_GET 5 110#define I_GET 5
108#define I_HELP 6 111#define I_HELP 6
109#define I_LCHDIR 7 112#define I_LCHDIR 7
@@ -136,6 +139,7 @@ static const struct CMD cmds[] = {
136 { "chgrp", I_CHGRP }, 139 { "chgrp", I_CHGRP },
137 { "chmod", I_CHMOD }, 140 { "chmod", I_CHMOD },
138 { "chown", I_CHOWN }, 141 { "chown", I_CHOWN },
142 { "df", I_DF },
139 { "dir", I_LS }, 143 { "dir", I_LS },
140 { "exit", I_QUIT }, 144 { "exit", I_QUIT },
141 { "get", I_GET }, 145 { "get", I_GET },
@@ -200,6 +204,8 @@ help(void)
200 printf("chgrp grp path Change group of file 'path' to 'grp'\n"); 204 printf("chgrp grp path Change group of file 'path' to 'grp'\n");
201 printf("chmod mode path Change permissions of file 'path' to 'mode'\n"); 205 printf("chmod mode path Change permissions of file 'path' to 'mode'\n");
202 printf("chown own path Change owner of file 'path' to 'own'\n"); 206 printf("chown own path Change owner of file 'path' to 'own'\n");
207 printf("df [path] Display statistics for current directory or\n");
208 printf(" filesystem containing 'path'\n");
203 printf("help Display this help text\n"); 209 printf("help Display this help text\n");
204 printf("get remote-path [local-path] Download file\n"); 210 printf("get remote-path [local-path] Download file\n");
205 printf("lls [ls-options [path]] Display local directory listing\n"); 211 printf("lls [ls-options [path]] Display local directory listing\n");
@@ -422,6 +428,33 @@ parse_ls_flags(char **argv, int argc, int *lflag)
422} 428}
423 429
424static int 430static int
431parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
432{
433 extern int optind, optreset, opterr;
434 int ch;
435
436 optind = optreset = 1;
437 opterr = 0;
438
439 *hflag = *iflag = 0;
440 while ((ch = getopt(argc, argv, "hi")) != -1) {
441 switch (ch) {
442 case 'h':
443 *hflag = 1;
444 break;
445 case 'i':
446 *iflag = 1;
447 break;
448 default:
449 error("%s: Invalid flag -%c", cmd, ch);
450 return -1;
451 }
452 }
453
454 return optind;
455}
456
457static int
425is_dir(char *path) 458is_dir(char *path)
426{ 459{
427 struct stat sb; 460 struct stat sb;
@@ -797,6 +830,56 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
797 return (0); 830 return (0);
798} 831}
799 832
833static int
834do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
835{
836 struct statvfs st;
837 char s_used[FMT_SCALED_STRSIZE];
838 char s_avail[FMT_SCALED_STRSIZE];
839 char s_root[FMT_SCALED_STRSIZE];
840 char s_total[FMT_SCALED_STRSIZE];
841
842 if (do_statvfs(conn, path, &st, 1) == -1)
843 return -1;
844 if (iflag) {
845 printf(" Inodes Used Avail "
846 "(root) %%Capacity\n");
847 printf("%11llu %11llu %11llu %11llu %3llu%%\n",
848 (unsigned long long)st.f_files,
849 (unsigned long long)(st.f_files - st.f_ffree),
850 (unsigned long long)st.f_favail,
851 (unsigned long long)st.f_ffree,
852 (unsigned long long)(100 * (st.f_files - st.f_ffree) /
853 st.f_files));
854 } else if (hflag) {
855 strlcpy(s_used, "error", sizeof(s_used));
856 strlcpy(s_avail, "error", sizeof(s_avail));
857 strlcpy(s_root, "error", sizeof(s_root));
858 strlcpy(s_total, "error", sizeof(s_total));
859 fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used);
860 fmt_scaled(st.f_bavail * st.f_frsize, s_avail);
861 fmt_scaled(st.f_bfree * st.f_frsize, s_root);
862 fmt_scaled(st.f_blocks * st.f_frsize, s_total);
863 printf(" Size Used Avail (root) %%Capacity\n");
864 printf("%7sB %7sB %7sB %7sB %3llu%%\n",
865 s_total, s_used, s_avail, s_root,
866 (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
867 st.f_blocks));
868 } else {
869 printf(" Size Used Avail "
870 "(root) %%Capacity\n");
871 printf("%12llu %12llu %12llu %12llu %3llu%%\n",
872 (unsigned long long)(st.f_frsize * st.f_blocks / 1024),
873 (unsigned long long)(st.f_frsize *
874 (st.f_blocks - st.f_bfree) / 1024),
875 (unsigned long long)(st.f_frsize * st.f_bavail / 1024),
876 (unsigned long long)(st.f_frsize * st.f_bfree / 1024),
877 (unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
878 st.f_blocks));
879 }
880 return 0;
881}
882
800/* 883/*
801 * Undo escaping of glob sequences in place. Used to undo extra escaping 884 * Undo escaping of glob sequences in place. Used to undo extra escaping
802 * applied in makeargv() when the string is destined for a function that 885 * applied in makeargv() when the string is destined for a function that
@@ -972,7 +1055,7 @@ makeargv(const char *arg, int *argcp)
972} 1055}
973 1056
974static int 1057static int
975parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, 1058parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, int *hflag,
976 unsigned long *n_arg, char **path1, char **path2) 1059 unsigned long *n_arg, char **path1, char **path2)
977{ 1060{
978 const char *cmd, *cp = *cpp; 1061 const char *cmd, *cp = *cpp;
@@ -1016,7 +1099,7 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
1016 } 1099 }
1017 1100
1018 /* Get arguments and parse flags */ 1101 /* Get arguments and parse flags */
1019 *lflag = *pflag = *n_arg = 0; 1102 *lflag = *pflag = *hflag = *n_arg = 0;
1020 *path1 = *path2 = NULL; 1103 *path1 = *path2 = NULL;
1021 optidx = 1; 1104 optidx = 1;
1022 switch (cmdnum) { 1105 switch (cmdnum) {
@@ -1068,6 +1151,18 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
1068 if (cmdnum != I_RM) 1151 if (cmdnum != I_RM)
1069 undo_glob_escape(*path1); 1152 undo_glob_escape(*path1);
1070 break; 1153 break;
1154 case I_DF:
1155 if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
1156 iflag)) == -1)
1157 return -1;
1158 /* Default to current directory if no path specified */
1159 if (argc - optidx < 1)
1160 *path1 = NULL;
1161 else {
1162 *path1 = xstrdup(argv[optidx]);
1163 undo_glob_escape(*path1);
1164 }
1165 break;
1071 case I_LS: 1166 case I_LS:
1072 if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) 1167 if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
1073 return(-1); 1168 return(-1);
@@ -1130,7 +1225,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1130 int err_abort) 1225 int err_abort)
1131{ 1226{
1132 char *path1, *path2, *tmp; 1227 char *path1, *path2, *tmp;
1133 int pflag, lflag, iflag, cmdnum, i; 1228 int pflag, lflag, iflag, hflag, cmdnum, i;
1134 unsigned long n_arg; 1229 unsigned long n_arg;
1135 Attrib a, *aa; 1230 Attrib a, *aa;
1136 char path_buf[MAXPATHLEN]; 1231 char path_buf[MAXPATHLEN];
@@ -1138,7 +1233,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1138 glob_t g; 1233 glob_t g;
1139 1234
1140 path1 = path2 = NULL; 1235 path1 = path2 = NULL;
1141 cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg, 1236 cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &hflag, &n_arg,
1142 &path1, &path2); 1237 &path1, &path2);
1143 1238
1144 if (iflag != 0) 1239 if (iflag != 0)
@@ -1232,6 +1327,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1232 path1 = make_absolute(path1, *pwd); 1327 path1 = make_absolute(path1, *pwd);
1233 err = do_globbed_ls(conn, path1, tmp, lflag); 1328 err = do_globbed_ls(conn, path1, tmp, lflag);
1234 break; 1329 break;
1330 case I_DF:
1331 /* Default to current directory if no path specified */
1332 if (path1 == NULL)
1333 path1 = xstrdup(*pwd);
1334 path1 = make_absolute(path1, *pwd);
1335 err = do_df(conn, path1, hflag, iflag);
1336 break;
1235 case I_LCHDIR: 1337 case I_LCHDIR:
1236 if (chdir(path1) == -1) { 1338 if (chdir(path1) == -1) {
1237 error("Couldn't change local directory to " 1339 error("Couldn't change local directory to "
diff --git a/sftp.h b/sftp.h
index 0835da6ed..b101b95a0 100644
--- a/sftp.h
+++ b/sftp.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.h,v 1.7 2008/02/08 23:24:07 djm Exp $ */ 1/* $OpenBSD: sftp.h,v 1.8 2008/04/18 12:32:11 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -79,6 +79,10 @@
79#define SSH2_FXF_TRUNC 0x00000010 79#define SSH2_FXF_TRUNC 0x00000010
80#define SSH2_FXF_EXCL 0x00000020 80#define SSH2_FXF_EXCL 0x00000020
81 81
82/* statvfs@openssh.com f_flag flags */
83#define SSH2_FXE_STATVFS_ST_RDONLY 0x00000001
84#define SSH2_FXE_STATVFS_ST_NOSUID 0x00000002
85
82/* status messages */ 86/* status messages */
83#define SSH2_FX_OK 0 87#define SSH2_FX_OK 0
84#define SSH2_FX_EOF 1 88#define SSH2_FX_EOF 1