summaryrefslogtreecommitdiff
path: root/sftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp.c')
-rw-r--r--sftp.c53
1 files changed, 43 insertions, 10 deletions
diff --git a/sftp.c b/sftp.c
index d605505e..ab667f5a 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.131 2010/10/23 22:06:12 sthen Exp $ */
+/* $OpenBSD: sftp.c,v 1.132 2010/12/04 00:18:01 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -132,6 +132,7 @@ extern char *__progname;
#define I_GET 5
#define I_HELP 6
#define I_LCHDIR 7
+#define I_LINK 25
#define I_LLS 8
#define I_LMKDIR 9
#define I_LPWD 10
@@ -176,7 +177,7 @@ static const struct CMD cmds[] = {
{ "lchdir", I_LCHDIR, LOCAL },
{ "lls", I_LLS, LOCAL },
{ "lmkdir", I_LMKDIR, LOCAL },
- { "ln", I_SYMLINK, REMOTE },
+ { "ln", I_LINK, REMOTE },
{ "lpwd", I_LPWD, LOCAL },
{ "ls", I_LS, REMOTE },
{ "lumask", I_LUMASK, NOARGS },
@@ -240,7 +241,7 @@ help(void)
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
"lmkdir path Create local directory\n"
- "ln oldpath newpath Symlink remote file\n"
+ "ln [-s] oldpath newpath Link remote file (-s for symlink)\n"
"lpwd Print local working directory\n"
"ls [-1afhlnrSt] [path] Display remote directory listing\n"
"lumask umask Set local umask to 'umask'\n"
@@ -377,6 +378,30 @@ parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag,
}
static int
+parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
+{
+ extern int opterr, optind, optopt, optreset;
+ int ch;
+
+ optind = optreset = 1;
+ opterr = 0;
+
+ *sflag = 0;
+ while ((ch = getopt(argc, argv, "s")) != -1) {
+ switch (ch) {
+ case 's':
+ *sflag = 1;
+ break;
+ default:
+ error("%s: Invalid flag -%c", cmd, optopt);
+ return -1;
+ }
+ }
+
+ return optind;
+}
+
+static int
parse_ls_flags(char **argv, int argc, int *lflag)
{
extern int opterr, optind, optopt, optreset;
@@ -1088,7 +1113,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
static int
parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
- int *hflag, unsigned long *n_arg, char **path1, char **path2)
+ int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2)
{
const char *cmd, *cp = *cpp;
char *cp2, **argv;
@@ -1138,7 +1163,8 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
switch (cmdnum) {
case I_GET:
case I_PUT:
- if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag)) == -1)
+ if ((optidx = parse_getput_flags(cmd, argv, argc,
+ pflag, rflag)) == -1)
return -1;
/* Get first pathname (mandatory) */
if (argc - optidx < 1) {
@@ -1154,8 +1180,11 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag,
undo_glob_escape(*path2);
}
break;
- case I_RENAME:
+ case I_LINK:
+ if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
+ return -1;
case I_SYMLINK:
+ case I_RENAME:
if (argc - optidx < 2) {
error("You must specify two paths after a %s "
"command.", cmd);
@@ -1258,7 +1287,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
int err_abort)
{
char *path1, *path2, *tmp;
- int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i;
+ int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0;
+ int cmdnum, i;
unsigned long n_arg = 0;
Attrib a, *aa;
char path_buf[MAXPATHLEN];
@@ -1266,8 +1296,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &n_arg,
- &path1, &path2);
+ cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag,
+ &sflag, &n_arg, &path1, &path2);
if (iflag != 0)
err_abort = 0;
@@ -1295,8 +1325,11 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
err = do_rename(conn, path1, path2);
break;
case I_SYMLINK:
+ sflag = 1;
+ case I_LINK:
+ path1 = make_absolute(path1, *pwd);
path2 = make_absolute(path2, *pwd);
- err = do_symlink(conn, path1, path2);
+ err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
break;
case I_RM:
path1 = make_absolute(path1, *pwd);