summaryrefslogtreecommitdiff
path: root/sftp.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.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.c')
-rw-r--r--sftp.c112
1 files changed, 107 insertions, 5 deletions
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 "