mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
- 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:
parent
789e95dbe9
commit
e1a4981707
@ -22,6 +22,10 @@
|
|||||||
[authfd.c authfd.h ssh.c]
|
[authfd.c authfd.h ssh.c]
|
||||||
don't connect to agent to test for presence if we've previously
|
don't connect to agent to test for presence if we've previously
|
||||||
connected; ok markus@
|
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
|
20020911
|
||||||
- (djm) Sync openbsd-compat with OpenBSD -current
|
- (djm) Sync openbsd-compat with OpenBSD -current
|
||||||
@ -1642,4 +1646,4 @@
|
|||||||
- (stevesk) entropy.c: typo in debug message
|
- (stevesk) entropy.c: typo in debug message
|
||||||
- (djm) ssh-keygen -i needs seeded RNG; report from markus@
|
- (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 */
|
/* XXX: copy between two remote sites */
|
||||||
|
|
||||||
#include "includes.h"
|
#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"
|
#include "openbsd-compat/fake-queue.h"
|
||||||
|
|
||||||
@ -414,12 +414,6 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
do_ls(struct sftp_conn *conn, char *path)
|
|
||||||
{
|
|
||||||
return(do_lsreaddir(conn, path, 1, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
|
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.
|
* 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' */
|
/* Close file referred to by 'handle' */
|
||||||
int do_close(struct sftp_conn *, char *, u_int);
|
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' */
|
/* Read contents of 'path' to NULL-terminated array 'dir' */
|
||||||
int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
|
int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
@ -65,6 +65,26 @@ stat_to_attrib(struct stat *st, Attrib *a)
|
|||||||
a->mtime = st->st_mtime;
|
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 */
|
/* Decode attributes in buffer */
|
||||||
Attrib *
|
Attrib *
|
||||||
decode_attrib(Buffer *b)
|
decode_attrib(Buffer *b)
|
||||||
@ -149,3 +169,45 @@ fx2txt(int status)
|
|||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* 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.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
@ -40,7 +40,9 @@ struct Attrib {
|
|||||||
|
|
||||||
void attrib_clear(Attrib *);
|
void attrib_clear(Attrib *);
|
||||||
void stat_to_attrib(struct stat *, Attrib *);
|
void stat_to_attrib(struct stat *, Attrib *);
|
||||||
|
void attrib_to_stat(Attrib *, struct stat *);
|
||||||
Attrib *decode_attrib(Buffer *);
|
Attrib *decode_attrib(Buffer *);
|
||||||
void encode_attrib(Buffer *, Attrib *);
|
void encode_attrib(Buffer *, Attrib *);
|
||||||
|
char *ls_file(char *, struct stat *, int);
|
||||||
|
|
||||||
const char *fx2txt(int);
|
const char *fx2txt(int);
|
||||||
|
21
sftp-glob.c
21
sftp-glob.c
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
@ -107,25 +107,6 @@ fudge_closedir(struct SFTP_OPENDIR *od)
|
|||||||
xfree(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
|
static int
|
||||||
fudge_lstat(const char *path, struct stat *st)
|
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.
|
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||||
@ -31,8 +31,7 @@
|
|||||||
|
|
||||||
#include "sftp-client.h"
|
#include "sftp-client.h"
|
||||||
|
|
||||||
int
|
int remote_glob(struct sftp_conn *, const char *, int,
|
||||||
remote_glob(struct sftp_conn *, const char *, int,
|
|
||||||
int (*)(const char *, int), glob_t *);
|
int (*)(const char *, int), glob_t *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
204
sftp-int.c
204
sftp-int.c
@ -22,11 +22,10 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* XXX: globbed ls */
|
|
||||||
/* XXX: recursive operations */
|
/* XXX: recursive operations */
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "buffer.h"
|
||||||
#include "xmalloc.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 *
|
static char *
|
||||||
path_append(char *p1, char *p2)
|
path_append(char *p1, char *p2)
|
||||||
{
|
{
|
||||||
@ -209,7 +228,7 @@ path_append(char *p1, char *p2)
|
|||||||
|
|
||||||
ret = xmalloc(len);
|
ret = xmalloc(len);
|
||||||
strlcpy(ret, p1, len);
|
strlcpy(ret, p1, len);
|
||||||
if (strcmp(p1, "/") != 0)
|
if (p1[strlen(p1) - 1] != '/')
|
||||||
strlcat(ret, "/", len);
|
strlcat(ret, "/", len);
|
||||||
strlcat(ret, p2, len);
|
strlcat(ret, p2, len);
|
||||||
|
|
||||||
@ -273,6 +292,29 @@ parse_getput_flags(const char **cpp, int *pflag)
|
|||||||
return(0);
|
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
|
static int
|
||||||
get_pathname(const char **cpp, char **path)
|
get_pathname(const char **cpp, char **path)
|
||||||
{
|
{
|
||||||
@ -504,8 +546,129 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
sdirent_comp(const void *aa, const void *bb)
|
||||||
char **path1, char **path2)
|
{
|
||||||
|
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;
|
const char *cmd, *cp = *cpp;
|
||||||
char *cp2;
|
char *cp2;
|
||||||
@ -545,7 +708,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get arguments and parse flags */
|
/* Get arguments and parse flags */
|
||||||
*pflag = *n_arg = 0;
|
*lflag = *pflag = *n_arg = 0;
|
||||||
*path1 = *path2 = NULL;
|
*path1 = *path2 = NULL;
|
||||||
switch (cmdnum) {
|
switch (cmdnum) {
|
||||||
case I_GET:
|
case I_GET:
|
||||||
@ -592,6 +755,8 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case I_LS:
|
case I_LS:
|
||||||
|
if (parse_ls_flags(&cp, lflag))
|
||||||
|
return(-1);
|
||||||
/* Path is optional */
|
/* Path is optional */
|
||||||
if (get_pathname(&cp, path1))
|
if (get_pathname(&cp, path1))
|
||||||
return(-1);
|
return(-1);
|
||||||
@ -652,7 +817,7 @@ static int
|
|||||||
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
||||||
{
|
{
|
||||||
char *path1, *path2, *tmp;
|
char *path1, *path2, *tmp;
|
||||||
int pflag, cmdnum, i;
|
int pflag, lflag, cmdnum, i;
|
||||||
unsigned long n_arg;
|
unsigned long n_arg;
|
||||||
Attrib a, *aa;
|
Attrib a, *aa;
|
||||||
char path_buf[MAXPATHLEN];
|
char path_buf[MAXPATHLEN];
|
||||||
@ -660,7 +825,8 @@ 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, &n_arg, &path1, &path2);
|
cmdnum = parse_args(&cmd, &pflag, &lflag, &n_arg,
|
||||||
|
&path1, &path2);
|
||||||
|
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
|
|
||||||
@ -732,22 +898,18 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
|||||||
break;
|
break;
|
||||||
case I_LS:
|
case I_LS:
|
||||||
if (!path1) {
|
if (!path1) {
|
||||||
do_ls(conn, *pwd);
|
do_globbed_ls(conn, *pwd, *pwd, lflag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Strip pwd off beginning of non-absolute paths */
|
||||||
|
tmp = NULL;
|
||||||
|
if (*path1 != '/')
|
||||||
|
tmp = *pwd;
|
||||||
|
|
||||||
path1 = make_absolute(path1, *pwd);
|
path1 = make_absolute(path1, *pwd);
|
||||||
if ((tmp = do_realpath(conn, path1)) == NULL)
|
|
||||||
break;
|
do_globbed_ls(conn, path1, tmp, lflag);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
case I_LCHDIR:
|
case I_LCHDIR:
|
||||||
if (chdir(path1) == -1) {
|
if (chdir(path1) == -1) {
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#include "includes.h"
|
#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 "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
@ -695,48 +695,6 @@ process_opendir(void)
|
|||||||
xfree(path);
|
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
|
static void
|
||||||
process_readdir(void)
|
process_readdir(void)
|
||||||
{
|
{
|
||||||
@ -772,7 +730,7 @@ process_readdir(void)
|
|||||||
continue;
|
continue;
|
||||||
stat_to_attrib(&st, &(stats[count].attrib));
|
stat_to_attrib(&st, &(stats[count].attrib));
|
||||||
stats[count].name = xstrdup(dp->d_name);
|
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++;
|
count++;
|
||||||
/* send up to 100 entries in one message */
|
/* send up to 100 entries in one message */
|
||||||
/* XXX check packet size instead */
|
/* 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.
|
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
@ -203,12 +203,18 @@ to
|
|||||||
.Ar newpath .
|
.Ar newpath .
|
||||||
.It Ic lpwd
|
.It Ic lpwd
|
||||||
Print local working directory.
|
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
|
Display remote directory listing of either
|
||||||
.Ar path
|
.Ar path
|
||||||
or current directory if
|
or current directory if
|
||||||
.Ar path
|
.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
|
.It Ic lumask Ar umask
|
||||||
Set local umask to
|
Set local umask to
|
||||||
.Ar umask .
|
.Ar umask .
|
||||||
|
Loading…
x
Reference in New Issue
Block a user