-/* $OpenBSD: sftp-client.c,v 1.70 2006/07/23 01:11:05 stevesk Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.80 2008/01/21 19:20:17 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
#include "includes.h"
#include <sys/types.h>
+#include <sys/param.h>
+#include "openbsd-compat/sys-queue.h"
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/uio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include "openbsd-compat/sys-queue.h"
-
-#include "buffer.h"
-#include "bufaux.h"
#include "xmalloc.h"
+#include "buffer.h"
#include "log.h"
#include "atomicio.h"
#include "progressmeter.h"
iov[0].iov_len = sizeof(mlen);
iov[1].iov_base = buffer_ptr(m);
iov[1].iov_len = buffer_len(m);
-
+
if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen))
fatal("Couldn't send packet: %s", strerror(errno));
return(get_decode_stat(conn->fd_in, id, quiet));
}
+#ifdef notyet
Attrib *
do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
{
return(get_decode_stat(conn->fd_in, id, quiet));
}
+#endif
int
do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
return(status);
}
+#ifdef notyet
char *
do_readlink(struct sftp_conn *conn, char *path)
{
return(filename);
}
+#endif
static void
send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
if (local_fd == -1) {
error("Couldn't open local file \"%s\" for writing: %s",
local_path, strerror(errno));
+ do_close(conn, handle, handle_len);
buffer_free(&msg);
xfree(handle);
return(-1);
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
int pflag)
{
- int local_fd, status;
+ int local_fd;
+ int status = SSH2_FX_OK;
u_int handle_len, id, type;
- u_int64_t offset;
+ off_t offset;
char *handle, *data;
Buffer msg;
struct stat sb;
struct outstanding_ack {
u_int id;
u_int len;
- u_int64_t offset;
+ off_t offset;
TAILQ_ENTRY(outstanding_ack) tq;
};
TAILQ_HEAD(ackhead, outstanding_ack) acks;
if (handle == NULL) {
close(local_fd);
buffer_free(&msg);
- return(-1);
+ return -1;
}
startid = ackid = id + 1;
* Simulate an EOF on interrupt, allowing ACKs from the
* server to drain.
*/
- if (interrupted)
+ if (interrupted || status != SSH2_FX_OK)
len = 0;
else do
len = read(local_fd, data, conn->transfer_buflen);
if (ack == NULL)
fatal("Can't find request for ID %u", r_id);
TAILQ_REMOVE(&acks, ack, tq);
-
- if (status != SSH2_FX_OK) {
- error("Couldn't write to remote file \"%s\": %s",
- remote_path, fx2txt(status));
- do_close(conn, handle, handle_len);
- close(local_fd);
- xfree(data);
- xfree(ack);
- goto done;
- }
- debug3("In write loop, ack for %u %u bytes at %llu",
- ack->id, ack->len, (unsigned long long)ack->offset);
+ debug3("In write loop, ack for %u %u bytes at %lld",
+ ack->id, ack->len, (long long)ack->offset);
++ackid;
xfree(ack);
}
offset += len;
+ if (offset < 0)
+ fatal("%s: offset < 0", __func__);
}
+ buffer_free(&msg);
+
if (showprogress)
stop_progress_meter();
xfree(data);
+ if (status != SSH2_FX_OK) {
+ error("Couldn't write to remote file \"%s\": %s",
+ remote_path, fx2txt(status));
+ status = -1;
+ }
+
if (close(local_fd) == -1) {
error("Couldn't close local file \"%s\": %s", local_path,
strerror(errno));
- do_close(conn, handle, handle_len);
status = -1;
- goto done;
}
/* Override umask and utimes if asked */
if (pflag)
do_fsetstat(conn, handle, handle_len, &a);
- status = do_close(conn, handle, handle_len);
-
-done:
+ if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
+ status = -1;
xfree(handle);
- buffer_free(&msg);
- return(status);
+
+ return status;
}