diff options
Diffstat (limited to 'sftp.c')
-rw-r--r-- | sftp.c | 112 |
1 files changed, 107 insertions, 5 deletions
@@ -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 | ||
424 | static int | 430 | static int |
431 | parse_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 | |||
457 | static int | ||
425 | is_dir(char *path) | 458 | is_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 | ||
833 | static int | ||
834 | do_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 | ||
974 | static int | 1057 | static int |
975 | parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, | 1058 | parse_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 " |