зеркало из https://github.com/Azure/sonic-openssh.git
- djm@cvs.openbsd.org 2002/09/11 22:41:50
[sftp.1 sftp-client.c sftp-client.h sftp-common.c sftp-common.h] [sftp-glob.c sftp-glob.h sftp-int.c sftp-server.c] support for short/long listings and globbing in "ls"; ok markus@
This commit is contained in:
Родитель
789e95dbe9
Коммит
e1a4981707
|
@ -22,6 +22,10 @@
|
|||
[authfd.c authfd.h ssh.c]
|
||||
don't connect to agent to test for presence if we've previously
|
||||
connected; ok markus@
|
||||
- djm@cvs.openbsd.org 2002/09/11 22:41:50
|
||||
[sftp.1 sftp-client.c sftp-client.h sftp-common.c sftp-common.h]
|
||||
[sftp-glob.c sftp-glob.h sftp-int.c sftp-server.c]
|
||||
support for short/long listings and globbing in "ls"; ok markus@
|
||||
|
||||
20020911
|
||||
- (djm) Sync openbsd-compat with OpenBSD -current
|
||||
|
@ -1642,4 +1646,4 @@
|
|||
- (stevesk) entropy.c: typo in debug message
|
||||
- (djm) ssh-keygen -i needs seeded RNG; report from markus@
|
||||
|
||||
$Id: ChangeLog,v 1.2457 2002/09/11 23:52:46 djm Exp $
|
||||
$Id: ChangeLog,v 1.2458 2002/09/11 23:54:25 djm Exp $
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/* XXX: copy between two remote sites */
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-client.c,v 1.34 2002/06/27 10:35:47 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sftp-client.c,v 1.35 2002/09/11 22:41:49 djm Exp $");
|
||||
|
||||
#include "openbsd-compat/fake-queue.h"
|
||||
|
||||
|
@ -414,12 +414,6 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
|
|||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
do_ls(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
return(do_lsreaddir(conn, path, 1, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sftp-client.h,v 1.10 2002/06/23 09:30:14 deraadt Exp $ */
|
||||
/* $OpenBSD: sftp-client.h,v 1.11 2002/09/11 22:41:50 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
|
@ -48,9 +48,6 @@ u_int sftp_proto_version(struct sftp_conn *);
|
|||
/* Close file referred to by 'handle' */
|
||||
int do_close(struct sftp_conn *, char *, u_int);
|
||||
|
||||
/* List contents of directory 'path' to stdout */
|
||||
int do_ls(struct sftp_conn *, char *);
|
||||
|
||||
/* Read contents of 'path' to NULL-terminated array 'dir' */
|
||||
int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-common.c,v 1.6 2002/06/23 09:30:14 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sftp-common.c,v 1.7 2002/09/11 22:41:50 djm Exp $");
|
||||
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
@ -65,6 +65,26 @@ stat_to_attrib(struct stat *st, Attrib *a)
|
|||
a->mtime = st->st_mtime;
|
||||
}
|
||||
|
||||
/* Convert from filexfer attribs to struct stat */
|
||||
void
|
||||
attrib_to_stat(Attrib *a, struct stat *st)
|
||||
{
|
||||
memset(st, 0, sizeof(*st));
|
||||
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
|
||||
st->st_size = a->size;
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
|
||||
st->st_uid = a->uid;
|
||||
st->st_gid = a->gid;
|
||||
}
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
||||
st->st_mode = a->perm;
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
|
||||
st->st_atime = a->atime;
|
||||
st->st_mtime = a->mtime;
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode attributes in buffer */
|
||||
Attrib *
|
||||
decode_attrib(Buffer *b)
|
||||
|
@ -149,3 +169,45 @@ fx2txt(int status)
|
|||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
|
||||
*/
|
||||
char *
|
||||
ls_file(char *name, struct stat *st, int remote)
|
||||
{
|
||||
int ulen, glen, sz = 0;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
struct tm *ltime = localtime(&st->st_mtime);
|
||||
char *user, *group;
|
||||
char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
|
||||
|
||||
strmode(st->st_mode, mode);
|
||||
if (!remote && (pw = getpwuid(st->st_uid)) != NULL) {
|
||||
user = pw->pw_name;
|
||||
} else {
|
||||
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
|
||||
user = ubuf;
|
||||
}
|
||||
if (!remote && (gr = getgrgid(st->st_gid)) != NULL) {
|
||||
group = gr->gr_name;
|
||||
} else {
|
||||
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
|
||||
group = gbuf;
|
||||
}
|
||||
if (ltime != NULL) {
|
||||
if (time(NULL) - st->st_mtime < (365*24*60*60)/2)
|
||||
sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
|
||||
else
|
||||
sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime);
|
||||
}
|
||||
if (sz == 0)
|
||||
tbuf[0] = '\0';
|
||||
ulen = MAX(strlen(user), 8);
|
||||
glen = MAX(strlen(group), 8);
|
||||
snprintf(buf, sizeof buf, "%s %3d %-*s %-*s %8llu %s %s", mode,
|
||||
st->st_nlink, ulen, user, glen, group,
|
||||
(u_int64_t)st->st_size, tbuf, name);
|
||||
return xstrdup(buf);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sftp-common.h,v 1.3 2001/06/26 17:27:24 markus Exp $ */
|
||||
/* $OpenBSD: sftp-common.h,v 1.4 2002/09/11 22:41:50 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
|
@ -40,7 +40,9 @@ struct Attrib {
|
|||
|
||||
void attrib_clear(Attrib *);
|
||||
void stat_to_attrib(struct stat *, Attrib *);
|
||||
void attrib_to_stat(Attrib *, struct stat *);
|
||||
Attrib *decode_attrib(Buffer *);
|
||||
void encode_attrib(Buffer *, Attrib *);
|
||||
char *ls_file(char *, struct stat *, int);
|
||||
|
||||
const char *fx2txt(int);
|
||||
|
|
21
sftp-glob.c
21
sftp-glob.c
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-glob.c,v 1.12 2002/07/04 04:15:33 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sftp-glob.c,v 1.13 2002/09/11 22:41:50 djm Exp $");
|
||||
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
@ -107,25 +107,6 @@ fudge_closedir(struct SFTP_OPENDIR *od)
|
|||
xfree(od);
|
||||
}
|
||||
|
||||
static void
|
||||
attrib_to_stat(Attrib *a, struct stat *st)
|
||||
{
|
||||
memset(st, 0, sizeof(*st));
|
||||
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
|
||||
st->st_size = a->size;
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
|
||||
st->st_uid = a->uid;
|
||||
st->st_gid = a->gid;
|
||||
}
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
|
||||
st->st_mode = a->perm;
|
||||
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
|
||||
st->st_atime = a->atime;
|
||||
st->st_mtime = a->mtime;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fudge_lstat(const char *path, struct stat *st)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: sftp-glob.h,v 1.7 2002/03/19 10:49:35 markus Exp $ */
|
||||
/* $OpenBSD: sftp-glob.h,v 1.8 2002/09/11 22:41:50 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
|
@ -31,8 +31,7 @@
|
|||
|
||||
#include "sftp-client.h"
|
||||
|
||||
int
|
||||
remote_glob(struct sftp_conn *, const char *, int,
|
||||
int remote_glob(struct sftp_conn *, const char *, int,
|
||||
int (*)(const char *, int), glob_t *);
|
||||
|
||||
#endif
|
||||
|
|
204
sftp-int.c
204
sftp-int.c
|
@ -22,11 +22,10 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* XXX: globbed ls */
|
||||
/* XXX: recursive operations */
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-int.c,v 1.47 2002/06/23 09:30:14 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sftp-int.c,v 1.48 2002/09/11 22:41:50 djm Exp $");
|
||||
|
||||
#include "buffer.h"
|
||||
#include "xmalloc.h"
|
||||
|
@ -201,6 +200,26 @@ local_do_ls(const char *args)
|
|||
}
|
||||
}
|
||||
|
||||
/* Strip one path (usually the pwd) from the start of another */
|
||||
static char *
|
||||
path_strip(char *path, char *strip)
|
||||
{
|
||||
size_t len;
|
||||
char *ret;
|
||||
|
||||
if (strip == NULL)
|
||||
return (xstrdup(path));
|
||||
|
||||
len = strlen(strip);
|
||||
if (strip != NULL && strncmp(path, strip, len) == 0) {
|
||||
if (strip[len - 1] != '/' && path[len] == '/')
|
||||
len++;
|
||||
return (xstrdup(path + len));
|
||||
}
|
||||
|
||||
return (xstrdup(path));
|
||||
}
|
||||
|
||||
static char *
|
||||
path_append(char *p1, char *p2)
|
||||
{
|
||||
|
@ -209,7 +228,7 @@ path_append(char *p1, char *p2)
|
|||
|
||||
ret = xmalloc(len);
|
||||
strlcpy(ret, p1, len);
|
||||
if (strcmp(p1, "/") != 0)
|
||||
if (p1[strlen(p1) - 1] != '/')
|
||||
strlcat(ret, "/", len);
|
||||
strlcat(ret, p2, len);
|
||||
|
||||
|
@ -273,6 +292,29 @@ parse_getput_flags(const char **cpp, int *pflag)
|
|||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_ls_flags(const char **cpp, int *lflag)
|
||||
{
|
||||
const char *cp = *cpp;
|
||||
|
||||
/* Check for flags */
|
||||
if (cp++[0] == '-') {
|
||||
for(; strchr(WHITESPACE, *cp) == NULL; cp++) {
|
||||
switch (*cp) {
|
||||
case 'l':
|
||||
*lflag = 1;
|
||||
break;
|
||||
default:
|
||||
error("Invalid flag -%c", *cp);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
*cpp = cp + strspn(cp, WHITESPACE);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
get_pathname(const char **cpp, char **path)
|
||||
{
|
||||
|
@ -504,8 +546,129 @@ out:
|
|||
}
|
||||
|
||||
static int
|
||||
parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
||||
char **path1, char **path2)
|
||||
sdirent_comp(const void *aa, const void *bb)
|
||||
{
|
||||
SFTP_DIRENT *a = *(SFTP_DIRENT **)aa;
|
||||
SFTP_DIRENT *b = *(SFTP_DIRENT **)bb;
|
||||
|
||||
return (strcmp(a->filename, b->filename));
|
||||
}
|
||||
|
||||
/* sftp ls.1 replacement for directories */
|
||||
static int
|
||||
do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
|
||||
{
|
||||
int n;
|
||||
SFTP_DIRENT **d;
|
||||
|
||||
if ((n = do_readdir(conn, path, &d)) != 0)
|
||||
return (n);
|
||||
|
||||
/* Count entries for sort */
|
||||
for (n = 0; d[n] != NULL; n++)
|
||||
;
|
||||
|
||||
qsort(d, n, sizeof(*d), sdirent_comp);
|
||||
|
||||
for (n = 0; d[n] != NULL; n++) {
|
||||
char *tmp, *fname;
|
||||
|
||||
tmp = path_append(path, d[n]->filename);
|
||||
fname = path_strip(tmp, strip_path);
|
||||
xfree(tmp);
|
||||
|
||||
if (lflag) {
|
||||
char *lname;
|
||||
struct stat sb;
|
||||
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
attrib_to_stat(&d[n]->a, &sb);
|
||||
lname = ls_file(fname, &sb, 1);
|
||||
printf("%s\n", lname);
|
||||
xfree(lname);
|
||||
} else {
|
||||
/* XXX - multicolumn display would be nice here */
|
||||
printf("%s\n", fname);
|
||||
}
|
||||
|
||||
xfree(fname);
|
||||
}
|
||||
|
||||
free_sftp_dirents(d);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* sftp ls.1 replacement which handles path globs */
|
||||
static int
|
||||
do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
|
||||
int lflag)
|
||||
{
|
||||
glob_t g;
|
||||
int i;
|
||||
Attrib *a;
|
||||
struct stat sb;
|
||||
|
||||
memset(&g, 0, sizeof(g));
|
||||
|
||||
if (remote_glob(conn, path, GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE,
|
||||
NULL, &g)) {
|
||||
error("Can't ls: \"%s\" not found", path);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the glob returns a single match, which is the same as the
|
||||
* input glob, and it is a directory, then just list its contents
|
||||
*/
|
||||
if (g.gl_pathc == 1 &&
|
||||
strncmp(path, g.gl_pathv[0], strlen(g.gl_pathv[0]) - 1) == 0) {
|
||||
if ((a = do_lstat(conn, path, 1)) == NULL) {
|
||||
globfree(&g);
|
||||
return (-1);
|
||||
}
|
||||
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
|
||||
S_ISDIR(a->perm)) {
|
||||
globfree(&g);
|
||||
return (do_ls_dir(conn, path, strip_path, lflag));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; g.gl_pathv[i]; i++) {
|
||||
char *fname, *lname;
|
||||
|
||||
fname = path_strip(g.gl_pathv[i], strip_path);
|
||||
|
||||
if (lflag) {
|
||||
/*
|
||||
* XXX: this is slow - 1 roundtrip per path
|
||||
* A solution to this is to fork glob() and
|
||||
* build a sftp specific version which keeps the
|
||||
* attribs (which currently get thrown away)
|
||||
* that the server returns as well as the filenames.
|
||||
*/
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
a = do_lstat(conn, g.gl_pathv[i], 1);
|
||||
if (a != NULL)
|
||||
attrib_to_stat(a, &sb);
|
||||
lname = ls_file(fname, &sb, 1);
|
||||
printf("%s\n", lname);
|
||||
xfree(lname);
|
||||
} else {
|
||||
/* XXX - multicolumn display would be nice here */
|
||||
printf("%s\n", fname);
|
||||
}
|
||||
xfree(fname);
|
||||
}
|
||||
|
||||
if (g.gl_pathc)
|
||||
globfree(&g);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_args(const char **cpp, int *pflag, int *lflag,
|
||||
unsigned long *n_arg, char **path1, char **path2)
|
||||
{
|
||||
const char *cmd, *cp = *cpp;
|
||||
char *cp2;
|
||||
|
@ -545,7 +708,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
|||
}
|
||||
|
||||
/* Get arguments and parse flags */
|
||||
*pflag = *n_arg = 0;
|
||||
*lflag = *pflag = *n_arg = 0;
|
||||
*path1 = *path2 = NULL;
|
||||
switch (cmdnum) {
|
||||
case I_GET:
|
||||
|
@ -592,6 +755,8 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
|||
}
|
||||
break;
|
||||
case I_LS:
|
||||
if (parse_ls_flags(&cp, lflag))
|
||||
return(-1);
|
||||
/* Path is optional */
|
||||
if (get_pathname(&cp, path1))
|
||||
return(-1);
|
||||
|
@ -652,7 +817,7 @@ static int
|
|||
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
||||
{
|
||||
char *path1, *path2, *tmp;
|
||||
int pflag, cmdnum, i;
|
||||
int pflag, lflag, cmdnum, i;
|
||||
unsigned long n_arg;
|
||||
Attrib a, *aa;
|
||||
char path_buf[MAXPATHLEN];
|
||||
|
@ -660,7 +825,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
|||
glob_t g;
|
||||
|
||||
path1 = path2 = NULL;
|
||||
cmdnum = parse_args(&cmd, &pflag, &n_arg, &path1, &path2);
|
||||
cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg,
|
||||
&path1, &path2);
|
||||
|
||||
memset(&g, 0, sizeof(g));
|
||||
|
||||
|
@ -732,22 +898,18 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
|||
break;
|
||||
case I_LS:
|
||||
if (!path1) {
|
||||
do_ls(conn, *pwd);
|
||||
do_globbed_ls(conn, *pwd, *pwd, lflag);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Strip pwd off beginning of non-absolute paths */
|
||||
tmp = NULL;
|
||||
if (*path1 != '/')
|
||||
tmp = *pwd;
|
||||
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
if ((tmp = do_realpath(conn, path1)) == NULL)
|
||||
break;
|
||||
xfree(path1);
|
||||
path1 = tmp;
|
||||
if ((aa = do_stat(conn, path1, 0)) == NULL)
|
||||
break;
|
||||
if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
|
||||
!S_ISDIR(aa->perm)) {
|
||||
error("Can't ls: \"%s\" is not a directory", path1);
|
||||
break;
|
||||
}
|
||||
do_ls(conn, path1);
|
||||
|
||||
do_globbed_ls(conn, path1, tmp, lflag);
|
||||
break;
|
||||
case I_LCHDIR:
|
||||
if (chdir(path1) == -1) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-server.c,v 1.37 2002/06/24 17:57:20 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sftp-server.c,v 1.38 2002/09/11 22:41:50 djm Exp $");
|
||||
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
@ -695,48 +695,6 @@ process_opendir(void)
|
|||
xfree(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
|
||||
*/
|
||||
static char *
|
||||
ls_file(char *name, struct stat *st)
|
||||
{
|
||||
int ulen, glen, sz = 0;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
struct tm *ltime = localtime(&st->st_mtime);
|
||||
char *user, *group;
|
||||
char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
|
||||
|
||||
strmode(st->st_mode, mode);
|
||||
if ((pw = getpwuid(st->st_uid)) != NULL) {
|
||||
user = pw->pw_name;
|
||||
} else {
|
||||
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
|
||||
user = ubuf;
|
||||
}
|
||||
if ((gr = getgrgid(st->st_gid)) != NULL) {
|
||||
group = gr->gr_name;
|
||||
} else {
|
||||
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
|
||||
group = gbuf;
|
||||
}
|
||||
if (ltime != NULL) {
|
||||
if (time(NULL) - st->st_mtime < (365*24*60*60)/2)
|
||||
sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
|
||||
else
|
||||
sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime);
|
||||
}
|
||||
if (sz == 0)
|
||||
tbuf[0] = '\0';
|
||||
ulen = MAX(strlen(user), 8);
|
||||
glen = MAX(strlen(group), 8);
|
||||
snprintf(buf, sizeof buf, "%s %3d %-*s %-*s %8llu %s %s", mode,
|
||||
st->st_nlink, ulen, user, glen, group,
|
||||
(u_int64_t)st->st_size, tbuf, name);
|
||||
return xstrdup(buf);
|
||||
}
|
||||
|
||||
static void
|
||||
process_readdir(void)
|
||||
{
|
||||
|
@ -772,7 +730,7 @@ process_readdir(void)
|
|||
continue;
|
||||
stat_to_attrib(&st, &(stats[count].attrib));
|
||||
stats[count].name = xstrdup(dp->d_name);
|
||||
stats[count].long_name = ls_file(dp->d_name, &st);
|
||||
stats[count].long_name = ls_file(dp->d_name, &st, 0);
|
||||
count++;
|
||||
/* send up to 100 entries in one message */
|
||||
/* XXX check packet size instead */
|
||||
|
|
12
sftp.1
12
sftp.1
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: sftp.1,v 1.35 2002/06/20 20:00:05 stevesk Exp $
|
||||
.\" $OpenBSD: sftp.1,v 1.36 2002/09/11 22:41:50 djm Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
.\"
|
||||
|
@ -203,12 +203,18 @@ to
|
|||
.Ar newpath .
|
||||
.It Ic lpwd
|
||||
Print local working directory.
|
||||
.It Ic ls Op Ar path
|
||||
.It Xo Ic ls
|
||||
.Op Ar flags
|
||||
.Op Ar path
|
||||
.Xc
|
||||
Display remote directory listing of either
|
||||
.Ar path
|
||||
or current directory if
|
||||
.Ar path
|
||||
is not specified.
|
||||
is not specified. If the
|
||||
.Fl l
|
||||
flag is specified, then display additional details including permissions
|
||||
and ownership information.
|
||||
.It Ic lumask Ar umask
|
||||
Set local umask to
|
||||
.Ar umask .
|
||||
|
|
Загрузка…
Ссылка в новой задаче