version 1.44, 2003/06/28 16:23:06 |
version 1.44.2.2, 2004/08/19 22:37:32 |
|
|
/* |
/* |
* Copyright (c) 2001-2003 Damien Miller. All rights reserved. |
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Permission to use, copy, modify, and distribute this software for any |
* modification, are permitted provided that the following conditions |
* purpose with or without fee is hereby granted, provided that the above |
* are met: |
* copyright notice and this permission notice appear in all copies. |
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
*/ |
|
|
/* XXX: memleaks */ |
/* XXX: memleaks */ |
|
|
#include "sftp-common.h" |
#include "sftp-common.h" |
#include "sftp-client.h" |
#include "sftp-client.h" |
|
|
|
extern volatile sig_atomic_t interrupted; |
extern int showprogress; |
extern int showprogress; |
|
|
/* Minimum amount of data to read at at time */ |
/* Minimum amount of data to read at at time */ |
|
|
(*dir)[0] = NULL; |
(*dir)[0] = NULL; |
} |
} |
|
|
for (;;) { |
for (; !interrupted;) { |
int count; |
int count; |
|
|
id = expected_id = conn->msg_id++; |
id = expected_id = conn->msg_id++; |
|
|
do_close(conn, handle, handle_len); |
do_close(conn, handle, handle_len); |
xfree(handle); |
xfree(handle); |
|
|
|
/* Don't return partial matches on interrupt */ |
|
if (interrupted && dir != NULL && *dir != NULL) { |
|
free_sftp_dirents(*dir); |
|
*dir = xmalloc(sizeof(**dir)); |
|
**dir = NULL; |
|
} |
|
|
return(0); |
return(0); |
} |
} |
|
|
|
|
|
|
buffer_init(&msg); |
buffer_init(&msg); |
|
|
/* Send rename request */ |
/* Send symlink request */ |
id = conn->msg_id++; |
id = conn->msg_id++; |
buffer_put_char(&msg, SSH2_FXP_SYMLINK); |
buffer_put_char(&msg, SSH2_FXP_SYMLINK); |
buffer_put_int(&msg, id); |
buffer_put_int(&msg, id); |
|
|
return(-1); |
return(-1); |
} |
} |
|
|
local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, |
local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, |
mode | S_IWRITE); |
mode | S_IWRITE); |
if (local_fd == -1) { |
if (local_fd == -1) { |
error("Couldn't open local file \"%s\" for writing: %s", |
error("Couldn't open local file \"%s\" for writing: %s", |
|
|
max_req = 1; |
max_req = 1; |
progress_counter = 0; |
progress_counter = 0; |
|
|
if (showprogress) { |
if (showprogress && size != 0) |
if (size) |
start_progress_meter(remote_path, size, &progress_counter); |
start_progress_meter(remote_path, size, |
|
&progress_counter); |
|
else |
|
printf("Fetching %s to %s\n", remote_path, local_path); |
|
} |
|
|
|
while (num_req > 0 || max_req > 0) { |
while (num_req > 0 || max_req > 0) { |
char *data; |
char *data; |
u_int len; |
u_int len; |
|
|
|
/* |
|
* Simulate EOF on interrupt: stop sending new requests and |
|
* allow outstanding requests to drain gracefully |
|
*/ |
|
if (interrupted) { |
|
if (num_req == 0) /* If we haven't started yet... */ |
|
break; |
|
max_req = 0; |
|
} |
|
|
/* Send some more requests */ |
/* Send some more requests */ |
while (num_req < max_req) { |
while (num_req < max_req) { |
debug3("Request range %llu -> %llu (%d/%d)", |
debug3("Request range %llu -> %llu (%d/%d)", |
|
|
(unsigned long long)offset, |
(unsigned long long)offset, |
num_req); |
num_req); |
max_req = 1; |
max_req = 1; |
} |
} else if (max_req <= conn->num_requests) { |
else if (max_req < conn->num_requests + 1) { |
|
++max_req; |
++max_req; |
} |
} |
} |
} |
|
|
TAILQ_ENTRY(outstanding_ack) tq; |
TAILQ_ENTRY(outstanding_ack) tq; |
}; |
}; |
TAILQ_HEAD(ackhead, outstanding_ack) acks; |
TAILQ_HEAD(ackhead, outstanding_ack) acks; |
struct outstanding_ack *ack; |
struct outstanding_ack *ack = NULL; |
|
|
TAILQ_INIT(&acks); |
TAILQ_INIT(&acks); |
|
|
|
|
offset = 0; |
offset = 0; |
if (showprogress) |
if (showprogress) |
start_progress_meter(local_path, sb.st_size, &offset); |
start_progress_meter(local_path, sb.st_size, &offset); |
else |
|
printf("Uploading %s to %s\n", local_path, remote_path); |
|
|
|
for (;;) { |
for (;;) { |
int len; |
int len; |
|
|
/* |
/* |
* Can't use atomicio here because it returns 0 on EOF, thus losing |
* Can't use atomicio here because it returns 0 on EOF, |
* the last block of the file |
* thus losing the last block of the file. |
|
* Simulate an EOF on interrupt, allowing ACKs from the |
|
* server to drain. |
*/ |
*/ |
do |
if (interrupted) |
|
len = 0; |
|
else do |
len = read(local_fd, data, conn->transfer_buflen); |
len = read(local_fd, data, conn->transfer_buflen); |
while ((len == -1) && (errno == EINTR || errno == EAGAIN)); |
while ((len == -1) && (errno == EINTR || errno == EAGAIN)); |
|
|