[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@
This commit is contained in:
Damien Miller 2008-05-19 14:53:33 +10:00
Родитель 354c48c641
Коммит d671e5a978
7 изменённых файлов: 339 добавлений и 15 удалений

Просмотреть файл

@ -21,6 +21,15 @@
Use arc4random_uniform() when the desired random number upper bound Use arc4random_uniform() when the desired random number upper bound
is not a power of two is not a power of two
ok deraadt@ millert@ ok deraadt@ millert@
- 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@
20080403 20080403
- (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile- - (djm) [openbsd-compat/bsd-poll.c] Include stdlib.h to avoid compile-
@ -3881,4 +3890,4 @@
OpenServer 6 and add osr5bigcrypt support so when someone migrates OpenServer 6 and add osr5bigcrypt support so when someone migrates
passwords between UnixWare and OpenServer they will still work. OK dtucker@ passwords between UnixWare and OpenServer they will still work. OK dtucker@
$Id: ChangeLog,v 1.4910 2008/05/19 04:50:00 djm Exp $ $Id: ChangeLog,v 1.4911 2008/05/19 04:53:33 djm Exp $

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.c,v 1.81 2008/03/23 12:54:01 djm Exp $ */ /* $OpenBSD: sftp-client.c,v 1.82 2008/04/18 12:32:11 djm Exp $ */
/* /*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
* *
@ -24,6 +24,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
#include <sys/statvfs.h>
#include "openbsd-compat/sys-queue.h" #include "openbsd-compat/sys-queue.h"
#ifdef HAVE_SYS_STAT_H #ifdef HAVE_SYS_STAT_H
# include <sys/stat.h> # include <sys/stat.h>
@ -65,7 +66,9 @@ struct sftp_conn {
u_int num_requests; u_int num_requests;
u_int version; u_int version;
u_int msg_id; u_int msg_id;
#define SFTP_EXT_POSIX_RENAME 1 #define SFTP_EXT_POSIX_RENAME 0x00000001
#define SFTP_EXT_STATVFS 0x00000002
#define SFTP_EXT_FSTATVFS 0x00000004
u_int exts; u_int exts;
}; };
@ -238,6 +241,56 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
return(a); return(a);
} }
static int
get_decode_statvfs(int fd, struct statvfs *st, u_int expected_id, int quiet)
{
Buffer msg;
u_int type, id, flag;
buffer_init(&msg);
get_msg(fd, &msg);
type = buffer_get_char(&msg);
id = buffer_get_int(&msg);
debug3("Received statvfs reply T:%u I:%u", type, id);
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
int status = buffer_get_int(&msg);
if (quiet)
debug("Couldn't statvfs: %s", fx2txt(status));
else
error("Couldn't statvfs: %s", fx2txt(status));
buffer_free(&msg);
return -1;
} else if (type != SSH2_FXP_EXTENDED_REPLY) {
fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
SSH2_FXP_EXTENDED_REPLY, type);
}
bzero(st, sizeof(*st));
st->f_bsize = buffer_get_int(&msg);
st->f_frsize = buffer_get_int(&msg);
st->f_blocks = buffer_get_int64(&msg);
st->f_bfree = buffer_get_int64(&msg);
st->f_bavail = buffer_get_int64(&msg);
st->f_files = buffer_get_int64(&msg);
st->f_ffree = buffer_get_int64(&msg);
st->f_favail = buffer_get_int64(&msg);
st->f_fsid = buffer_get_int(&msg);
flag = buffer_get_int(&msg);
st->f_namemax = buffer_get_int(&msg);
st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
buffer_free(&msg);
return 0;
}
struct sftp_conn * struct sftp_conn *
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
{ {
@ -272,8 +325,15 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
char *value = buffer_get_string(&msg, NULL); char *value = buffer_get_string(&msg, NULL);
debug2("Init extension: \"%s\"", name); debug2("Init extension: \"%s\"", name);
if (strcmp(name, "posix-rename@openssh.com") == 0) if (strcmp(name, "posix-rename@openssh.com") == 0 &&
strcmp(value, "1") == 0)
exts |= SFTP_EXT_POSIX_RENAME; exts |= SFTP_EXT_POSIX_RENAME;
if (strcmp(name, "statvfs@openssh.com") == 0 &&
strcmp(value, "1") == 0)
exts |= SFTP_EXT_STATVFS;
if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
strcmp(value, "1") == 0)
exts |= SFTP_EXT_FSTATVFS;
xfree(name); xfree(name);
xfree(value); xfree(value);
} }
@ -749,6 +809,60 @@ do_readlink(struct sftp_conn *conn, char *path)
} }
#endif #endif
int
do_statvfs(struct sftp_conn *conn, const char *path, struct statvfs *st,
int quiet)
{
Buffer msg;
u_int id;
if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
error("Server does not support statvfs@openssh.com extension");
return -1;
}
id = conn->msg_id++;
buffer_init(&msg);
buffer_clear(&msg);
buffer_put_char(&msg, SSH2_FXP_EXTENDED);
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, "statvfs@openssh.com");
buffer_put_cstring(&msg, path);
send_msg(conn->fd_out, &msg);
buffer_free(&msg);
return get_decode_statvfs(conn->fd_in, st, id, quiet);
}
#ifdef notyet
int
do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
struct statvfs *st, int quiet)
{
Buffer msg;
u_int id;
if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
error("Server does not support fstatvfs@openssh.com extension");
return -1;
}
id = conn->msg_id++;
buffer_init(&msg);
buffer_clear(&msg);
buffer_put_char(&msg, SSH2_FXP_EXTENDED);
buffer_put_int(&msg, id);
buffer_put_cstring(&msg, "fstatvfs@openssh.com");
buffer_put_string(&msg, handle, handle_len);
send_msg(conn->fd_out, &msg);
buffer_free(&msg);
return get_decode_statvfs(conn->fd_in, st, id, quiet);
}
#endif
static void static void
send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
char *handle, u_int handle_len) char *handle, u_int handle_len)

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.h,v 1.15 2008/01/11 07:22:28 chl Exp $ */ /* $OpenBSD: sftp-client.h,v 1.16 2008/04/18 12:32:11 djm Exp $ */
/* /*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@ -70,6 +70,10 @@ int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
/* Canonicalise 'path' - caller must free result */ /* Canonicalise 'path' - caller must free result */
char *do_realpath(struct sftp_conn *, char *); char *do_realpath(struct sftp_conn *, char *);
/* Get statistics for filesystem hosting file at "path" */
struct statvfs;
int do_statvfs(struct sftp_conn *, const char *, struct statvfs *, int);
/* Rename 'oldpath' to 'newpath' */ /* Rename 'oldpath' to 'newpath' */
int do_rename(struct sftp_conn *, char *, char *); int do_rename(struct sftp_conn *, char *, char *);

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-server.c,v 1.78 2008/02/27 20:21:15 djm Exp $ */ /* $OpenBSD: sftp-server.c,v 1.79 2008/04/18 12:32:11 djm Exp $ */
/* /*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
* *
@ -23,6 +23,8 @@
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
#endif #endif
#include <sys/mount.h>
#include <sys/statvfs.h>
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
@ -475,6 +477,33 @@ send_attrib(u_int32_t id, const Attrib *a)
buffer_free(&msg); buffer_free(&msg);
} }
static void
send_statvfs(u_int32_t id, struct statvfs *st)
{
Buffer msg;
u_int64_t flag;
flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
buffer_init(&msg);
buffer_put_char(&msg, SSH2_FXP_EXTENDED_REPLY);
buffer_put_int(&msg, id);
buffer_put_int(&msg, st->f_bsize);
buffer_put_int(&msg, st->f_frsize);
buffer_put_int64(&msg, st->f_blocks);
buffer_put_int64(&msg, st->f_bfree);
buffer_put_int64(&msg, st->f_bavail);
buffer_put_int64(&msg, st->f_files);
buffer_put_int64(&msg, st->f_ffree);
buffer_put_int64(&msg, st->f_favail);
buffer_put_int(&msg, st->f_fsid);
buffer_put_int(&msg, flag);
buffer_put_int(&msg, st->f_namemax);
send_msg(&msg);
buffer_free(&msg);
}
/* parse incoming */ /* parse incoming */
static void static void
@ -490,6 +519,10 @@ process_init(void)
/* POSIX rename extension */ /* POSIX rename extension */
buffer_put_cstring(&msg, "posix-rename@openssh.com"); buffer_put_cstring(&msg, "posix-rename@openssh.com");
buffer_put_cstring(&msg, "1"); /* version */ buffer_put_cstring(&msg, "1"); /* version */
buffer_put_cstring(&msg, "statvfs@openssh.com");
buffer_put_cstring(&msg, "1"); /* version */
buffer_put_cstring(&msg, "fstatvfs@openssh.com");
buffer_put_cstring(&msg, "1"); /* version */
send_msg(&msg); send_msg(&msg);
buffer_free(&msg); buffer_free(&msg);
} }
@ -1099,6 +1132,42 @@ process_extended_posix_rename(u_int32_t id)
xfree(newpath); xfree(newpath);
} }
static void
process_extended_statvfs(u_int32_t id)
{
char *path;
struct statvfs st;
path = get_string(NULL);
debug3("request %u: statfs", id);
logit("statfs \"%s\"", path);
if (statvfs(path, &st) != 0)
send_status(id, errno_to_portable(errno));
else
send_statvfs(id, &st);
xfree(path);
}
static void
process_extended_fstatvfs(u_int32_t id)
{
int handle, fd;
struct statvfs st;
handle = get_handle();
debug("request %u: fstatvfs \"%s\" (handle %u)",
id, handle_to_name(handle), handle);
if ((fd = handle_to_fd(handle)) < 0) {
send_status(id, SSH2_FX_FAILURE);
return;
}
if (fstatvfs(fd, &st) != 0)
send_status(id, errno_to_portable(errno));
else
send_statvfs(id, &st);
}
static void static void
process_extended(void) process_extended(void)
{ {
@ -1109,6 +1178,10 @@ process_extended(void)
request = get_string(NULL); request = get_string(NULL);
if (strcmp(request, "posix-rename@openssh.com") == 0) if (strcmp(request, "posix-rename@openssh.com") == 0)
process_extended_posix_rename(id); process_extended_posix_rename(id);
else if (strcmp(request, "statvfs@openssh.com") == 0)
process_extended_statvfs(id);
else if (strcmp(request, "fstatvfs@openssh.com") == 0)
process_extended_fstatvfs(id);
else else
send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */ send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
xfree(request); xfree(request);

24
sftp.1
Просмотреть файл

@ -1,4 +1,4 @@
.\" $OpenBSD: sftp.1,v 1.64 2007/05/31 19:20:16 jmc Exp $ .\" $OpenBSD: sftp.1,v 1.65 2008/04/18 12:32:11 djm Exp $
.\" .\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\" .\"
@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: May 31 2007 $ .Dd $Mdocdate: April 18 2008 $
.Dt SFTP 1 .Dt SFTP 1
.Os .Os
.Sh NAME .Sh NAME
@ -112,7 +112,7 @@ will abort if any of the following
commands fail: commands fail:
.Ic get , put , rename , ln , .Ic get , put , rename , ln ,
.Ic rm , mkdir , chdir , ls , .Ic rm , mkdir , chdir , ls ,
.Ic lchdir , chmod , chown , chgrp , lpwd .Ic lchdir , chmod , chown , chgrp , lpwd, df,
and and
.Ic lmkdir . .Ic lmkdir .
Termination on error can be suppressed on a command by command basis by Termination on error can be suppressed on a command by command basis by
@ -272,6 +272,24 @@ may contain
characters and may match multiple files. characters and may match multiple files.
.Ar own .Ar own
must be a numeric UID. must be a numeric UID.
.It Xo Ic df
.Op Fl hi
.Op Ar path
.Xc
Display usage information for the filesystem holding the current directory
(or
.Ar path
if specified).
If the
.Fl h
flag is specified, the capacity information will be displayed using
"human-readable" suffixes.
The
.Fl i
flag requests display of inode information in addition to capacity information.
This command is only supported on servers that implement the
.Dq statvfs@openssh.com
extension.
.It Ic exit .It Ic exit
Quit Quit
.Nm sftp . .Nm sftp .

112
sftp.c
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.c,v 1.99 2008/01/20 00:38:30 djm Exp $ */ /* $OpenBSD: sftp.c,v 1.100 2008/04/18 12:32:11 djm Exp $ */
/* /*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
* *
@ -25,6 +25,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/statvfs.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
@ -42,6 +43,7 @@ typedef void EditLine;
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <util.h>
#include <stdarg.h> #include <stdarg.h>
#include "xmalloc.h" #include "xmalloc.h"
@ -104,6 +106,7 @@ extern char *__progname;
#define I_CHGRP 2 #define I_CHGRP 2
#define I_CHMOD 3 #define I_CHMOD 3
#define I_CHOWN 4 #define I_CHOWN 4
#define I_DF 24
#define I_GET 5 #define I_GET 5
#define I_HELP 6 #define I_HELP 6
#define I_LCHDIR 7 #define I_LCHDIR 7
@ -136,6 +139,7 @@ static const struct CMD cmds[] = {
{ "chgrp", I_CHGRP }, { "chgrp", I_CHGRP },
{ "chmod", I_CHMOD }, { "chmod", I_CHMOD },
{ "chown", I_CHOWN }, { "chown", I_CHOWN },
{ "df", I_DF },
{ "dir", I_LS }, { "dir", I_LS },
{ "exit", I_QUIT }, { "exit", I_QUIT },
{ "get", I_GET }, { "get", I_GET },
@ -200,6 +204,8 @@ help(void)
printf("chgrp grp path Change group of file 'path' to 'grp'\n"); printf("chgrp grp path Change group of file 'path' to 'grp'\n");
printf("chmod mode path Change permissions of file 'path' to 'mode'\n"); printf("chmod mode path Change permissions of file 'path' to 'mode'\n");
printf("chown own path Change owner of file 'path' to 'own'\n"); printf("chown own path Change owner of file 'path' to 'own'\n");
printf("df [path] Display statistics for current directory or\n");
printf(" filesystem containing 'path'\n");
printf("help Display this help text\n"); printf("help Display this help text\n");
printf("get remote-path [local-path] Download file\n"); printf("get remote-path [local-path] Download file\n");
printf("lls [ls-options [path]] Display local directory listing\n"); printf("lls [ls-options [path]] Display local directory listing\n");
@ -421,6 +427,33 @@ parse_ls_flags(char **argv, int argc, int *lflag)
return optind; return optind;
} }
static int
parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
{
extern int optind, optreset, opterr;
int ch;
optind = optreset = 1;
opterr = 0;
*hflag = *iflag = 0;
while ((ch = getopt(argc, argv, "hi")) != -1) {
switch (ch) {
case 'h':
*hflag = 1;
break;
case 'i':
*iflag = 1;
break;
default:
error("%s: Invalid flag -%c", cmd, ch);
return -1;
}
}
return optind;
}
static int static int
is_dir(char *path) is_dir(char *path)
{ {
@ -797,6 +830,56 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
return (0); return (0);
} }
static int
do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
{
struct statvfs st;
char s_used[FMT_SCALED_STRSIZE];
char s_avail[FMT_SCALED_STRSIZE];
char s_root[FMT_SCALED_STRSIZE];
char s_total[FMT_SCALED_STRSIZE];
if (do_statvfs(conn, path, &st, 1) == -1)
return -1;
if (iflag) {
printf(" Inodes Used Avail "
"(root) %%Capacity\n");
printf("%11llu %11llu %11llu %11llu %3llu%%\n",
(unsigned long long)st.f_files,
(unsigned long long)(st.f_files - st.f_ffree),
(unsigned long long)st.f_favail,
(unsigned long long)st.f_ffree,
(unsigned long long)(100 * (st.f_files - st.f_ffree) /
st.f_files));
} else if (hflag) {
strlcpy(s_used, "error", sizeof(s_used));
strlcpy(s_avail, "error", sizeof(s_avail));
strlcpy(s_root, "error", sizeof(s_root));
strlcpy(s_total, "error", sizeof(s_total));
fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used);
fmt_scaled(st.f_bavail * st.f_frsize, s_avail);
fmt_scaled(st.f_bfree * st.f_frsize, s_root);
fmt_scaled(st.f_blocks * st.f_frsize, s_total);
printf(" Size Used Avail (root) %%Capacity\n");
printf("%7sB %7sB %7sB %7sB %3llu%%\n",
s_total, s_used, s_avail, s_root,
(unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
st.f_blocks));
} else {
printf(" Size Used Avail "
"(root) %%Capacity\n");
printf("%12llu %12llu %12llu %12llu %3llu%%\n",
(unsigned long long)(st.f_frsize * st.f_blocks / 1024),
(unsigned long long)(st.f_frsize *
(st.f_blocks - st.f_bfree) / 1024),
(unsigned long long)(st.f_frsize * st.f_bavail / 1024),
(unsigned long long)(st.f_frsize * st.f_bfree / 1024),
(unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
st.f_blocks));
}
return 0;
}
/* /*
* Undo escaping of glob sequences in place. Used to undo extra escaping * Undo escaping of glob sequences in place. Used to undo extra escaping
* applied in makeargv() when the string is destined for a function that * applied in makeargv() when the string is destined for a function that
@ -972,7 +1055,7 @@ makeargv(const char *arg, int *argcp)
} }
static int static int
parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, parse_args(const char **cpp, int *pflag, int *lflag, int *iflag, int *hflag,
unsigned long *n_arg, char **path1, char **path2) unsigned long *n_arg, char **path1, char **path2)
{ {
const char *cmd, *cp = *cpp; const char *cmd, *cp = *cpp;
@ -1016,7 +1099,7 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
} }
/* Get arguments and parse flags */ /* Get arguments and parse flags */
*lflag = *pflag = *n_arg = 0; *lflag = *pflag = *hflag = *n_arg = 0;
*path1 = *path2 = NULL; *path1 = *path2 = NULL;
optidx = 1; optidx = 1;
switch (cmdnum) { switch (cmdnum) {
@ -1068,6 +1151,18 @@ parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
if (cmdnum != I_RM) if (cmdnum != I_RM)
undo_glob_escape(*path1); undo_glob_escape(*path1);
break; break;
case I_DF:
if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
iflag)) == -1)
return -1;
/* Default to current directory if no path specified */
if (argc - optidx < 1)
*path1 = NULL;
else {
*path1 = xstrdup(argv[optidx]);
undo_glob_escape(*path1);
}
break;
case I_LS: case I_LS:
if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1) if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
return(-1); return(-1);
@ -1130,7 +1225,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort) int err_abort)
{ {
char *path1, *path2, *tmp; char *path1, *path2, *tmp;
int pflag, lflag, iflag, cmdnum, i; int pflag, lflag, iflag, hflag, cmdnum, i;
unsigned long n_arg; unsigned long n_arg;
Attrib a, *aa; Attrib a, *aa;
char path_buf[MAXPATHLEN]; char path_buf[MAXPATHLEN];
@ -1138,7 +1233,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g; glob_t g;
path1 = path2 = NULL; path1 = path2 = NULL;
cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg, cmdnum = parse_args(&cmd, &pflag, &lflag, &iflag, &hflag, &n_arg,
&path1, &path2); &path1, &path2);
if (iflag != 0) if (iflag != 0)
@ -1232,6 +1327,13 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
path1 = make_absolute(path1, *pwd); path1 = make_absolute(path1, *pwd);
err = do_globbed_ls(conn, path1, tmp, lflag); err = do_globbed_ls(conn, path1, tmp, lflag);
break; break;
case I_DF:
/* Default to current directory if no path specified */
if (path1 == NULL)
path1 = xstrdup(*pwd);
path1 = make_absolute(path1, *pwd);
err = do_df(conn, path1, hflag, iflag);
break;
case I_LCHDIR: case I_LCHDIR:
if (chdir(path1) == -1) { if (chdir(path1) == -1) {
error("Couldn't change local directory to " error("Couldn't change local directory to "

6
sftp.h
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: sftp.h,v 1.7 2008/02/08 23:24:07 djm Exp $ */ /* $OpenBSD: sftp.h,v 1.8 2008/04/18 12:32:11 djm Exp $ */
/* /*
* Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -79,6 +79,10 @@
#define SSH2_FXF_TRUNC 0x00000010 #define SSH2_FXF_TRUNC 0x00000010
#define SSH2_FXF_EXCL 0x00000020 #define SSH2_FXF_EXCL 0x00000020
/* statvfs@openssh.com f_flag flags */
#define SSH2_FXE_STATVFS_ST_RDONLY 0x00000001
#define SSH2_FXE_STATVFS_ST_NOSUID 0x00000002
/* status messages */ /* status messages */
#define SSH2_FX_OK 0 #define SSH2_FX_OK 0
#define SSH2_FX_EOF 1 #define SSH2_FX_EOF 1