diff options
author | Darren Tucker <dtucker@zip.com.au> | 2010-12-05 09:02:47 +1100 |
---|---|---|
committer | Darren Tucker <dtucker@zip.com.au> | 2010-12-05 09:02:47 +1100 |
commit | af1f90925494deba97a4b877798cf250f7dc75cf (patch) | |
tree | c6e44e388c2bd4ca0caad6ce9f422576fe650b57 /sftp.c | |
parent | adab6f12992c522e1208fa2bdf89ce572840ccf8 (diff) |
- djm@cvs.openbsd.org 2010/12/04 00:18:01
[sftp-server.c sftp.1 sftp-client.h sftp.c PROTOCOL sftp-client.c]
add a protocol extension to support a hard link operation. It is
available through the "ln" command in the client. The old "ln"
behaviour of creating a symlink is available using its "-s" option
or through the preexisting "symlink" command; based on a patch from
miklos AT szeredi.hu in bz#1555; ok markus@
Diffstat (limited to 'sftp.c')
-rw-r--r-- | sftp.c | 53 |
1 files changed, 43 insertions, 10 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp.c,v 1.131 2010/10/23 22:06:12 sthen Exp $ */ | 1 | /* $OpenBSD: sftp.c,v 1.132 2010/12/04 00:18:01 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 | * |
@@ -132,6 +132,7 @@ extern char *__progname; | |||
132 | #define I_GET 5 | 132 | #define I_GET 5 |
133 | #define I_HELP 6 | 133 | #define I_HELP 6 |
134 | #define I_LCHDIR 7 | 134 | #define I_LCHDIR 7 |
135 | #define I_LINK 25 | ||
135 | #define I_LLS 8 | 136 | #define I_LLS 8 |
136 | #define I_LMKDIR 9 | 137 | #define I_LMKDIR 9 |
137 | #define I_LPWD 10 | 138 | #define I_LPWD 10 |
@@ -176,7 +177,7 @@ static const struct CMD cmds[] = { | |||
176 | { "lchdir", I_LCHDIR, LOCAL }, | 177 | { "lchdir", I_LCHDIR, LOCAL }, |
177 | { "lls", I_LLS, LOCAL }, | 178 | { "lls", I_LLS, LOCAL }, |
178 | { "lmkdir", I_LMKDIR, LOCAL }, | 179 | { "lmkdir", I_LMKDIR, LOCAL }, |
179 | { "ln", I_SYMLINK, REMOTE }, | 180 | { "ln", I_LINK, REMOTE }, |
180 | { "lpwd", I_LPWD, LOCAL }, | 181 | { "lpwd", I_LPWD, LOCAL }, |
181 | { "ls", I_LS, REMOTE }, | 182 | { "ls", I_LS, REMOTE }, |
182 | { "lumask", I_LUMASK, NOARGS }, | 183 | { "lumask", I_LUMASK, NOARGS }, |
@@ -240,7 +241,7 @@ help(void) | |||
240 | "lcd path Change local directory to 'path'\n" | 241 | "lcd path Change local directory to 'path'\n" |
241 | "lls [ls-options [path]] Display local directory listing\n" | 242 | "lls [ls-options [path]] Display local directory listing\n" |
242 | "lmkdir path Create local directory\n" | 243 | "lmkdir path Create local directory\n" |
243 | "ln oldpath newpath Symlink remote file\n" | 244 | "ln [-s] oldpath newpath Link remote file (-s for symlink)\n" |
244 | "lpwd Print local working directory\n" | 245 | "lpwd Print local working directory\n" |
245 | "ls [-1afhlnrSt] [path] Display remote directory listing\n" | 246 | "ls [-1afhlnrSt] [path] Display remote directory listing\n" |
246 | "lumask umask Set local umask to 'umask'\n" | 247 | "lumask umask Set local umask to 'umask'\n" |
@@ -377,6 +378,30 @@ parse_getput_flags(const char *cmd, char **argv, int argc, int *pflag, | |||
377 | } | 378 | } |
378 | 379 | ||
379 | static int | 380 | static int |
381 | parse_link_flags(const char *cmd, char **argv, int argc, int *sflag) | ||
382 | { | ||
383 | extern int opterr, optind, optopt, optreset; | ||
384 | int ch; | ||
385 | |||
386 | optind = optreset = 1; | ||
387 | opterr = 0; | ||
388 | |||
389 | *sflag = 0; | ||
390 | while ((ch = getopt(argc, argv, "s")) != -1) { | ||
391 | switch (ch) { | ||
392 | case 's': | ||
393 | *sflag = 1; | ||
394 | break; | ||
395 | default: | ||
396 | error("%s: Invalid flag -%c", cmd, optopt); | ||
397 | return -1; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | return optind; | ||
402 | } | ||
403 | |||
404 | static int | ||
380 | parse_ls_flags(char **argv, int argc, int *lflag) | 405 | parse_ls_flags(char **argv, int argc, int *lflag) |
381 | { | 406 | { |
382 | extern int opterr, optind, optopt, optreset; | 407 | extern int opterr, optind, optopt, optreset; |
@@ -1088,7 +1113,7 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, | |||
1088 | 1113 | ||
1089 | static int | 1114 | static int |
1090 | parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, | 1115 | parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, |
1091 | int *hflag, unsigned long *n_arg, char **path1, char **path2) | 1116 | int *hflag, int *sflag, unsigned long *n_arg, char **path1, char **path2) |
1092 | { | 1117 | { |
1093 | const char *cmd, *cp = *cpp; | 1118 | const char *cmd, *cp = *cpp; |
1094 | char *cp2, **argv; | 1119 | char *cp2, **argv; |
@@ -1138,7 +1163,8 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, | |||
1138 | switch (cmdnum) { | 1163 | switch (cmdnum) { |
1139 | case I_GET: | 1164 | case I_GET: |
1140 | case I_PUT: | 1165 | case I_PUT: |
1141 | if ((optidx = parse_getput_flags(cmd, argv, argc, pflag, rflag)) == -1) | 1166 | if ((optidx = parse_getput_flags(cmd, argv, argc, |
1167 | pflag, rflag)) == -1) | ||
1142 | return -1; | 1168 | return -1; |
1143 | /* Get first pathname (mandatory) */ | 1169 | /* Get first pathname (mandatory) */ |
1144 | if (argc - optidx < 1) { | 1170 | if (argc - optidx < 1) { |
@@ -1154,8 +1180,11 @@ parse_args(const char **cpp, int *pflag, int *rflag, int *lflag, int *iflag, | |||
1154 | undo_glob_escape(*path2); | 1180 | undo_glob_escape(*path2); |
1155 | } | 1181 | } |
1156 | break; | 1182 | break; |
1157 | case I_RENAME: | 1183 | case I_LINK: |
1184 | if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) | ||
1185 | return -1; | ||
1158 | case I_SYMLINK: | 1186 | case I_SYMLINK: |
1187 | case I_RENAME: | ||
1159 | if (argc - optidx < 2) { | 1188 | if (argc - optidx < 2) { |
1160 | error("You must specify two paths after a %s " | 1189 | error("You must specify two paths after a %s " |
1161 | "command.", cmd); | 1190 | "command.", cmd); |
@@ -1258,7 +1287,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1258 | int err_abort) | 1287 | int err_abort) |
1259 | { | 1288 | { |
1260 | char *path1, *path2, *tmp; | 1289 | char *path1, *path2, *tmp; |
1261 | int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, cmdnum, i; | 1290 | int pflag = 0, rflag = 0, lflag = 0, iflag = 0, hflag = 0, sflag = 0; |
1291 | int cmdnum, i; | ||
1262 | unsigned long n_arg = 0; | 1292 | unsigned long n_arg = 0; |
1263 | Attrib a, *aa; | 1293 | Attrib a, *aa; |
1264 | char path_buf[MAXPATHLEN]; | 1294 | char path_buf[MAXPATHLEN]; |
@@ -1266,8 +1296,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1266 | glob_t g; | 1296 | glob_t g; |
1267 | 1297 | ||
1268 | path1 = path2 = NULL; | 1298 | path1 = path2 = NULL; |
1269 | cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, &n_arg, | 1299 | cmdnum = parse_args(&cmd, &pflag, &rflag, &lflag, &iflag, &hflag, |
1270 | &path1, &path2); | 1300 | &sflag, &n_arg, &path1, &path2); |
1271 | 1301 | ||
1272 | if (iflag != 0) | 1302 | if (iflag != 0) |
1273 | err_abort = 0; | 1303 | err_abort = 0; |
@@ -1295,8 +1325,11 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, | |||
1295 | err = do_rename(conn, path1, path2); | 1325 | err = do_rename(conn, path1, path2); |
1296 | break; | 1326 | break; |
1297 | case I_SYMLINK: | 1327 | case I_SYMLINK: |
1328 | sflag = 1; | ||
1329 | case I_LINK: | ||
1330 | path1 = make_absolute(path1, *pwd); | ||
1298 | path2 = make_absolute(path2, *pwd); | 1331 | path2 = make_absolute(path2, *pwd); |
1299 | err = do_symlink(conn, path1, path2); | 1332 | err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2); |
1300 | break; | 1333 | break; |
1301 | case I_RM: | 1334 | case I_RM: |
1302 | path1 = make_absolute(path1, *pwd); | 1335 | path1 = make_absolute(path1, *pwd); |