diff options
author | Ben Lindstrom <mouring@eviladmin.org> | 2001-03-17 00:34:46 +0000 |
---|---|---|
committer | Ben Lindstrom <mouring@eviladmin.org> | 2001-03-17 00:34:46 +0000 |
commit | c8d1c30c312003ecbeba9a383f0a61ed45ad0c04 (patch) | |
tree | de4f4b94c8d94f24164b03ea6e114d02e81d216a | |
parent | 86fe8686b920b7da020b96aaf2303a7b596c36a4 (diff) |
- djm@cvs.openbsd.org 2001/03/16 08:16:18
[sftp-client.c sftp-client.h sftp-glob.c sftp-int.c]
Revise globbing for get/put to be more shell-like. In particular,
"get/put file* directory/" now works. ok markus@
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | sftp-client.c | 32 | ||||
-rw-r--r-- | sftp-client.h | 10 | ||||
-rw-r--r-- | sftp-glob.c | 6 | ||||
-rw-r--r-- | sftp-int.c | 288 |
5 files changed, 249 insertions, 93 deletions
@@ -8,6 +8,10 @@ | |||
8 | - markus@cvs.openbsd.org 2001/03/15 22:07:08 | 8 | - markus@cvs.openbsd.org 2001/03/15 22:07:08 |
9 | [session.c] | 9 | [session.c] |
10 | pass Session to do_child + KNF | 10 | pass Session to do_child + KNF |
11 | - djm@cvs.openbsd.org 2001/03/16 08:16:18 | ||
12 | [sftp-client.c sftp-client.h sftp-glob.c sftp-int.c] | ||
13 | Revise globbing for get/put to be more shell-like. In particular, | ||
14 | "get/put file* directory/" now works. ok markus@ | ||
11 | 15 | ||
12 | 20010315 | 16 | 20010315 |
13 | - OpenBSD CVS Sync | 17 | - OpenBSD CVS Sync |
@@ -4570,4 +4574,4 @@ | |||
4570 | - Wrote replacements for strlcpy and mkdtemp | 4574 | - Wrote replacements for strlcpy and mkdtemp |
4571 | - Released 1.0pre1 | 4575 | - Released 1.0pre1 |
4572 | 4576 | ||
4573 | $Id: ChangeLog,v 1.963 2001/03/17 00:32:57 mouring Exp $ | 4577 | $Id: ChangeLog,v 1.964 2001/03/17 00:34:46 mouring Exp $ |
diff --git a/sftp-client.c b/sftp-client.c index 87f3053f6..b0007a734 100644 --- a/sftp-client.c +++ b/sftp-client.c | |||
@@ -29,7 +29,7 @@ | |||
29 | /* XXX: copy between two remote sites */ | 29 | /* XXX: copy between two remote sites */ |
30 | 30 | ||
31 | #include "includes.h" | 31 | #include "includes.h" |
32 | RCSID("$OpenBSD: sftp-client.c,v 1.13 2001/03/14 08:57:14 markus Exp $"); | 32 | RCSID("$OpenBSD: sftp-client.c,v 1.14 2001/03/16 08:16:17 djm Exp $"); |
33 | 33 | ||
34 | #include "ssh.h" | 34 | #include "ssh.h" |
35 | #include "buffer.h" | 35 | #include "buffer.h" |
@@ -180,7 +180,7 @@ get_handle(int fd, u_int expected_id, u_int *len) | |||
180 | } | 180 | } |
181 | 181 | ||
182 | Attrib * | 182 | Attrib * |
183 | get_decode_stat(int fd, u_int expected_id) | 183 | get_decode_stat(int fd, u_int expected_id, int quiet) |
184 | { | 184 | { |
185 | Buffer msg; | 185 | Buffer msg; |
186 | u_int type, id; | 186 | u_int type, id; |
@@ -198,7 +198,10 @@ get_decode_stat(int fd, u_int expected_id) | |||
198 | if (type == SSH2_FXP_STATUS) { | 198 | if (type == SSH2_FXP_STATUS) { |
199 | int status = buffer_get_int(&msg); | 199 | int status = buffer_get_int(&msg); |
200 | 200 | ||
201 | error("Couldn't stat remote file: %s", fx2txt(status)); | 201 | if (quiet) |
202 | debug("Couldn't stat remote file: %s", fx2txt(status)); | ||
203 | else | ||
204 | error("Couldn't stat remote file: %s", fx2txt(status)); | ||
202 | return(NULL); | 205 | return(NULL); |
203 | } else if (type != SSH2_FXP_ATTRS) { | 206 | } else if (type != SSH2_FXP_ATTRS) { |
204 | fatal("Expected SSH2_FXP_ATTRS(%d) packet, got %d", | 207 | fatal("Expected SSH2_FXP_ATTRS(%d) packet, got %d", |
@@ -455,34 +458,33 @@ do_rmdir(int fd_in, int fd_out, char *path) | |||
455 | } | 458 | } |
456 | 459 | ||
457 | Attrib * | 460 | Attrib * |
458 | do_stat(int fd_in, int fd_out, char *path) | 461 | do_stat(int fd_in, int fd_out, char *path, int quiet) |
459 | { | 462 | { |
460 | u_int id; | 463 | u_int id; |
461 | 464 | ||
462 | id = msg_id++; | 465 | id = msg_id++; |
463 | send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path)); | 466 | send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path)); |
464 | return(get_decode_stat(fd_in, id)); | 467 | return(get_decode_stat(fd_in, id, quiet)); |
465 | } | 468 | } |
466 | 469 | ||
467 | Attrib * | 470 | Attrib * |
468 | do_lstat(int fd_in, int fd_out, char *path) | 471 | do_lstat(int fd_in, int fd_out, char *path, int quiet) |
469 | { | 472 | { |
470 | u_int id; | 473 | u_int id; |
471 | 474 | ||
472 | id = msg_id++; | 475 | id = msg_id++; |
473 | send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path)); | 476 | send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path)); |
474 | return(get_decode_stat(fd_in, id)); | 477 | return(get_decode_stat(fd_in, id, quiet)); |
475 | } | 478 | } |
476 | 479 | ||
477 | Attrib * | 480 | Attrib * |
478 | do_fstat(int fd_in, int fd_out, char *handle, | 481 | do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet) |
479 | u_int handle_len) | ||
480 | { | 482 | { |
481 | u_int id; | 483 | u_int id; |
482 | 484 | ||
483 | id = msg_id++; | 485 | id = msg_id++; |
484 | send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len); | 486 | send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len); |
485 | return(get_decode_stat(fd_in, id)); | 487 | return(get_decode_stat(fd_in, id, quiet)); |
486 | } | 488 | } |
487 | 489 | ||
488 | int | 490 | int |
@@ -677,7 +679,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path, | |||
677 | Attrib junk, *a; | 679 | Attrib junk, *a; |
678 | int status; | 680 | int status; |
679 | 681 | ||
680 | a = do_stat(fd_in, fd_out, remote_path); | 682 | a = do_stat(fd_in, fd_out, remote_path, 0); |
681 | if (a == NULL) | 683 | if (a == NULL) |
682 | return(-1); | 684 | return(-1); |
683 | 685 | ||
@@ -687,11 +689,17 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path, | |||
687 | else | 689 | else |
688 | mode = 0666; | 690 | mode = 0666; |
689 | 691 | ||
692 | if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && | ||
693 | (a->perm & S_IFDIR)) { | ||
694 | error("Cannot download a directory: %s", remote_path); | ||
695 | return(-1); | ||
696 | } | ||
697 | |||
690 | local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); | 698 | local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); |
691 | if (local_fd == -1) { | 699 | if (local_fd == -1) { |
692 | error("Couldn't open local file \"%s\" for writing: %s", | 700 | error("Couldn't open local file \"%s\" for writing: %s", |
693 | local_path, strerror(errno)); | 701 | local_path, strerror(errno)); |
694 | return(errno); | 702 | return(-1); |
695 | } | 703 | } |
696 | 704 | ||
697 | buffer_init(&msg); | 705 | buffer_init(&msg); |
diff --git a/sftp-client.h b/sftp-client.h index e7ba02ad6..a935736e3 100644 --- a/sftp-client.h +++ b/sftp-client.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.h,v 1.3 2001/03/13 22:42:54 djm Exp $ */ | 1 | /* $OpenBSD: sftp-client.h,v 1.4 2001/03/16 08:16:18 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2001 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2001 Damien Miller. All rights reserved. |
@@ -62,14 +62,14 @@ int do_mkdir(int fd_in, int fd_out, char *path, Attrib *a); | |||
62 | int do_rmdir(int fd_in, int fd_out, char *path); | 62 | int do_rmdir(int fd_in, int fd_out, char *path); |
63 | 63 | ||
64 | /* Get file attributes of 'path' (follows symlinks) */ | 64 | /* Get file attributes of 'path' (follows symlinks) */ |
65 | Attrib *do_stat(int fd_in, int fd_out, char *path); | 65 | Attrib *do_stat(int fd_in, int fd_out, char *path, int quiet); |
66 | 66 | ||
67 | /* Get file attributes of 'path' (does not follow symlinks) */ | 67 | /* Get file attributes of 'path' (does not follow symlinks) */ |
68 | Attrib *do_lstat(int fd_in, int fd_out, char *path); | 68 | Attrib *do_lstat(int fd_in, int fd_out, char *path, int quiet); |
69 | 69 | ||
70 | /* Get file attributes of open file 'handle' */ | 70 | /* Get file attributes of open file 'handle' */ |
71 | Attrib *do_fstat(int fd_in, int fd_out, char *handle, | 71 | Attrib *do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, |
72 | u_int handle_len); | 72 | int quiet); |
73 | 73 | ||
74 | /* Set file attributes of 'path' */ | 74 | /* Set file attributes of 'path' */ |
75 | int do_setstat(int fd_in, int fd_out, char *path, Attrib *a); | 75 | int do_setstat(int fd_in, int fd_out, char *path, Attrib *a); |
diff --git a/sftp-glob.c b/sftp-glob.c index aec6d2734..79dca00f1 100644 --- a/sftp-glob.c +++ b/sftp-glob.c | |||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | RCSID("$OpenBSD: sftp-glob.c,v 1.1 2001/03/13 22:42:54 djm Exp $"); | 26 | RCSID("$OpenBSD: sftp-glob.c,v 1.2 2001/03/16 08:16:18 djm Exp $"); |
27 | 27 | ||
28 | #include "ssh.h" | 28 | #include "ssh.h" |
29 | #include "buffer.h" | 29 | #include "buffer.h" |
@@ -119,7 +119,7 @@ int fudge_lstat(const char *path, struct stat *st) | |||
119 | { | 119 | { |
120 | Attrib *a; | 120 | Attrib *a; |
121 | 121 | ||
122 | if (!(a = do_lstat(cur.fd_in, cur.fd_out, (char*)path))) | 122 | if (!(a = do_lstat(cur.fd_in, cur.fd_out, (char*)path, 0))) |
123 | return(-1); | 123 | return(-1); |
124 | 124 | ||
125 | attrib_to_stat(a, st); | 125 | attrib_to_stat(a, st); |
@@ -131,7 +131,7 @@ int fudge_stat(const char *path, struct stat *st) | |||
131 | { | 131 | { |
132 | Attrib *a; | 132 | Attrib *a; |
133 | 133 | ||
134 | if (!(a = do_stat(cur.fd_in, cur.fd_out, (char*)path))) | 134 | if (!(a = do_stat(cur.fd_in, cur.fd_out, (char*)path, 0))) |
135 | return(-1); | 135 | return(-1); |
136 | 136 | ||
137 | attrib_to_stat(a, st); | 137 | attrib_to_stat(a, st); |
diff --git a/sftp-int.c b/sftp-int.c index cf86012ea..fdadf23b2 100644 --- a/sftp-int.c +++ b/sftp-int.c | |||
@@ -26,7 +26,7 @@ | |||
26 | /* XXX: recursive operations */ | 26 | /* XXX: recursive operations */ |
27 | 27 | ||
28 | #include "includes.h" | 28 | #include "includes.h" |
29 | RCSID("$OpenBSD: sftp-int.c,v 1.28 2001/03/14 15:15:58 markus Exp $"); | 29 | RCSID("$OpenBSD: sftp-int.c,v 1.29 2001/03/16 08:16:18 djm Exp $"); |
30 | 30 | ||
31 | #include "buffer.h" | 31 | #include "buffer.h" |
32 | #include "xmalloc.h" | 32 | #include "xmalloc.h" |
@@ -195,18 +195,50 @@ local_do_ls(const char *args) | |||
195 | } | 195 | } |
196 | 196 | ||
197 | char * | 197 | char * |
198 | path_append(char *p1, char *p2) | ||
199 | { | ||
200 | char *ret; | ||
201 | |||
202 | ret = xmalloc(strlen(p1) + strlen(p2) + 2); | ||
203 | strcpy(ret, p1); | ||
204 | strcat(ret, "/"); | ||
205 | strcat(ret, p2); | ||
206 | |||
207 | return(ret); | ||
208 | } | ||
209 | |||
210 | char * | ||
198 | make_absolute(char *p, char *pwd) | 211 | make_absolute(char *p, char *pwd) |
199 | { | 212 | { |
200 | char buf[2048]; | 213 | char *abs; |
201 | 214 | ||
202 | /* Derelativise */ | 215 | /* Derelativise */ |
203 | if (p && p[0] != '/') { | 216 | if (p && p[0] != '/') { |
204 | snprintf(buf, sizeof(buf), "%s/%s", pwd, p); | 217 | abs = path_append(pwd, p); |
205 | xfree(p); | 218 | xfree(p); |
206 | p = xstrdup(buf); | 219 | return(abs); |
220 | } else | ||
221 | return(p); | ||
222 | } | ||
223 | |||
224 | int | ||
225 | infer_path(const char *p, char **ifp) | ||
226 | { | ||
227 | char *cp; | ||
228 | |||
229 | cp = strrchr(p, '/'); | ||
230 | if (cp == NULL) { | ||
231 | *ifp = xstrdup(p); | ||
232 | return(0); | ||
233 | } | ||
234 | |||
235 | if (!cp[1]) { | ||
236 | error("Invalid path"); | ||
237 | return(-1); | ||
207 | } | 238 | } |
208 | 239 | ||
209 | return(p); | 240 | *ifp = xstrdup(cp + 1); |
241 | return(0); | ||
210 | } | 242 | } |
211 | 243 | ||
212 | int | 244 | int |
@@ -281,23 +313,182 @@ get_pathname(const char **cpp, char **path) | |||
281 | } | 313 | } |
282 | 314 | ||
283 | int | 315 | int |
284 | infer_path(const char *p, char **ifp) | 316 | is_dir(char *path) |
285 | { | 317 | { |
286 | char *cp; | 318 | struct stat sb; |
287 | 319 | ||
288 | cp = strrchr(p, '/'); | 320 | /* XXX: report errors? */ |
289 | if (cp == NULL) { | 321 | if (stat(path, &sb) == -1) |
290 | *ifp = xstrdup(p); | ||
291 | return(0); | 322 | return(0); |
323 | |||
324 | return(sb.st_mode & S_IFDIR); | ||
325 | } | ||
326 | |||
327 | int | ||
328 | remote_is_dir(int in, int out, char *path) | ||
329 | { | ||
330 | Attrib *a; | ||
331 | |||
332 | /* XXX: report errors? */ | ||
333 | if ((a = do_stat(in, out, path, 1)) == NULL) | ||
334 | return(0); | ||
335 | if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) | ||
336 | return(0); | ||
337 | return(a->perm & S_IFDIR); | ||
338 | } | ||
339 | |||
340 | int | ||
341 | process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) | ||
342 | { | ||
343 | char *abs_src = NULL; | ||
344 | char *abs_dst = NULL; | ||
345 | char *tmp; | ||
346 | glob_t g; | ||
347 | int err = 0; | ||
348 | int i; | ||
349 | |||
350 | abs_src = xstrdup(src); | ||
351 | abs_src = make_absolute(abs_src, pwd); | ||
352 | |||
353 | memset(&g, '\0', sizeof(g)); | ||
354 | debug3("Looking up %s", abs_src); | ||
355 | if (remote_glob(in, out, abs_src, 0, NULL, &g)) { | ||
356 | error("File \"%s\" not found.", abs_src); | ||
357 | err = -1; | ||
358 | goto out; | ||
292 | } | 359 | } |
293 | 360 | ||
294 | if (!cp[1]) { | 361 | /* Only one match, dst may be file, directory or unspecified */ |
295 | error("Invalid path"); | 362 | if (g.gl_pathv[0] && g.gl_matchc == 1) { |
296 | return(-1); | 363 | if (dst) { |
364 | /* If directory specified, append filename */ | ||
365 | if (is_dir(dst)) { | ||
366 | if (infer_path(g.gl_pathv[0], &tmp)) { | ||
367 | err = 1; | ||
368 | goto out; | ||
369 | } | ||
370 | abs_dst = path_append(dst, tmp); | ||
371 | xfree(tmp); | ||
372 | } else | ||
373 | abs_dst = xstrdup(dst); | ||
374 | } else if (infer_path(g.gl_pathv[0], &abs_dst)) { | ||
375 | err = -1; | ||
376 | goto out; | ||
377 | } | ||
378 | printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst); | ||
379 | err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag); | ||
380 | goto out; | ||
297 | } | 381 | } |
298 | 382 | ||
299 | *ifp = xstrdup(cp + 1); | 383 | /* Multiple matches, dst may be directory or unspecified */ |
300 | return(0); | 384 | if (dst && !is_dir(dst)) { |
385 | error("Multiple files match, but \"%s\" is not a directory", | ||
386 | dst); | ||
387 | err = -1; | ||
388 | goto out; | ||
389 | } | ||
390 | |||
391 | for(i = 0; g.gl_pathv[i]; i++) { | ||
392 | if (infer_path(g.gl_pathv[i], &tmp)) { | ||
393 | err = -1; | ||
394 | goto out; | ||
395 | } | ||
396 | if (dst) { | ||
397 | abs_dst = path_append(dst, tmp); | ||
398 | xfree(tmp); | ||
399 | } else | ||
400 | abs_dst = tmp; | ||
401 | |||
402 | printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); | ||
403 | if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag) == -1) | ||
404 | err = -1; | ||
405 | xfree(abs_dst); | ||
406 | abs_dst = NULL; | ||
407 | } | ||
408 | |||
409 | out: | ||
410 | xfree(abs_src); | ||
411 | if (abs_dst) | ||
412 | xfree(abs_dst); | ||
413 | globfree(&g); | ||
414 | return(err); | ||
415 | } | ||
416 | |||
417 | int | ||
418 | process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) | ||
419 | { | ||
420 | char *tmp_dst = NULL; | ||
421 | char *abs_dst = NULL; | ||
422 | char *tmp; | ||
423 | glob_t g; | ||
424 | int err = 0; | ||
425 | int i; | ||
426 | |||
427 | if (dst) { | ||
428 | tmp_dst = xstrdup(dst); | ||
429 | tmp_dst = make_absolute(tmp_dst, pwd); | ||
430 | } | ||
431 | |||
432 | memset(&g, '\0', sizeof(g)); | ||
433 | debug3("Looking up %s", src); | ||
434 | if (glob(src, 0, NULL, &g)) { | ||
435 | error("File \"%s\" not found.", src); | ||
436 | err = -1; | ||
437 | goto out; | ||
438 | } | ||
439 | |||
440 | /* Only one match, dst may be file, directory or unspecified */ | ||
441 | if (g.gl_pathv[0] && g.gl_matchc == 1) { | ||
442 | if (tmp_dst) { | ||
443 | /* If directory specified, append filename */ | ||
444 | if (remote_is_dir(in, out, tmp_dst)) { | ||
445 | if (infer_path(g.gl_pathv[0], &tmp)) { | ||
446 | err = 1; | ||
447 | goto out; | ||
448 | } | ||
449 | abs_dst = path_append(tmp_dst, tmp); | ||
450 | xfree(tmp); | ||
451 | } else | ||
452 | abs_dst = xstrdup(tmp_dst); | ||
453 | } else if (infer_path(g.gl_pathv[0], &abs_dst)) { | ||
454 | err = -1; | ||
455 | goto out; | ||
456 | } | ||
457 | printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst); | ||
458 | err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag); | ||
459 | goto out; | ||
460 | } | ||
461 | |||
462 | /* Multiple matches, dst may be directory or unspecified */ | ||
463 | if (tmp_dst && !remote_is_dir(in, out, tmp_dst)) { | ||
464 | error("Multiple files match, but \"%s\" is not a directory", | ||
465 | tmp_dst); | ||
466 | err = -1; | ||
467 | goto out; | ||
468 | } | ||
469 | |||
470 | for(i = 0; g.gl_pathv[i]; i++) { | ||
471 | if (infer_path(g.gl_pathv[i], &tmp)) { | ||
472 | err = -1; | ||
473 | goto out; | ||
474 | } | ||
475 | if (tmp_dst) { | ||
476 | abs_dst = path_append(tmp_dst, tmp); | ||
477 | xfree(tmp); | ||
478 | } else | ||
479 | abs_dst = make_absolute(tmp, pwd); | ||
480 | |||
481 | printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); | ||
482 | if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag) == -1) | ||
483 | err = -1; | ||
484 | } | ||
485 | |||
486 | out: | ||
487 | if (abs_dst) | ||
488 | xfree(abs_dst); | ||
489 | if (tmp_dst) | ||
490 | xfree(tmp_dst); | ||
491 | return(err); | ||
301 | } | 492 | } |
302 | 493 | ||
303 | int | 494 | int |
@@ -459,66 +650,17 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
459 | path1 = path2 = NULL; | 650 | path1 = path2 = NULL; |
460 | cmdnum = parse_args(&cmd, &pflag, &n_arg, &path1, &path2); | 651 | cmdnum = parse_args(&cmd, &pflag, &n_arg, &path1, &path2); |
461 | 652 | ||
653 | memset(&g, 0, sizeof(g)); | ||
654 | |||
462 | /* Perform command */ | 655 | /* Perform command */ |
463 | switch (cmdnum) { | 656 | switch (cmdnum) { |
464 | case -1: | 657 | case -1: |
465 | break; | 658 | break; |
466 | case I_GET: | 659 | case I_GET: |
467 | memset(&g, 0, sizeof(g)); | 660 | err = process_get(in, out, path1, path2, *pwd, pflag); |
468 | if (!remote_glob(in, out, path1, 0, NULL, &g)) { | ||
469 | if (path2) { | ||
470 | /* XXX: target should be directory */ | ||
471 | error("You cannot specify a target when " | ||
472 | "downloading multiple files"); | ||
473 | err = -1; | ||
474 | break; | ||
475 | } | ||
476 | for(i = 0; g.gl_pathv[i]; i++) { | ||
477 | if (!infer_path(g.gl_pathv[i], &path2)) { | ||
478 | printf("Fetching %s\n", g.gl_pathv[i]); | ||
479 | if (do_download(in, out, g.gl_pathv[i], | ||
480 | path2, pflag) == -1) | ||
481 | err = -1; | ||
482 | free(path2); | ||
483 | path2 = NULL; | ||
484 | } else | ||
485 | err = -1; | ||
486 | } | ||
487 | } else { | ||
488 | if (!path2 && infer_path(path1, &path2)) { | ||
489 | err = -1; | ||
490 | break; | ||
491 | } | ||
492 | err = do_download(in, out, path1, path2, pflag); | ||
493 | } | ||
494 | break; | 661 | break; |
495 | case I_PUT: | 662 | case I_PUT: |
496 | if (!glob(path1, 0, NULL, &g)) { | 663 | err = process_put(in, out, path1, path2, *pwd, pflag); |
497 | if (path2) { | ||
498 | error("You cannot specify a target when " | ||
499 | "uploading multiple files"); | ||
500 | err = -1; | ||
501 | break; | ||
502 | } | ||
503 | for(i = 0; g.gl_pathv[i]; i++) { | ||
504 | if (!infer_path(g.gl_pathv[i], &path2)) { | ||
505 | path2 = make_absolute(path2, *pwd); | ||
506 | printf("Uploading %s\n", g.gl_pathv[i]); | ||
507 | if (do_upload(in, out, g.gl_pathv[i], | ||
508 | path2, pflag) == -1) | ||
509 | err = -1; | ||
510 | free(path2); | ||
511 | path2 = NULL; | ||
512 | } else | ||
513 | err = -1; | ||
514 | } | ||
515 | } else { | ||
516 | if (!path2 && infer_path(path1, &path2)) { | ||
517 | err = -1; | ||
518 | break; | ||
519 | } | ||
520 | err = do_upload(in, out, path1, path2, pflag); | ||
521 | } | ||
522 | break; | 664 | break; |
523 | case I_RENAME: | 665 | case I_RENAME: |
524 | path1 = make_absolute(path1, *pwd); | 666 | path1 = make_absolute(path1, *pwd); |
@@ -561,7 +703,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
561 | err = 1; | 703 | err = 1; |
562 | break; | 704 | break; |
563 | } | 705 | } |
564 | if ((aa = do_stat(in, out, tmp)) == NULL) { | 706 | if ((aa = do_stat(in, out, tmp, 0)) == NULL) { |
565 | xfree(tmp); | 707 | xfree(tmp); |
566 | err = 1; | 708 | err = 1; |
567 | break; | 709 | break; |
@@ -592,7 +734,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
592 | break; | 734 | break; |
593 | xfree(path1); | 735 | xfree(path1); |
594 | path1 = tmp; | 736 | path1 = tmp; |
595 | if ((aa = do_stat(in, out, path1)) == NULL) | 737 | if ((aa = do_stat(in, out, path1, 0)) == NULL) |
596 | break; | 738 | break; |
597 | if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && | 739 | if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && |
598 | !S_ISDIR(aa->perm)) { | 740 | !S_ISDIR(aa->perm)) { |
@@ -640,7 +782,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
640 | path1 = make_absolute(path1, *pwd); | 782 | path1 = make_absolute(path1, *pwd); |
641 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); | 783 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); |
642 | for(i = 0; g.gl_pathv[i]; i++) { | 784 | for(i = 0; g.gl_pathv[i]; i++) { |
643 | if (!(aa = do_stat(in, out, g.gl_pathv[i]))) | 785 | if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) |
644 | continue; | 786 | continue; |
645 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 787 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
646 | error("Can't get current ownership of " | 788 | error("Can't get current ownership of " |
@@ -657,7 +799,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
657 | path1 = make_absolute(path1, *pwd); | 799 | path1 = make_absolute(path1, *pwd); |
658 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); | 800 | remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); |
659 | for(i = 0; g.gl_pathv[i]; i++) { | 801 | for(i = 0; g.gl_pathv[i]; i++) { |
660 | if (!(aa = do_stat(in, out, g.gl_pathv[i]))) | 802 | if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) |
661 | continue; | 803 | continue; |
662 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { | 804 | if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { |
663 | error("Can't get current ownership of " | 805 | error("Can't get current ownership of " |
@@ -693,6 +835,8 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | |||
693 | fatal("%d is not implemented", cmdnum); | 835 | fatal("%d is not implemented", cmdnum); |
694 | } | 836 | } |
695 | 837 | ||
838 | if (g.gl_pathc) | ||
839 | globfree(&g); | ||
696 | if (path1) | 840 | if (path1) |
697 | xfree(path1); | 841 | xfree(path1); |
698 | if (path2) | 842 | if (path2) |