summaryrefslogtreecommitdiff
path: root/sftp-int.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-int.c')
-rw-r--r--sftp-int.c288
1 files changed, 216 insertions, 72 deletions
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"
29RCSID("$OpenBSD: sftp-int.c,v 1.28 2001/03/14 15:15:58 markus Exp $"); 29RCSID("$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
197char * 197char *
198path_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
210char *
198make_absolute(char *p, char *pwd) 211make_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
224int
225infer_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
212int 244int
@@ -281,23 +313,182 @@ get_pathname(const char **cpp, char **path)
281} 313}
282 314
283int 315int
284infer_path(const char *p, char **ifp) 316is_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
327int
328remote_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
340int
341process_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
409out:
410 xfree(abs_src);
411 if (abs_dst)
412 xfree(abs_dst);
413 globfree(&g);
414 return(err);
415}
416
417int
418process_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
486out:
487 if (abs_dst)
488 xfree(abs_dst);
489 if (tmp_dst)
490 xfree(tmp_dst);
491 return(err);
301} 492}
302 493
303int 494int
@@ -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)