diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | sftp-client.c | 302 | ||||
-rw-r--r-- | sftp-client.h | 49 | ||||
-rw-r--r-- | sftp-glob.c | 21 | ||||
-rw-r--r-- | sftp-glob.h | 14 | ||||
-rw-r--r-- | sftp-int.c | 104 | ||||
-rw-r--r-- | sftp-int.h | 4 | ||||
-rw-r--r-- | sftp.h | 3 |
8 files changed, 280 insertions, 223 deletions
@@ -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 | ||
34 | 20020210 | 38 | 20020210 |
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" |
31 | RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $"); | 31 | RCSID("$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 */ | 53 | struct sftp_conn { |
54 | static 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 | ||
56 | static void | 62 | static void |
57 | send_msg(int fd, Buffer *m) | 63 | send_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 | ||
222 | int | 228 | struct sftp_conn * |
223 | do_init(int fd_in, int fd_out) | 229 | do_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 | |||
282 | u_int | ||
283 | sftp_proto_version(struct sftp_conn *conn) | ||
284 | { | ||
285 | return(conn->version); | ||
261 | } | 286 | } |
262 | 287 | ||
263 | int | 288 | int |
264 | do_close(int fd_in, int fd_out, char *handle, u_int handle_len) | 289 | do_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 | ||
288 | static int | 313 | static int |
289 | do_lsreaddir(int fd_in, int fd_out, char *path, int printflag, | 314 | do_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 | ||
395 | int | 420 | int |
396 | do_ls(int fd_in, int fd_out, char *path) | 421 | do_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 | ||
401 | int | 426 | int |
402 | do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir) | 427 | do_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 | ||
407 | void free_sftp_dirents(SFTP_DIRENT **s) | 432 | void free_sftp_dirents(SFTP_DIRENT **s) |
@@ -417,30 +442,31 @@ void free_sftp_dirents(SFTP_DIRENT **s) | |||
417 | } | 442 | } |
418 | 443 | ||
419 | int | 444 | int |
420 | do_rm(int fd_in, int fd_out, char *path) | 445 | do_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 | ||
434 | int | 460 | int |
435 | do_mkdir(int fd_in, int fd_out, char *path, Attrib *a) | 461 | do_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 | ||
450 | int | 476 | int |
451 | do_rmdir(int fd_in, int fd_out, char *path) | 477 | do_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 | ||
465 | Attrib * | 492 | Attrib * |
466 | do_stat(int fd_in, int fd_out, char *path, int quiet) | 493 | do_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 | ||
475 | Attrib * | 506 | Attrib * |
476 | do_lstat(int fd_in, int fd_out, char *path, int quiet) | 507 | do_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 | ||
485 | Attrib * | 526 | Attrib * |
486 | do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet) | 527 | do_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 | ||
495 | int | 538 | int |
496 | do_setstat(int fd_in, int fd_out, char *path, Attrib *a) | 539 | do_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 | ||
512 | int | 555 | int |
513 | do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len, | 556 | do_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 | ||
529 | char * | 572 | char * |
530 | do_realpath(int fd_in, int fd_out, char *path) | 573 | do_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 | ||
575 | int | 619 | int |
576 | do_rename(int fd_in, int fd_out, char *oldpath, char *newpath) | 620 | do_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 | ||
602 | int | 646 | int |
603 | do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath) | 647 | do_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 | ||
629 | char * | 678 | char * |
630 | do_readlink(int fd_in, int fd_out, char *path) | 679 | do_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 | ||
692 | int | 742 | int |
693 | do_download(int fd_in, int fd_out, char *remote_path, char *local_path, | 743 | do_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 | ||
903 | int | 953 | int |
904 | do_upload(int fd_in, int fd_out, char *local_path, char *remote_path, | 954 | do_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 | ||
1062 | done: | 1112 | done: |
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 | |||
29 | typedef struct SFTP_DIRENT SFTP_DIRENT; | 32 | typedef struct SFTP_DIRENT SFTP_DIRENT; |
30 | 33 | ||
31 | struct SFTP_DIRENT { | 34 | struct 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 | */ |
41 | int do_init(int, int); | 44 | struct sftp_conn * |
45 | do_init(int, int, u_int, u_int); | ||
46 | |||
47 | u_int | ||
48 | sftp_proto_version(struct sftp_conn *); | ||
42 | 49 | ||
43 | /* Close file referred to by 'handle' */ | 50 | /* Close file referred to by 'handle' */ |
44 | int do_close(int, int, char *, u_int); | 51 | int 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 */ |
47 | int do_ls(int, int, char *); | 54 | int 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' */ |
50 | int do_readdir(int, int, char *, SFTP_DIRENT ***); | 57 | int 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) */ |
53 | void free_sftp_dirents(SFTP_DIRENT **); | 60 | void free_sftp_dirents(SFTP_DIRENT **); |
54 | 61 | ||
55 | /* Delete file 'path' */ | 62 | /* Delete file 'path' */ |
56 | int do_rm(int, int, char *); | 63 | int do_rm(struct sftp_conn *, char *); |
57 | 64 | ||
58 | /* Create directory 'path' */ | 65 | /* Create directory 'path' */ |
59 | int do_mkdir(int, int, char *, Attrib *); | 66 | int do_mkdir(struct sftp_conn *, char *, Attrib *); |
60 | 67 | ||
61 | /* Remove directory 'path' */ | 68 | /* Remove directory 'path' */ |
62 | int do_rmdir(int, int, char *); | 69 | int do_rmdir(struct sftp_conn *, char *); |
63 | 70 | ||
64 | /* Get file attributes of 'path' (follows symlinks) */ | 71 | /* Get file attributes of 'path' (follows symlinks) */ |
65 | Attrib *do_stat(int, int, char *, int); | 72 | Attrib *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) */ |
68 | Attrib *do_lstat(int, int, char *, int); | 75 | Attrib *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' */ |
71 | Attrib *do_fstat(int, int, char *, u_int, int); | 78 | Attrib *do_fstat(struct sftp_conn *, char *, u_int, int); |
72 | 79 | ||
73 | /* Set file attributes of 'path' */ | 80 | /* Set file attributes of 'path' */ |
74 | int do_setstat(int, int, char *, Attrib *); | 81 | int 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' */ |
77 | int do_fsetstat(int, int, char *, u_int, Attrib *); | 84 | int 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 */ |
80 | char *do_realpath(int, int, char *); | 87 | char *do_realpath(struct sftp_conn *, char *); |
81 | 88 | ||
82 | /* Rename 'oldpath' to 'newpath' */ | 89 | /* Rename 'oldpath' to 'newpath' */ |
83 | int do_rename(int, int, char *, char *); | 90 | int do_rename(struct sftp_conn *, char *, char *); |
84 | 91 | ||
85 | /* Rename 'oldpath' to 'newpath' */ | 92 | /* Rename 'oldpath' to 'newpath' */ |
86 | int do_symlink(int, int, char *, char *); | 93 | int 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 */ |
89 | char *do_readlink(int, int, char *); | 96 | char *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 | */ |
97 | int do_download(int, int, char *, char *, int, size_t, int); | 104 | int 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 | */ |
103 | int do_upload(int, int, char *, char *, int , size_t, int); | 110 | int 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" |
26 | RCSID("$OpenBSD: sftp-glob.c,v 1.9 2001/12/19 07:18:56 deraadt Exp $"); | 26 | RCSID("$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 | ||
43 | static struct { | 43 | static struct { |
44 | int fd_in; | 44 | struct sftp_conn *conn; |
45 | int fd_out; | ||
46 | } cur; | 45 | } cur; |
47 | 46 | ||
48 | static void * | 47 | static 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 | ||
154 | int | 153 | int |
155 | remote_glob(int fd_in, int fd_out, const char *pattern, int flags, | 154 | remote_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 | |||
29 | int | 34 | int |
30 | remote_glob(int, int, const char *, int, int (*)(const char *, int), glob_t *); | 35 | remote_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" |
29 | RCSID("$OpenBSD: sftp-int.c,v 1.43 2002/02/12 12:32:27 djm Exp $"); | 29 | RCSID("$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 */ |
49 | extern int num_requests; | 49 | extern int num_requests; |
50 | 50 | ||
51 | /* Version of server we are speaking to */ | ||
52 | int 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 | ||
338 | static int | 335 | static int |
339 | remote_is_dir(int in, int out, char *path) | 336 | remote_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 | ||
351 | static int | 348 | static int |
352 | process_get(int in, int out, char *src, char *dst, char *pwd, int pflag) | 349 | process_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 | ||
430 | static int | 425 | static int |
431 | process_put(int in, int out, char *src, char *dst, char *pwd, int pflag) | 426 | process_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 | ||
657 | static int | 650 | static int |
658 | parse_dispatch_command(int in, int out, const char *cmd, char **pwd) | 651 | parse_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 |
@@ -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 |