summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2002-02-13 14:10:32 +1100
committerDamien Miller <djm@mindrot.org>2002-02-13 14:10:32 +1100
commit3db5f530d0fdf8044d6014ab12940efe0bbecca7 (patch)
tree578c5ea0091f934c13d40264b033bbd2532d2e9a
parent3606ee29388781894e6374030d0e40fa46da4cf9 (diff)
- djm@cvs.openbsd.org 2002/02/13 00:59:23
[sftp-client.c sftp-client.h sftp-glob.c sftp-glob.h sftp.h] [sftp-int.c sftp-int.h] API cleanup and backwards compat for filexfer v.0 servers; ok markus@
-rw-r--r--ChangeLog6
-rw-r--r--sftp-client.c302
-rw-r--r--sftp-client.h49
-rw-r--r--sftp-glob.c21
-rw-r--r--sftp-glob.h14
-rw-r--r--sftp-int.c104
-rw-r--r--sftp-int.h4
-rw-r--r--sftp.h3
8 files changed, 280 insertions, 223 deletions
diff --git a/ChangeLog b/ChangeLog
index e9e0c785a..b630bd541 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,10 @@
30 - markus@cvs.openbsd.org 2002/02/13 00:39:15 30 - markus@cvs.openbsd.org 2002/02/13 00:39:15
31 [readpass.c] 31 [readpass.c]
32 readpass.c is not longer from UCB, since we now use readpassphrase(3) 32 readpass.c is not longer from UCB, since we now use readpassphrase(3)
33 - djm@cvs.openbsd.org 2002/02/13 00:59:23
34 [sftp-client.c sftp-client.h sftp-glob.c sftp-glob.h sftp.h]
35 [sftp-int.c sftp-int.h]
36 API cleanup and backwards compat for filexfer v.0 servers; ok markus@
33 37
3420020210 3820020210
35 - (djm) OpenBSD CVS Sync 39 - (djm) OpenBSD CVS Sync
@@ -7577,4 +7581,4 @@
7577 - Wrote replacements for strlcpy and mkdtemp 7581 - Wrote replacements for strlcpy and mkdtemp
7578 - Released 1.0pre1 7582 - Released 1.0pre1
7579 7583
7580$Id: ChangeLog,v 1.1847 2002/02/13 03:05:23 djm Exp $ 7584$Id: ChangeLog,v 1.1848 2002/02/13 03:10:32 djm Exp $
diff --git a/sftp-client.c b/sftp-client.c
index cb11fd581..481341c66 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2001-2002 Damien Miller. All rights reserved. 2 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
@@ -24,11 +24,11 @@
24 24
25/* XXX: memleaks */ 25/* XXX: memleaks */
26/* XXX: signed vs unsigned */ 26/* XXX: signed vs unsigned */
27/* XXX: we use fatal too much, error may be more appropriate in places */ 27/* XXX: remove all logging, only return status codes */
28/* XXX: copy between two remote sites */ 28/* XXX: copy between two remote sites */
29 29
30#include "includes.h" 30#include "includes.h"
31RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $"); 31RCSID("$OpenBSD: sftp-client.c,v 1.23 2002/02/13 00:59:23 djm Exp $");
32 32
33#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H) 33#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H)
34#include <sys/queue.h> 34#include <sys/queue.h>
@@ -50,8 +50,14 @@ RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $");
50/* Minimum amount of data to read at at time */ 50/* Minimum amount of data to read at at time */
51#define MIN_READ_SIZE 512 51#define MIN_READ_SIZE 512
52 52
53/* Message ID */ 53struct sftp_conn {
54static u_int msg_id = 1; 54 int fd_in;
55 int fd_out;
56 u_int transfer_buflen;
57 u_int num_requests;
58 u_int version;
59 u_int msg_id;
60};
55 61
56static void 62static void
57send_msg(int fd, Buffer *m) 63send_msg(int fd, Buffer *m)
@@ -219,11 +225,12 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
219 return(a); 225 return(a);
220} 226}
221 227
222int 228struct sftp_conn *
223do_init(int fd_in, int fd_out) 229do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
224{ 230{
225 int type, version; 231 int type, version;
226 Buffer msg; 232 Buffer msg;
233 struct sftp_conn *ret;
227 234
228 buffer_init(&msg); 235 buffer_init(&msg);
229 buffer_put_char(&msg, SSH2_FXP_INIT); 236 buffer_put_char(&msg, SSH2_FXP_INIT);
@@ -239,7 +246,7 @@ do_init(int fd_in, int fd_out)
239 error("Invalid packet back from SSH2_FXP_INIT (type %d)", 246 error("Invalid packet back from SSH2_FXP_INIT (type %d)",
240 type); 247 type);
241 buffer_free(&msg); 248 buffer_free(&msg);
242 return(-1); 249 return(NULL);
243 } 250 }
244 version = buffer_get_int(&msg); 251 version = buffer_get_int(&msg);
245 252
@@ -257,25 +264,43 @@ do_init(int fd_in, int fd_out)
257 264
258 buffer_free(&msg); 265 buffer_free(&msg);
259 266
260 return(version); 267 ret = xmalloc(sizeof(*ret));
268 ret->fd_in = fd_in;
269 ret->fd_out = fd_out;
270 ret->transfer_buflen = transfer_buflen;
271 ret->num_requests = num_requests;
272 ret->version = version;
273 ret->msg_id = 1;
274
275 /* Some filexfer v.0 servers don't support large packets */
276 if (version == 0)
277 ret->transfer_buflen = MAX(ret->transfer_buflen, 20480);
278
279 return(ret);
280}
281
282u_int
283sftp_proto_version(struct sftp_conn *conn)
284{
285 return(conn->version);
261} 286}
262 287
263int 288int
264do_close(int fd_in, int fd_out, char *handle, u_int handle_len) 289do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
265{ 290{
266 u_int id, status; 291 u_int id, status;
267 Buffer msg; 292 Buffer msg;
268 293
269 buffer_init(&msg); 294 buffer_init(&msg);
270 295
271 id = msg_id++; 296 id = conn->msg_id++;
272 buffer_put_char(&msg, SSH2_FXP_CLOSE); 297 buffer_put_char(&msg, SSH2_FXP_CLOSE);
273 buffer_put_int(&msg, id); 298 buffer_put_int(&msg, id);
274 buffer_put_string(&msg, handle, handle_len); 299 buffer_put_string(&msg, handle, handle_len);
275 send_msg(fd_out, &msg); 300 send_msg(conn->fd_out, &msg);
276 debug3("Sent message SSH2_FXP_CLOSE I:%d", id); 301 debug3("Sent message SSH2_FXP_CLOSE I:%d", id);
277 302
278 status = get_status(fd_in, id); 303 status = get_status(conn->fd_in, id);
279 if (status != SSH2_FX_OK) 304 if (status != SSH2_FX_OK)
280 error("Couldn't close file: %s", fx2txt(status)); 305 error("Couldn't close file: %s", fx2txt(status));
281 306
@@ -286,24 +311,24 @@ do_close(int fd_in, int fd_out, char *handle, u_int handle_len)
286 311
287 312
288static int 313static int
289do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, 314do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
290 SFTP_DIRENT ***dir) 315 SFTP_DIRENT ***dir)
291{ 316{
292 Buffer msg; 317 Buffer msg;
293 u_int type, id, handle_len, i, expected_id, ents = 0; 318 u_int type, id, handle_len, i, expected_id, ents = 0;
294 char *handle; 319 char *handle;
295 320
296 id = msg_id++; 321 id = conn->msg_id++;
297 322
298 buffer_init(&msg); 323 buffer_init(&msg);
299 buffer_put_char(&msg, SSH2_FXP_OPENDIR); 324 buffer_put_char(&msg, SSH2_FXP_OPENDIR);
300 buffer_put_int(&msg, id); 325 buffer_put_int(&msg, id);
301 buffer_put_cstring(&msg, path); 326 buffer_put_cstring(&msg, path);
302 send_msg(fd_out, &msg); 327 send_msg(conn->fd_out, &msg);
303 328
304 buffer_clear(&msg); 329 buffer_clear(&msg);
305 330
306 handle = get_handle(fd_in, id, &handle_len); 331 handle = get_handle(conn->fd_in, id, &handle_len);
307 if (handle == NULL) 332 if (handle == NULL)
308 return(-1); 333 return(-1);
309 334
@@ -316,7 +341,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
316 for (;;) { 341 for (;;) {
317 int count; 342 int count;
318 343
319 id = expected_id = msg_id++; 344 id = expected_id = conn->msg_id++;
320 345
321 debug3("Sending SSH2_FXP_READDIR I:%d", id); 346 debug3("Sending SSH2_FXP_READDIR I:%d", id);
322 347
@@ -324,11 +349,11 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
324 buffer_put_char(&msg, SSH2_FXP_READDIR); 349 buffer_put_char(&msg, SSH2_FXP_READDIR);
325 buffer_put_int(&msg, id); 350 buffer_put_int(&msg, id);
326 buffer_put_string(&msg, handle, handle_len); 351 buffer_put_string(&msg, handle, handle_len);
327 send_msg(fd_out, &msg); 352 send_msg(conn->fd_out, &msg);
328 353
329 buffer_clear(&msg); 354 buffer_clear(&msg);
330 355
331 get_msg(fd_in, &msg); 356 get_msg(conn->fd_in, &msg);
332 357
333 type = buffer_get_char(&msg); 358 type = buffer_get_char(&msg);
334 id = buffer_get_int(&msg); 359 id = buffer_get_int(&msg);
@@ -348,7 +373,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
348 } else { 373 } else {
349 error("Couldn't read directory: %s", 374 error("Couldn't read directory: %s",
350 fx2txt(status)); 375 fx2txt(status));
351 do_close(fd_in, fd_out, handle, handle_len); 376 do_close(conn, handle, handle_len);
352 return(status); 377 return(status);
353 } 378 }
354 } else if (type != SSH2_FXP_NAME) 379 } else if (type != SSH2_FXP_NAME)
@@ -386,22 +411,22 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
386 } 411 }
387 412
388 buffer_free(&msg); 413 buffer_free(&msg);
389 do_close(fd_in, fd_out, handle, handle_len); 414 do_close(conn, handle, handle_len);
390 xfree(handle); 415 xfree(handle);
391 416
392 return(0); 417 return(0);
393} 418}
394 419
395int 420int
396do_ls(int fd_in, int fd_out, char *path) 421do_ls(struct sftp_conn *conn, char *path)
397{ 422{
398 return(do_lsreaddir(fd_in, fd_out, path, 1, NULL)); 423 return(do_lsreaddir(conn, path, 1, NULL));
399} 424}
400 425
401int 426int
402do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir) 427do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
403{ 428{
404 return(do_lsreaddir(fd_in, fd_out, path, 0, dir)); 429 return(do_lsreaddir(conn, path, 0, dir));
405} 430}
406 431
407void free_sftp_dirents(SFTP_DIRENT **s) 432void free_sftp_dirents(SFTP_DIRENT **s)
@@ -417,30 +442,31 @@ void free_sftp_dirents(SFTP_DIRENT **s)
417} 442}
418 443
419int 444int
420do_rm(int fd_in, int fd_out, char *path) 445do_rm(struct sftp_conn *conn, char *path)
421{ 446{
422 u_int status, id; 447 u_int status, id;
423 448
424 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 449 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
425 450
426 id = msg_id++; 451 id = conn->msg_id++;
427 send_string_request(fd_out, id, SSH2_FXP_REMOVE, path, strlen(path)); 452 send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
428 status = get_status(fd_in, id); 453 strlen(path));
454 status = get_status(conn->fd_in, id);
429 if (status != SSH2_FX_OK) 455 if (status != SSH2_FX_OK)
430 error("Couldn't delete file: %s", fx2txt(status)); 456 error("Couldn't delete file: %s", fx2txt(status));
431 return(status); 457 return(status);
432} 458}
433 459
434int 460int
435do_mkdir(int fd_in, int fd_out, char *path, Attrib *a) 461do_mkdir(struct sftp_conn *conn, char *path, Attrib *a)
436{ 462{
437 u_int status, id; 463 u_int status, id;
438 464
439 id = msg_id++; 465 id = conn->msg_id++;
440 send_string_attrs_request(fd_out, id, SSH2_FXP_MKDIR, path, 466 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path,
441 strlen(path), a); 467 strlen(path), a);
442 468
443 status = get_status(fd_in, id); 469 status = get_status(conn->fd_in, id);
444 if (status != SSH2_FX_OK) 470 if (status != SSH2_FX_OK)
445 error("Couldn't create directory: %s", fx2txt(status)); 471 error("Couldn't create directory: %s", fx2txt(status));
446 472
@@ -448,14 +474,15 @@ do_mkdir(int fd_in, int fd_out, char *path, Attrib *a)
448} 474}
449 475
450int 476int
451do_rmdir(int fd_in, int fd_out, char *path) 477do_rmdir(struct sftp_conn *conn, char *path)
452{ 478{
453 u_int status, id; 479 u_int status, id;
454 480
455 id = msg_id++; 481 id = conn->msg_id++;
456 send_string_request(fd_out, id, SSH2_FXP_RMDIR, path, strlen(path)); 482 send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path,
483 strlen(path));
457 484
458 status = get_status(fd_in, id); 485 status = get_status(conn->fd_in, id);
459 if (status != SSH2_FX_OK) 486 if (status != SSH2_FX_OK)
460 error("Couldn't remove directory: %s", fx2txt(status)); 487 error("Couldn't remove directory: %s", fx2txt(status));
461 488
@@ -463,45 +490,61 @@ do_rmdir(int fd_in, int fd_out, char *path)
463} 490}
464 491
465Attrib * 492Attrib *
466do_stat(int fd_in, int fd_out, char *path, int quiet) 493do_stat(struct sftp_conn *conn, char *path, int quiet)
467{ 494{
468 u_int id; 495 u_int id;
469 496
470 id = msg_id++; 497 id = conn->msg_id++;
471 send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path)); 498
472 return(get_decode_stat(fd_in, id, quiet)); 499 send_string_request(conn->fd_out, id,
500 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
501 path, strlen(path));
502
503 return(get_decode_stat(conn->fd_in, id, quiet));
473} 504}
474 505
475Attrib * 506Attrib *
476do_lstat(int fd_in, int fd_out, char *path, int quiet) 507do_lstat(struct sftp_conn *conn, char *path, int quiet)
477{ 508{
478 u_int id; 509 u_int id;
479 510
480 id = msg_id++; 511 if (conn->version == 0) {
481 send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path)); 512 if (quiet)
482 return(get_decode_stat(fd_in, id, quiet)); 513 debug("Server version does not support lstat operation");
514 else
515 error("Server version does not support lstat operation");
516 return(NULL);
517 }
518
519 id = conn->msg_id++;
520 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
521 strlen(path));
522
523 return(get_decode_stat(conn->fd_in, id, quiet));
483} 524}
484 525
485Attrib * 526Attrib *
486do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet) 527do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
487{ 528{
488 u_int id; 529 u_int id;
489 530
490 id = msg_id++; 531 id = conn->msg_id++;
491 send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len); 532 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
492 return(get_decode_stat(fd_in, id, quiet)); 533 handle_len);
534
535 return(get_decode_stat(conn->fd_in, id, quiet));
493} 536}
494 537
495int 538int
496do_setstat(int fd_in, int fd_out, char *path, Attrib *a) 539do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
497{ 540{
498 u_int status, id; 541 u_int status, id;
499 542
500 id = msg_id++; 543 id = conn->msg_id++;
501 send_string_attrs_request(fd_out, id, SSH2_FXP_SETSTAT, path, 544 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,
502 strlen(path), a); 545 strlen(path), a);
503 546
504 status = get_status(fd_in, id); 547 status = get_status(conn->fd_in, id);
505 if (status != SSH2_FX_OK) 548 if (status != SSH2_FX_OK)
506 error("Couldn't setstat on \"%s\": %s", path, 549 error("Couldn't setstat on \"%s\": %s", path,
507 fx2txt(status)); 550 fx2txt(status));
@@ -510,16 +553,16 @@ do_setstat(int fd_in, int fd_out, char *path, Attrib *a)
510} 553}
511 554
512int 555int
513do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len, 556do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
514 Attrib *a) 557 Attrib *a)
515{ 558{
516 u_int status, id; 559 u_int status, id;
517 560
518 id = msg_id++; 561 id = conn->msg_id++;
519 send_string_attrs_request(fd_out, id, SSH2_FXP_FSETSTAT, handle, 562 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle,
520 handle_len, a); 563 handle_len, a);
521 564
522 status = get_status(fd_in, id); 565 status = get_status(conn->fd_in, id);
523 if (status != SSH2_FX_OK) 566 if (status != SSH2_FX_OK)
524 error("Couldn't fsetstat: %s", fx2txt(status)); 567 error("Couldn't fsetstat: %s", fx2txt(status));
525 568
@@ -527,19 +570,20 @@ do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len,
527} 570}
528 571
529char * 572char *
530do_realpath(int fd_in, int fd_out, char *path) 573do_realpath(struct sftp_conn *conn, char *path)
531{ 574{
532 Buffer msg; 575 Buffer msg;
533 u_int type, expected_id, count, id; 576 u_int type, expected_id, count, id;
534 char *filename, *longname; 577 char *filename, *longname;
535 Attrib *a; 578 Attrib *a;
536 579
537 expected_id = id = msg_id++; 580 expected_id = id = conn->msg_id++;
538 send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path)); 581 send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
582 strlen(path));
539 583
540 buffer_init(&msg); 584 buffer_init(&msg);
541 585
542 get_msg(fd_in, &msg); 586 get_msg(conn->fd_in, &msg);
543 type = buffer_get_char(&msg); 587 type = buffer_get_char(&msg);
544 id = buffer_get_int(&msg); 588 id = buffer_get_int(&msg);
545 589
@@ -573,7 +617,7 @@ do_realpath(int fd_in, int fd_out, char *path)
573} 617}
574 618
575int 619int
576do_rename(int fd_in, int fd_out, char *oldpath, char *newpath) 620do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
577{ 621{
578 Buffer msg; 622 Buffer msg;
579 u_int status, id; 623 u_int status, id;
@@ -581,65 +625,71 @@ do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)
581 buffer_init(&msg); 625 buffer_init(&msg);
582 626
583 /* Send rename request */ 627 /* Send rename request */
584 id = msg_id++; 628 id = conn->msg_id++;
585 buffer_put_char(&msg, SSH2_FXP_RENAME); 629 buffer_put_char(&msg, SSH2_FXP_RENAME);
586 buffer_put_int(&msg, id); 630 buffer_put_int(&msg, id);
587 buffer_put_cstring(&msg, oldpath); 631 buffer_put_cstring(&msg, oldpath);
588 buffer_put_cstring(&msg, newpath); 632 buffer_put_cstring(&msg, newpath);
589 send_msg(fd_out, &msg); 633 send_msg(conn->fd_out, &msg);
590 debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath, 634 debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,
591 newpath); 635 newpath);
592 buffer_free(&msg); 636 buffer_free(&msg);
593 637
594 status = get_status(fd_in, id); 638 status = get_status(conn->fd_in, id);
595 if (status != SSH2_FX_OK) 639 if (status != SSH2_FX_OK)
596 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, 640 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
597 fx2txt(status)); 641 newpath, fx2txt(status));
598 642
599 return(status); 643 return(status);
600} 644}
601 645
602int 646int
603do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath) 647do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
604{ 648{
605 Buffer msg; 649 Buffer msg;
606 u_int status, id; 650 u_int status, id;
607 651
652 if (conn->version < 3) {
653 error("This server does not support the symlink operation");
654 return(SSH2_FX_OP_UNSUPPORTED);
655 }
656
608 buffer_init(&msg); 657 buffer_init(&msg);
609 658
610 /* Send rename request */ 659 /* Send rename request */
611 id = msg_id++; 660 id = conn->msg_id++;
612 buffer_put_char(&msg, SSH2_FXP_SYMLINK); 661 buffer_put_char(&msg, SSH2_FXP_SYMLINK);
613 buffer_put_int(&msg, id); 662 buffer_put_int(&msg, id);
614 buffer_put_cstring(&msg, oldpath); 663 buffer_put_cstring(&msg, oldpath);
615 buffer_put_cstring(&msg, newpath); 664 buffer_put_cstring(&msg, newpath);
616 send_msg(fd_out, &msg); 665 send_msg(conn->fd_out, &msg);
617 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 666 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
618 newpath); 667 newpath);
619 buffer_free(&msg); 668 buffer_free(&msg);
620 669
621 status = get_status(fd_in, id); 670 status = get_status(conn->fd_in, id);
622 if (status != SSH2_FX_OK) 671 if (status != SSH2_FX_OK)
623 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, 672 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
624 fx2txt(status)); 673 newpath, fx2txt(status));
625 674
626 return(status); 675 return(status);
627} 676}
628 677
629char * 678char *
630do_readlink(int fd_in, int fd_out, char *path) 679do_readlink(struct sftp_conn *conn, char *path)
631{ 680{
632 Buffer msg; 681 Buffer msg;
633 u_int type, expected_id, count, id; 682 u_int type, expected_id, count, id;
634 char *filename, *longname; 683 char *filename, *longname;
635 Attrib *a; 684 Attrib *a;
636 685
637 expected_id = id = msg_id++; 686 expected_id = id = conn->msg_id++;
638 send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path)); 687 send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path,
688 strlen(path));
639 689
640 buffer_init(&msg); 690 buffer_init(&msg);
641 691
642 get_msg(fd_in, &msg); 692 get_msg(conn->fd_in, &msg);
643 type = buffer_get_char(&msg); 693 type = buffer_get_char(&msg);
644 id = buffer_get_int(&msg); 694 id = buffer_get_int(&msg);
645 695
@@ -690,8 +740,8 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
690} 740}
691 741
692int 742int
693do_download(int fd_in, int fd_out, char *remote_path, char *local_path, 743do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
694 int pflag, size_t buflen, int num_requests) 744 int pflag)
695{ 745{
696 Attrib junk, *a; 746 Attrib junk, *a;
697 Buffer msg; 747 Buffer msg;
@@ -699,7 +749,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
699 int local_fd, status, num_req, max_req, write_error; 749 int local_fd, status, num_req, max_req, write_error;
700 int read_error, write_errno; 750 int read_error, write_errno;
701 u_int64_t offset, size; 751 u_int64_t offset, size;
702 u_int handle_len, mode, type, id; 752 u_int handle_len, mode, type, id, buflen;
703 struct request { 753 struct request {
704 u_int id; 754 u_int id;
705 u_int len; 755 u_int len;
@@ -711,7 +761,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
711 761
712 TAILQ_INIT(&requests); 762 TAILQ_INIT(&requests);
713 763
714 a = do_stat(fd_in, fd_out, remote_path, 0); 764 a = do_stat(conn, remote_path, 0);
715 if (a == NULL) 765 if (a == NULL)
716 return(-1); 766 return(-1);
717 767
@@ -732,33 +782,34 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
732 else 782 else
733 size = 0; 783 size = 0;
734 784
735 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); 785 buflen = conn->transfer_buflen;
736 if (local_fd == -1) {
737 error("Couldn't open local file \"%s\" for writing: %s",
738 local_path, strerror(errno));
739 return(-1);
740 }
741
742 buffer_init(&msg); 786 buffer_init(&msg);
743 787
744 /* Send open request */ 788 /* Send open request */
745 id = msg_id++; 789 id = conn->msg_id++;
746 buffer_put_char(&msg, SSH2_FXP_OPEN); 790 buffer_put_char(&msg, SSH2_FXP_OPEN);
747 buffer_put_int(&msg, id); 791 buffer_put_int(&msg, id);
748 buffer_put_cstring(&msg, remote_path); 792 buffer_put_cstring(&msg, remote_path);
749 buffer_put_int(&msg, SSH2_FXF_READ); 793 buffer_put_int(&msg, SSH2_FXF_READ);
750 attrib_clear(&junk); /* Send empty attributes */ 794 attrib_clear(&junk); /* Send empty attributes */
751 encode_attrib(&msg, &junk); 795 encode_attrib(&msg, &junk);
752 send_msg(fd_out, &msg); 796 send_msg(conn->fd_out, &msg);
753 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); 797 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
754 798
755 handle = get_handle(fd_in, id, &handle_len); 799 handle = get_handle(conn->fd_in, id, &handle_len);
756 if (handle == NULL) { 800 if (handle == NULL) {
757 buffer_free(&msg); 801 buffer_free(&msg);
758 close(local_fd); 802 close(local_fd);
759 return(-1); 803 return(-1);
760 } 804 }
761 805
806 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
807 if (local_fd == -1) {
808 error("Couldn't open local file \"%s\" for writing: %s",
809 local_path, strerror(errno));
810 return(-1);
811 }
812
762 /* Read from remote and write to local */ 813 /* Read from remote and write to local */
763 write_error = read_error = write_errno = num_req = offset = 0; 814 write_error = read_error = write_errno = num_req = offset = 0;
764 max_req = 1; 815 max_req = 1;
@@ -771,18 +822,18 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
771 debug3("Request range %llu -> %llu (%d/%d)", 822 debug3("Request range %llu -> %llu (%d/%d)",
772 offset, offset + buflen - 1, num_req, max_req); 823 offset, offset + buflen - 1, num_req, max_req);
773 req = xmalloc(sizeof(*req)); 824 req = xmalloc(sizeof(*req));
774 req->id = msg_id++; 825 req->id = conn->msg_id++;
775 req->len = buflen; 826 req->len = buflen;
776 req->offset = offset; 827 req->offset = offset;
777 offset += buflen; 828 offset += buflen;
778 num_req++; 829 num_req++;
779 TAILQ_INSERT_TAIL(&requests, req, tq); 830 TAILQ_INSERT_TAIL(&requests, req, tq);
780 send_read_request(fd_out, req->id, req->offset, 831 send_read_request(conn->fd_out, req->id, req->offset,
781 req->len, handle, handle_len); 832 req->len, handle, handle_len);
782 } 833 }
783 834
784 buffer_clear(&msg); 835 buffer_clear(&msg);
785 get_msg(fd_in, &msg); 836 get_msg(conn->fd_in, &msg);
786 type = buffer_get_char(&msg); 837 type = buffer_get_char(&msg);
787 id = buffer_get_int(&msg); 838 id = buffer_get_int(&msg);
788 debug3("Received reply T:%d I:%d R:%d", type, id, max_req); 839 debug3("Received reply T:%d I:%d R:%d", type, id, max_req);
@@ -830,12 +881,11 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
830 debug3("Short data block, re-requesting " 881 debug3("Short data block, re-requesting "
831 "%llu -> %llu (%2d)", req->offset + len, 882 "%llu -> %llu (%2d)", req->offset + len,
832 req->offset + req->len - 1, num_req); 883 req->offset + req->len - 1, num_req);
833 req->id = msg_id++; 884 req->id = conn->msg_id++;
834 req->len -= len; 885 req->len -= len;
835 req->offset += len; 886 req->offset += len;
836 send_read_request(fd_out, req->id, 887 send_read_request(conn->fd_out, req->id,
837 req->offset, req->len, handle, 888 req->offset, req->len, handle, handle_len);
838 handle_len);
839 /* Reduce the request size */ 889 /* Reduce the request size */
840 if (len < buflen) 890 if (len < buflen)
841 buflen = MAX(MIN_READ_SIZE, len); 891 buflen = MAX(MIN_READ_SIZE, len);
@@ -848,7 +898,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
848 offset, num_req); 898 offset, num_req);
849 max_req = 1; 899 max_req = 1;
850 } 900 }
851 else if (max_req < num_requests + 1) { 901 else if (max_req < conn->num_requests + 1) {
852 ++max_req; 902 ++max_req;
853 } 903 }
854 } 904 }
@@ -864,17 +914,16 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
864 fatal("Transfer complete, but requests still in queue"); 914 fatal("Transfer complete, but requests still in queue");
865 915
866 if (read_error) { 916 if (read_error) {
867 error("Couldn't read from remote " 917 error("Couldn't read from remote file \"%s\" : %s",
868 "file \"%s\" : %s", remote_path, 918 remote_path, fx2txt(status));
869 fx2txt(status)); 919 do_close(conn, handle, handle_len);
870 do_close(fd_in, fd_out, handle, handle_len);
871 } else if (write_error) { 920 } else if (write_error) {
872 error("Couldn't write to \"%s\": %s", local_path, 921 error("Couldn't write to \"%s\": %s", local_path,
873 strerror(write_errno)); 922 strerror(write_errno));
874 status = -1; 923 status = -1;
875 do_close(fd_in, fd_out, handle, handle_len); 924 do_close(conn, handle, handle_len);
876 } else { 925 } else {
877 status = do_close(fd_in, fd_out, handle, handle_len); 926 status = do_close(conn, handle, handle_len);
878 927
879 /* Override umask and utimes if asked */ 928 /* Override umask and utimes if asked */
880#ifdef HAVE_FCHMOD 929#ifdef HAVE_FCHMOD
@@ -897,12 +946,13 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
897 close(local_fd); 946 close(local_fd);
898 buffer_free(&msg); 947 buffer_free(&msg);
899 xfree(handle); 948 xfree(handle);
900 return status; 949
950 return(status);
901} 951}
902 952
903int 953int
904do_upload(int fd_in, int fd_out, char *local_path, char *remote_path, 954do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
905 int pflag, size_t buflen, int num_requests) 955 int pflag)
906{ 956{
907 int local_fd, status; 957 int local_fd, status;
908 u_int handle_len, id, type; 958 u_int handle_len, id, type;
@@ -946,18 +996,18 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
946 buffer_init(&msg); 996 buffer_init(&msg);
947 997
948 /* Send open request */ 998 /* Send open request */
949 id = msg_id++; 999 id = conn->msg_id++;
950 buffer_put_char(&msg, SSH2_FXP_OPEN); 1000 buffer_put_char(&msg, SSH2_FXP_OPEN);
951 buffer_put_int(&msg, id); 1001 buffer_put_int(&msg, id);
952 buffer_put_cstring(&msg, remote_path); 1002 buffer_put_cstring(&msg, remote_path);
953 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1003 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
954 encode_attrib(&msg, &a); 1004 encode_attrib(&msg, &a);
955 send_msg(fd_out, &msg); 1005 send_msg(conn->fd_out, &msg);
956 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); 1006 debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
957 1007
958 buffer_clear(&msg); 1008 buffer_clear(&msg);
959 1009
960 handle = get_handle(fd_in, id, &handle_len); 1010 handle = get_handle(conn->fd_in, id, &handle_len);
961 if (handle == NULL) { 1011 if (handle == NULL) {
962 close(local_fd); 1012 close(local_fd);
963 buffer_free(&msg); 1013 buffer_free(&msg);
@@ -965,7 +1015,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
965 } 1015 }
966 1016
967 startid = ackid = id + 1; 1017 startid = ackid = id + 1;
968 data = xmalloc(buflen); 1018 data = xmalloc(conn->transfer_buflen);
969 1019
970 /* Read from local and write to remote */ 1020 /* Read from local and write to remote */
971 offset = 0; 1021 offset = 0;
@@ -977,7 +1027,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
977 * the last block of the file 1027 * the last block of the file
978 */ 1028 */
979 do 1029 do
980 len = read(local_fd, data, buflen); 1030 len = read(local_fd, data, conn->transfer_buflen);
981 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 1031 while ((len == -1) && (errno == EINTR || errno == EAGAIN));
982 1032
983 if (len == -1) 1033 if (len == -1)
@@ -997,7 +1047,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
997 buffer_put_string(&msg, handle, handle_len); 1047 buffer_put_string(&msg, handle, handle_len);
998 buffer_put_int64(&msg, offset); 1048 buffer_put_int64(&msg, offset);
999 buffer_put_string(&msg, data, len); 1049 buffer_put_string(&msg, data, len);
1000 send_msg(fd_out, &msg); 1050 send_msg(conn->fd_out, &msg);
1001 debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", 1051 debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
1002 id, (u_int64_t)offset, len); 1052 id, (u_int64_t)offset, len);
1003 } else if (TAILQ_FIRST(&acks) == NULL) 1053 } else if (TAILQ_FIRST(&acks) == NULL)
@@ -1006,9 +1056,10 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1006 if (ack == NULL) 1056 if (ack == NULL)
1007 fatal("Unexpected ACK %u", id); 1057 fatal("Unexpected ACK %u", id);
1008 1058
1009 if (id == startid || len == 0 || id - ackid >= num_requests) { 1059 if (id == startid || len == 0 ||
1060 id - ackid >= conn->num_requests) {
1010 buffer_clear(&msg); 1061 buffer_clear(&msg);
1011 get_msg(fd_in, &msg); 1062 get_msg(conn->fd_in, &msg);
1012 type = buffer_get_char(&msg); 1063 type = buffer_get_char(&msg);
1013 id = buffer_get_int(&msg); 1064 id = buffer_get_int(&msg);
1014 1065
@@ -1031,7 +1082,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1031 if (status != SSH2_FX_OK) { 1082 if (status != SSH2_FX_OK) {
1032 error("Couldn't write to remote file \"%s\": %s", 1083 error("Couldn't write to remote file \"%s\": %s",
1033 remote_path, fx2txt(status)); 1084 remote_path, fx2txt(status));
1034 do_close(fd_in, fd_out, handle, handle_len); 1085 do_close(conn, handle, handle_len);
1035 close(local_fd); 1086 close(local_fd);
1036 goto done; 1087 goto done;
1037 } 1088 }
@@ -1040,7 +1091,6 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1040 ++ackid; 1091 ++ackid;
1041 free(ack); 1092 free(ack);
1042 } 1093 }
1043
1044 offset += len; 1094 offset += len;
1045 } 1095 }
1046 xfree(data); 1096 xfree(data);
@@ -1048,19 +1098,19 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
1048 if (close(local_fd) == -1) { 1098 if (close(local_fd) == -1) {
1049 error("Couldn't close local file \"%s\": %s", local_path, 1099 error("Couldn't close local file \"%s\": %s", local_path,
1050 strerror(errno)); 1100 strerror(errno));
1051 do_close(fd_in, fd_out, handle, handle_len); 1101 do_close(conn, handle, handle_len);
1052 status = -1; 1102 status = -1;
1053 goto done; 1103 goto done;
1054 } 1104 }
1055 1105
1056 /* Override umask and utimes if asked */ 1106 /* Override umask and utimes if asked */
1057 if (pflag) 1107 if (pflag)
1058 do_fsetstat(fd_in, fd_out, handle, handle_len, &a); 1108 do_fsetstat(conn, handle, handle_len, &a);
1059 1109
1060 status = do_close(fd_in, fd_out, handle, handle_len); 1110 status = do_close(conn, handle, handle_len);
1061 1111
1062done: 1112done:
1063 xfree(handle); 1113 xfree(handle);
1064 buffer_free(&msg); 1114 buffer_free(&msg);
1065 return status; 1115 return(status);
1066} 1116}
diff --git a/sftp-client.h b/sftp-client.h
index 477c8ed3b..ceda879b9 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -1,7 +1,7 @@
1/* $OpenBSD: sftp-client.h,v 1.8 2002/02/12 12:32:27 djm Exp $ */ 1/* $OpenBSD: sftp-client.h,v 1.9 2002/02/13 00:59:23 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2002 Damien Miller. All rights reserved. 4 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
@@ -26,6 +26,9 @@
26 26
27/* Client side of SSH2 filexfer protocol */ 27/* Client side of SSH2 filexfer protocol */
28 28
29#ifndef _SFTP_CLIENT_H
30#define _SFTP_CLIENT_H
31
29typedef struct SFTP_DIRENT SFTP_DIRENT; 32typedef struct SFTP_DIRENT SFTP_DIRENT;
30 33
31struct SFTP_DIRENT { 34struct SFTP_DIRENT {
@@ -38,55 +41,59 @@ struct SFTP_DIRENT {
38 * Initialiase a SSH filexfer connection. Returns -1 on error or 41 * Initialiase a SSH filexfer connection. Returns -1 on error or
39 * protocol version on success. 42 * protocol version on success.
40 */ 43 */
41int do_init(int, int); 44struct sftp_conn *
45do_init(int, int, u_int, u_int);
46
47u_int
48sftp_proto_version(struct sftp_conn *);
42 49
43/* Close file referred to by 'handle' */ 50/* Close file referred to by 'handle' */
44int do_close(int, int, char *, u_int); 51int do_close(struct sftp_conn *, char *, u_int);
45 52
46/* List contents of directory 'path' to stdout */ 53/* List contents of directory 'path' to stdout */
47int do_ls(int, int, char *); 54int do_ls(struct sftp_conn *, char *);
48 55
49/* Read contents of 'path' to NULL-terminated array 'dir' */ 56/* Read contents of 'path' to NULL-terminated array 'dir' */
50int do_readdir(int, int, char *, SFTP_DIRENT ***); 57int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
51 58
52/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ 59/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */
53void free_sftp_dirents(SFTP_DIRENT **); 60void free_sftp_dirents(SFTP_DIRENT **);
54 61
55/* Delete file 'path' */ 62/* Delete file 'path' */
56int do_rm(int, int, char *); 63int do_rm(struct sftp_conn *, char *);
57 64
58/* Create directory 'path' */ 65/* Create directory 'path' */
59int do_mkdir(int, int, char *, Attrib *); 66int do_mkdir(struct sftp_conn *, char *, Attrib *);
60 67
61/* Remove directory 'path' */ 68/* Remove directory 'path' */
62int do_rmdir(int, int, char *); 69int do_rmdir(struct sftp_conn *, char *);
63 70
64/* Get file attributes of 'path' (follows symlinks) */ 71/* Get file attributes of 'path' (follows symlinks) */
65Attrib *do_stat(int, int, char *, int); 72Attrib *do_stat(struct sftp_conn *, char *, int);
66 73
67/* Get file attributes of 'path' (does not follow symlinks) */ 74/* Get file attributes of 'path' (does not follow symlinks) */
68Attrib *do_lstat(int, int, char *, int); 75Attrib *do_lstat(struct sftp_conn *, char *, int);
69 76
70/* Get file attributes of open file 'handle' */ 77/* Get file attributes of open file 'handle' */
71Attrib *do_fstat(int, int, char *, u_int, int); 78Attrib *do_fstat(struct sftp_conn *, char *, u_int, int);
72 79
73/* Set file attributes of 'path' */ 80/* Set file attributes of 'path' */
74int do_setstat(int, int, char *, Attrib *); 81int do_setstat(struct sftp_conn *, char *, Attrib *);
75 82
76/* Set file attributes of open file 'handle' */ 83/* Set file attributes of open file 'handle' */
77int do_fsetstat(int, int, char *, u_int, Attrib *); 84int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
78 85
79/* Canonicalise 'path' - caller must free result */ 86/* Canonicalise 'path' - caller must free result */
80char *do_realpath(int, int, char *); 87char *do_realpath(struct sftp_conn *, char *);
81 88
82/* Rename 'oldpath' to 'newpath' */ 89/* Rename 'oldpath' to 'newpath' */
83int do_rename(int, int, char *, char *); 90int do_rename(struct sftp_conn *, char *, char *);
84 91
85/* Rename 'oldpath' to 'newpath' */ 92/* Rename 'oldpath' to 'newpath' */
86int do_symlink(int, int, char *, char *); 93int do_symlink(struct sftp_conn *, char *, char *);
87 94
88/* Return target of symlink 'path' - caller must free result */ 95/* Return target of symlink 'path' - caller must free result */
89char *do_readlink(int, int, char *); 96char *do_readlink(struct sftp_conn *, char *);
90 97
91/* XXX: add callbacks to do_download/do_upload so we can do progress meter */ 98/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
92 99
@@ -94,10 +101,12 @@ char *do_readlink(int, int, char *);
94 * Download 'remote_path' to 'local_path'. Preserve permissions and times 101 * Download 'remote_path' to 'local_path'. Preserve permissions and times
95 * if 'pflag' is set 102 * if 'pflag' is set
96 */ 103 */
97int do_download(int, int, char *, char *, int, size_t, int); 104int do_download(struct sftp_conn *, char *, char *, int);
98 105
99/* 106/*
100 * Upload 'local_path' to 'remote_path'. Preserve permissions and times 107 * Upload 'local_path' to 'remote_path'. Preserve permissions and times
101 * if 'pflag' is set 108 * if 'pflag' is set
102 */ 109 */
103int do_upload(int, int, char *, char *, int , size_t, int); 110int do_upload(struct sftp_conn *, char *, char *, int);
111
112#endif
diff --git a/sftp-glob.c b/sftp-glob.c
index 849ac65ed..1234074c4 100644
--- a/sftp-glob.c
+++ b/sftp-glob.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2001 Damien Miller. All rights reserved. 2 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sftp-glob.c,v 1.9 2001/12/19 07:18:56 deraadt Exp $"); 26RCSID("$OpenBSD: sftp-glob.c,v 1.10 2002/02/13 00:59:23 djm Exp $");
27 27
28#include "buffer.h" 28#include "buffer.h"
29#include "bufaux.h" 29#include "bufaux.h"
@@ -41,8 +41,7 @@ struct SFTP_OPENDIR {
41}; 41};
42 42
43static struct { 43static struct {
44 int fd_in; 44 struct sftp_conn *conn;
45 int fd_out;
46} cur; 45} cur;
47 46
48static void * 47static void *
@@ -52,7 +51,7 @@ fudge_opendir(const char *path)
52 51
53 r = xmalloc(sizeof(*r)); 52 r = xmalloc(sizeof(*r));
54 53
55 if (do_readdir(cur.fd_in, cur.fd_out, (char*)path, &r->dir)) 54 if (do_readdir(cur.conn, (char*)path, &r->dir))
56 return(NULL); 55 return(NULL);
57 56
58 r->offset = 0; 57 r->offset = 0;
@@ -130,7 +129,7 @@ fudge_lstat(const char *path, struct stat *st)
130{ 129{
131 Attrib *a; 130 Attrib *a;
132 131
133 if (!(a = do_lstat(cur.fd_in, cur.fd_out, (char*)path, 0))) 132 if (!(a = do_lstat(cur.conn, (char*)path, 0)))
134 return(-1); 133 return(-1);
135 134
136 attrib_to_stat(a, st); 135 attrib_to_stat(a, st);
@@ -143,7 +142,7 @@ fudge_stat(const char *path, struct stat *st)
143{ 142{
144 Attrib *a; 143 Attrib *a;
145 144
146 if (!(a = do_stat(cur.fd_in, cur.fd_out, (char*)path, 0))) 145 if (!(a = do_stat(cur.conn, (char*)path, 0)))
147 return(-1); 146 return(-1);
148 147
149 attrib_to_stat(a, st); 148 attrib_to_stat(a, st);
@@ -152,7 +151,7 @@ fudge_stat(const char *path, struct stat *st)
152} 151}
153 152
154int 153int
155remote_glob(int fd_in, int fd_out, const char *pattern, int flags, 154remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
156 int (*errfunc)(const char *, int), glob_t *pglob) 155 int (*errfunc)(const char *, int), glob_t *pglob)
157{ 156{
158 pglob->gl_opendir = fudge_opendir; 157 pglob->gl_opendir = fudge_opendir;
@@ -162,9 +161,7 @@ remote_glob(int fd_in, int fd_out, const char *pattern, int flags,
162 pglob->gl_stat = fudge_stat; 161 pglob->gl_stat = fudge_stat;
163 162
164 memset(&cur, 0, sizeof(cur)); 163 memset(&cur, 0, sizeof(cur));
165 cur.fd_in = fd_in; 164 cur.conn = conn;
166 cur.fd_out = fd_out;
167 165
168 return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, 166 return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
169 pglob));
170} 167}
diff --git a/sftp-glob.h b/sftp-glob.h
index 2885044ae..488b0a80b 100644
--- a/sftp-glob.h
+++ b/sftp-glob.h
@@ -1,7 +1,7 @@
1/* $OpenBSD: sftp-glob.h,v 1.5 2001/06/26 17:27:24 markus Exp $ */ 1/* $OpenBSD: sftp-glob.h,v 1.6 2002/02/13 00:59:23 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Damien Miller. All rights reserved. 4 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
@@ -26,5 +26,13 @@
26 26
27/* Remote sftp filename globbing */ 27/* Remote sftp filename globbing */
28 28
29#ifndef _SFTP_GLOB_H
30#define _SFTP_GLOB_H
31
32#include "sftp-client.h"
33
29int 34int
30remote_glob(int, int, const char *, int, int (*)(const char *, int), glob_t *); 35remote_glob(struct sftp_conn *, const char *, int,
36 int (*)(const char *, int), glob_t *);
37
38#endif
diff --git a/sftp-int.c b/sftp-int.c
index babc0ed60..5de93891a 100644
--- a/sftp-int.c
+++ b/sftp-int.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2001 Damien Miller. All rights reserved. 2 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
@@ -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.43 2002/02/12 12:32:27 djm Exp $"); 29RCSID("$OpenBSD: sftp-int.c,v 1.44 2002/02/13 00:59:23 djm Exp $");
30 30
31#include "buffer.h" 31#include "buffer.h"
32#include "xmalloc.h" 32#include "xmalloc.h"
@@ -48,9 +48,6 @@ extern size_t copy_buffer_len;
48/* Number of concurrent outstanding requests */ 48/* Number of concurrent outstanding requests */
49extern int num_requests; 49extern int num_requests;
50 50
51/* Version of server we are speaking to */
52int version;
53
54/* Seperators for interactive commands */ 51/* Seperators for interactive commands */
55#define WHITESPACE " \t\r\n" 52#define WHITESPACE " \t\r\n"
56 53
@@ -336,12 +333,12 @@ is_dir(char *path)
336} 333}
337 334
338static int 335static int
339remote_is_dir(int in, int out, char *path) 336remote_is_dir(struct sftp_conn *conn, char *path)
340{ 337{
341 Attrib *a; 338 Attrib *a;
342 339
343 /* XXX: report errors? */ 340 /* XXX: report errors? */
344 if ((a = do_stat(in, out, path, 1)) == NULL) 341 if ((a = do_stat(conn, path, 1)) == NULL)
345 return(0); 342 return(0);
346 if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) 343 if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
347 return(0); 344 return(0);
@@ -349,7 +346,7 @@ remote_is_dir(int in, int out, char *path)
349} 346}
350 347
351static int 348static int
352process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) 349process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
353{ 350{
354 char *abs_src = NULL; 351 char *abs_src = NULL;
355 char *abs_dst = NULL; 352 char *abs_dst = NULL;
@@ -363,7 +360,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
363 360
364 memset(&g, 0, sizeof(g)); 361 memset(&g, 0, sizeof(g));
365 debug3("Looking up %s", abs_src); 362 debug3("Looking up %s", abs_src);
366 if (remote_glob(in, out, abs_src, 0, NULL, &g)) { 363 if (remote_glob(conn, abs_src, 0, NULL, &g)) {
367 error("File \"%s\" not found.", abs_src); 364 error("File \"%s\" not found.", abs_src);
368 err = -1; 365 err = -1;
369 goto out; 366 goto out;
@@ -387,8 +384,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
387 goto out; 384 goto out;
388 } 385 }
389 printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst); 386 printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst);
390 err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag, 387 err = do_download(conn, g.gl_pathv[0], abs_dst, pflag);
391 copy_buffer_len, num_requests);
392 goto out; 388 goto out;
393 } 389 }
394 390
@@ -412,8 +408,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
412 abs_dst = tmp; 408 abs_dst = tmp;
413 409
414 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); 410 printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
415 if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag, 411 if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
416 copy_buffer_len, num_requests) == -1)
417 err = -1; 412 err = -1;
418 xfree(abs_dst); 413 xfree(abs_dst);
419 abs_dst = NULL; 414 abs_dst = NULL;
@@ -428,7 +423,7 @@ out:
428} 423}
429 424
430static int 425static int
431process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) 426process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
432{ 427{
433 char *tmp_dst = NULL; 428 char *tmp_dst = NULL;
434 char *abs_dst = NULL; 429 char *abs_dst = NULL;
@@ -454,7 +449,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
454 if (g.gl_pathv[0] && g.gl_matchc == 1) { 449 if (g.gl_pathv[0] && g.gl_matchc == 1) {
455 if (tmp_dst) { 450 if (tmp_dst) {
456 /* If directory specified, append filename */ 451 /* If directory specified, append filename */
457 if (remote_is_dir(in, out, tmp_dst)) { 452 if (remote_is_dir(conn, tmp_dst)) {
458 if (infer_path(g.gl_pathv[0], &tmp)) { 453 if (infer_path(g.gl_pathv[0], &tmp)) {
459 err = 1; 454 err = 1;
460 goto out; 455 goto out;
@@ -471,13 +466,12 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
471 abs_dst = make_absolute(abs_dst, pwd); 466 abs_dst = make_absolute(abs_dst, pwd);
472 } 467 }
473 printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst); 468 printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst);
474 err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag, 469 err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag);
475 copy_buffer_len, num_requests);
476 goto out; 470 goto out;
477 } 471 }
478 472
479 /* Multiple matches, dst may be directory or unspecified */ 473 /* Multiple matches, dst may be directory or unspecified */
480 if (tmp_dst && !remote_is_dir(in, out, tmp_dst)) { 474 if (tmp_dst && !remote_is_dir(conn, tmp_dst)) {
481 error("Multiple files match, but \"%s\" is not a directory", 475 error("Multiple files match, but \"%s\" is not a directory",
482 tmp_dst); 476 tmp_dst);
483 err = -1; 477 err = -1;
@@ -496,8 +490,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
496 abs_dst = make_absolute(tmp, pwd); 490 abs_dst = make_absolute(tmp, pwd);
497 491
498 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 492 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
499 if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag, 493 if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
500 copy_buffer_len, num_requests) == -1)
501 err = -1; 494 err = -1;
502 } 495 }
503 496
@@ -655,7 +648,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
655} 648}
656 649
657static int 650static int
658parse_dispatch_command(int in, int out, const char *cmd, char **pwd) 651parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
659{ 652{
660 char *path1, *path2, *tmp; 653 char *path1, *path2, *tmp;
661 int pflag, cmdnum, i; 654 int pflag, cmdnum, i;
@@ -675,32 +668,26 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
675 case -1: 668 case -1:
676 break; 669 break;
677 case I_GET: 670 case I_GET:
678 err = process_get(in, out, path1, path2, *pwd, pflag); 671 err = process_get(conn, path1, path2, *pwd, pflag);
679 break; 672 break;
680 case I_PUT: 673 case I_PUT:
681 err = process_put(in, out, path1, path2, *pwd, pflag); 674 err = process_put(conn, path1, path2, *pwd, pflag);
682 break; 675 break;
683 case I_RENAME: 676 case I_RENAME:
684 path1 = make_absolute(path1, *pwd); 677 path1 = make_absolute(path1, *pwd);
685 path2 = make_absolute(path2, *pwd); 678 path2 = make_absolute(path2, *pwd);
686 err = do_rename(in, out, path1, path2); 679 err = do_rename(conn, path1, path2);
687 break; 680 break;
688 case I_SYMLINK: 681 case I_SYMLINK:
689 if (version < 3) { 682 path2 = make_absolute(path2, *pwd);
690 error("The server (version %d) does not support " 683 err = do_symlink(conn, path1, path2);
691 "this operation", version);
692 err = -1;
693 } else {
694 path2 = make_absolute(path2, *pwd);
695 err = do_symlink(in, out, path1, path2);
696 }
697 break; 684 break;
698 case I_RM: 685 case I_RM:
699 path1 = make_absolute(path1, *pwd); 686 path1 = make_absolute(path1, *pwd);
700 remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); 687 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
701 for (i = 0; g.gl_pathv[i]; i++) { 688 for (i = 0; g.gl_pathv[i]; i++) {
702 printf("Removing %s\n", g.gl_pathv[i]); 689 printf("Removing %s\n", g.gl_pathv[i]);
703 if (do_rm(in, out, g.gl_pathv[i]) == -1) 690 if (do_rm(conn, g.gl_pathv[i]) == -1)
704 err = -1; 691 err = -1;
705 } 692 }
706 break; 693 break;
@@ -709,19 +696,19 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
709 attrib_clear(&a); 696 attrib_clear(&a);
710 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 697 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
711 a.perm = 0777; 698 a.perm = 0777;
712 err = do_mkdir(in, out, path1, &a); 699 err = do_mkdir(conn, path1, &a);
713 break; 700 break;
714 case I_RMDIR: 701 case I_RMDIR:
715 path1 = make_absolute(path1, *pwd); 702 path1 = make_absolute(path1, *pwd);
716 err = do_rmdir(in, out, path1); 703 err = do_rmdir(conn, path1);
717 break; 704 break;
718 case I_CHDIR: 705 case I_CHDIR:
719 path1 = make_absolute(path1, *pwd); 706 path1 = make_absolute(path1, *pwd);
720 if ((tmp = do_realpath(in, out, path1)) == NULL) { 707 if ((tmp = do_realpath(conn, path1)) == NULL) {
721 err = 1; 708 err = 1;
722 break; 709 break;
723 } 710 }
724 if ((aa = do_stat(in, out, tmp, 0)) == NULL) { 711 if ((aa = do_stat(conn, tmp, 0)) == NULL) {
725 xfree(tmp); 712 xfree(tmp);
726 err = 1; 713 err = 1;
727 break; 714 break;
@@ -744,22 +731,22 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
744 break; 731 break;
745 case I_LS: 732 case I_LS:
746 if (!path1) { 733 if (!path1) {
747 do_ls(in, out, *pwd); 734 do_ls(conn, *pwd);
748 break; 735 break;
749 } 736 }
750 path1 = make_absolute(path1, *pwd); 737 path1 = make_absolute(path1, *pwd);
751 if ((tmp = do_realpath(in, out, path1)) == NULL) 738 if ((tmp = do_realpath(conn, path1)) == NULL)
752 break; 739 break;
753 xfree(path1); 740 xfree(path1);
754 path1 = tmp; 741 path1 = tmp;
755 if ((aa = do_stat(in, out, path1, 0)) == NULL) 742 if ((aa = do_stat(conn, path1, 0)) == NULL)
756 break; 743 break;
757 if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 744 if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
758 !S_ISDIR(aa->perm)) { 745 !S_ISDIR(aa->perm)) {
759 error("Can't ls: \"%s\" is not a directory", path1); 746 error("Can't ls: \"%s\" is not a directory", path1);
760 break; 747 break;
761 } 748 }
762 do_ls(in, out, path1); 749 do_ls(conn, path1);
763 break; 750 break;
764 case I_LCHDIR: 751 case I_LCHDIR:
765 if (chdir(path1) == -1) { 752 if (chdir(path1) == -1) {
@@ -790,17 +777,17 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
790 attrib_clear(&a); 777 attrib_clear(&a);
791 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 778 a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
792 a.perm = n_arg; 779 a.perm = n_arg;
793 remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); 780 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
794 for (i = 0; g.gl_pathv[i]; i++) { 781 for (i = 0; g.gl_pathv[i]; i++) {
795 printf("Changing mode on %s\n", g.gl_pathv[i]); 782 printf("Changing mode on %s\n", g.gl_pathv[i]);
796 do_setstat(in, out, g.gl_pathv[i], &a); 783 do_setstat(conn, g.gl_pathv[i], &a);
797 } 784 }
798 break; 785 break;
799 case I_CHOWN: 786 case I_CHOWN:
800 path1 = make_absolute(path1, *pwd); 787 path1 = make_absolute(path1, *pwd);
801 remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); 788 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
802 for (i = 0; g.gl_pathv[i]; i++) { 789 for (i = 0; g.gl_pathv[i]; i++) {
803 if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) 790 if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
804 continue; 791 continue;
805 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { 792 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
806 error("Can't get current ownership of " 793 error("Can't get current ownership of "
@@ -810,14 +797,14 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
810 printf("Changing owner on %s\n", g.gl_pathv[i]); 797 printf("Changing owner on %s\n", g.gl_pathv[i]);
811 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; 798 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
812 aa->uid = n_arg; 799 aa->uid = n_arg;
813 do_setstat(in, out, g.gl_pathv[i], aa); 800 do_setstat(conn, g.gl_pathv[i], aa);
814 } 801 }
815 break; 802 break;
816 case I_CHGRP: 803 case I_CHGRP:
817 path1 = make_absolute(path1, *pwd); 804 path1 = make_absolute(path1, *pwd);
818 remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g); 805 remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
819 for (i = 0; g.gl_pathv[i]; i++) { 806 for (i = 0; g.gl_pathv[i]; i++) {
820 if (!(aa = do_stat(in, out, g.gl_pathv[i], 0))) 807 if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
821 continue; 808 continue;
822 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) { 809 if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
823 error("Can't get current ownership of " 810 error("Can't get current ownership of "
@@ -827,7 +814,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
827 printf("Changing group on %s\n", g.gl_pathv[i]); 814 printf("Changing group on %s\n", g.gl_pathv[i]);
828 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID; 815 aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
829 aa->gid = n_arg; 816 aa->gid = n_arg;
830 do_setstat(in, out, g.gl_pathv[i], aa); 817 do_setstat(conn, g.gl_pathv[i], aa);
831 } 818 }
832 break; 819 break;
833 case I_PWD: 820 case I_PWD:
@@ -847,7 +834,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
847 help(); 834 help();
848 break; 835 break;
849 case I_VERSION: 836 case I_VERSION:
850 printf("SFTP protocol version %d\n", version); 837 printf("SFTP protocol version %d\n", sftp_proto_version(conn));
851 break; 838 break;
852 default: 839 default:
853 fatal("%d is not implemented", cmdnum); 840 fatal("%d is not implemented", cmdnum);
@@ -873,12 +860,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
873 char *pwd; 860 char *pwd;
874 char *dir = NULL; 861 char *dir = NULL;
875 char cmd[2048]; 862 char cmd[2048];
863 struct sftp_conn *conn;
876 864
877 version = do_init(fd_in, fd_out); 865 conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
878 if (version == -1) 866 if (conn == NULL)
879 fatal("Couldn't initialise connection to server"); 867 fatal("Couldn't initialise connection to server");
880 868
881 pwd = do_realpath(fd_in, fd_out, "."); 869 pwd = do_realpath(conn, ".");
882 if (pwd == NULL) 870 if (pwd == NULL)
883 fatal("Need cwd"); 871 fatal("Need cwd");
884 872
@@ -886,10 +874,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
886 dir = xstrdup(file1); 874 dir = xstrdup(file1);
887 dir = make_absolute(dir, pwd); 875 dir = make_absolute(dir, pwd);
888 876
889 if (remote_is_dir(fd_in, fd_out, dir) && file2 == NULL) { 877 if (remote_is_dir(conn, dir) && file2 == NULL) {
890 printf("Changing to: %s\n", dir); 878 printf("Changing to: %s\n", dir);
891 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); 879 snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
892 parse_dispatch_command(fd_in, fd_out, cmd, &pwd); 880 parse_dispatch_command(conn, cmd, &pwd);
893 } else { 881 } else {
894 if (file2 == NULL) 882 if (file2 == NULL)
895 snprintf(cmd, sizeof cmd, "get %s", dir); 883 snprintf(cmd, sizeof cmd, "get %s", dir);
@@ -897,7 +885,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
897 snprintf(cmd, sizeof cmd, "get %s %s", dir, 885 snprintf(cmd, sizeof cmd, "get %s %s", dir,
898 file2); 886 file2);
899 887
900 parse_dispatch_command(fd_in, fd_out, cmd, &pwd); 888 parse_dispatch_command(conn, cmd, &pwd);
901 return; 889 return;
902 } 890 }
903 } 891 }
@@ -925,7 +913,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
925 if (cp) 913 if (cp)
926 *cp = '\0'; 914 *cp = '\0';
927 915
928 if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd)) 916 if (parse_dispatch_command(conn, cmd, &pwd))
929 break; 917 break;
930 } 918 }
931 xfree(pwd); 919 xfree(pwd);
diff --git a/sftp-int.h b/sftp-int.h
index 699e758b1..976875812 100644
--- a/sftp-int.h
+++ b/sftp-int.h
@@ -1,7 +1,7 @@
1/* $OpenBSD: sftp-int.h,v 1.4 2001/06/26 17:27:25 markus Exp $ */ 1/* $OpenBSD: sftp-int.h,v 1.5 2002/02/13 00:59:23 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Damien Miller. All rights reserved. 4 * Copyright (c) 2001,2002 Damien Miller. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
diff --git a/sftp.h b/sftp.h
index 2ad95864b..675c6086e 100644
--- a/sftp.h
+++ b/sftp.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */ 1/* $OpenBSD: sftp.h,v 1.4 2002/02/13 00:59:23 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -38,6 +38,7 @@
38#define SSH2_FXP_READ 5 38#define SSH2_FXP_READ 5
39#define SSH2_FXP_WRITE 6 39#define SSH2_FXP_WRITE 6
40#define SSH2_FXP_LSTAT 7 40#define SSH2_FXP_LSTAT 7
41#define SSH2_FXP_STAT_VERSION_0 7
41#define SSH2_FXP_FSTAT 8 42#define SSH2_FXP_FSTAT 8
42#define SSH2_FXP_SETSTAT 9 43#define SSH2_FXP_SETSTAT 9
43#define SSH2_FXP_FSETSTAT 10 44#define SSH2_FXP_FSETSTAT 10