=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/sftp-client.c,v retrieving revision 1.31.2.3 retrieving revision 1.32 diff -u -r1.31.2.3 -r1.32 --- src/usr.bin/ssh/sftp-client.c 2003/04/03 22:35:17 1.31.2.3 +++ src/usr.bin/ssh/sftp-client.c 2002/06/09 13:32:01 1.32 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2003 Damien Miller. All rights reserved. + * Copyright (c) 2001,2002 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,7 +28,7 @@ /* XXX: copy between two remote sites */ #include "includes.h" -RCSID("$OpenBSD: sftp-client.c,v 1.31.2.3 2003/04/03 22:35:17 miod Exp $"); +RCSID("$OpenBSD: sftp-client.c,v 1.32 2002/06/09 13:32:01 markus Exp $"); #include @@ -38,20 +38,14 @@ #include "xmalloc.h" #include "log.h" #include "atomicio.h" -#include "progressmeter.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" -extern int showprogress; - /* Minimum amount of data to read at at time */ #define MIN_READ_SIZE 512 -/* Maximum packet size */ -#define MAX_MSG_LENGTH (256 * 1024) - struct sftp_conn { int fd_in; int fd_out; @@ -64,45 +58,48 @@ static void send_msg(int fd, Buffer *m) { - u_char mlen[4]; + int mlen = buffer_len(m); + int len; + Buffer oqueue; - if (buffer_len(m) > MAX_MSG_LENGTH) - fatal("Outbound message too long %u", buffer_len(m)); + buffer_init(&oqueue); + buffer_put_int(&oqueue, mlen); + buffer_append(&oqueue, buffer_ptr(m), mlen); + buffer_consume(m, mlen); - /* Send length first */ - PUT_32BIT(mlen, buffer_len(m)); - if (atomicio(write, fd, mlen, sizeof(mlen)) <= 0) + len = atomicio(write, fd, buffer_ptr(&oqueue), buffer_len(&oqueue)); + if (len <= 0) fatal("Couldn't send packet: %s", strerror(errno)); - if (atomicio(write, fd, buffer_ptr(m), buffer_len(m)) <= 0) - fatal("Couldn't send packet: %s", strerror(errno)); - - buffer_clear(m); + buffer_free(&oqueue); } static void get_msg(int fd, Buffer *m) { - ssize_t len; - u_int msg_len; + u_int len, msg_len; + unsigned char buf[4096]; - buffer_append_space(m, 4); - len = atomicio(read, fd, buffer_ptr(m), 4); + len = atomicio(read, fd, buf, 4); if (len == 0) fatal("Connection closed"); else if (len == -1) fatal("Couldn't read packet: %s", strerror(errno)); - msg_len = buffer_get_int(m); - if (msg_len > MAX_MSG_LENGTH) - fatal("Received message too long %u", msg_len); + msg_len = GET_32BIT(buf); + if (msg_len > 256 * 1024) + fatal("Received message too long %d", msg_len); - buffer_append_space(m, msg_len); - len = atomicio(read, fd, buffer_ptr(m), msg_len); - if (len == 0) - fatal("Connection closed"); - else if (len == -1) - fatal("Read packet: %s", strerror(errno)); + while (msg_len) { + len = atomicio(read, fd, buf, MIN(msg_len, sizeof(buf))); + if (len == 0) + fatal("Connection closed"); + else if (len == -1) + fatal("Couldn't read packet: %s", strerror(errno)); + + msg_len -= len; + buffer_append(m, buf, len); + } } static void @@ -116,7 +113,7 @@ buffer_put_int(&msg, id); buffer_put_string(&msg, s, len); send_msg(fd, &msg); - debug3("Sent message fd %d T:%u I:%u", fd, code, id); + debug3("Sent message fd %d T:%d I:%d", fd, code, id); buffer_free(&msg); } @@ -132,12 +129,12 @@ buffer_put_string(&msg, s, len); encode_attrib(&msg, a); send_msg(fd, &msg); - debug3("Sent message fd %d T:%u I:%u", fd, code, id); + debug3("Sent message fd %d T:%d I:%d", fd, code, id); buffer_free(&msg); } static u_int -get_status(int fd, u_int expected_id) +get_status(int fd, int expected_id) { Buffer msg; u_int type, id, status; @@ -148,15 +145,15 @@ id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); + fatal("ID mismatch (%d != %d)", id, expected_id); if (type != SSH2_FXP_STATUS) - fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", + fatal("Expected SSH2_FXP_STATUS(%d) packet, got %d", SSH2_FXP_STATUS, type); status = buffer_get_int(&msg); buffer_free(&msg); - debug3("SSH2_FXP_STATUS %u", status); + debug3("SSH2_FXP_STATUS %d", status); return(status); } @@ -174,14 +171,14 @@ id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); + fatal("ID mismatch (%d != %d)", id, expected_id); if (type == SSH2_FXP_STATUS) { int status = buffer_get_int(&msg); error("Couldn't get handle: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_HANDLE) - fatal("Expected SSH2_FXP_HANDLE(%u) packet, got %u", + fatal("Expected SSH2_FXP_HANDLE(%d) packet, got %d", SSH2_FXP_HANDLE, type); handle = buffer_get_string(&msg, len); @@ -203,9 +200,9 @@ type = buffer_get_char(&msg); id = buffer_get_int(&msg); - debug3("Received stat reply T:%u I:%u", type, id); + debug3("Received stat reply T:%d I:%d", type, id); if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); + fatal("ID mismatch (%d != %d)", id, expected_id); if (type == SSH2_FXP_STATUS) { int status = buffer_get_int(&msg); @@ -215,7 +212,7 @@ error("Couldn't stat remote file: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_ATTRS) { - fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", + fatal("Expected SSH2_FXP_ATTRS(%d) packet, got %d", SSH2_FXP_ATTRS, type); } a = decode_attrib(&msg); @@ -227,8 +224,7 @@ struct sftp_conn * do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) { - u_int type; - int version; + int type, version; Buffer msg; struct sftp_conn *ret; @@ -243,7 +239,7 @@ /* Expecting a VERSION reply */ if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { - error("Invalid packet back from SSH2_FXP_INIT (type %u)", + error("Invalid packet back from SSH2_FXP_INIT (type %d)", type); buffer_free(&msg); return(NULL); @@ -298,7 +294,7 @@ buffer_put_int(&msg, id); buffer_put_string(&msg, handle, handle_len); send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_CLOSE I:%u", id); + debug3("Sent message SSH2_FXP_CLOSE I:%d", id); status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) @@ -343,7 +339,7 @@ id = expected_id = conn->msg_id++; - debug3("Sending SSH2_FXP_READDIR I:%u", id); + debug3("Sending SSH2_FXP_READDIR I:%d", id); buffer_clear(&msg); buffer_put_char(&msg, SSH2_FXP_READDIR); @@ -358,10 +354,10 @@ type = buffer_get_char(&msg); id = buffer_get_int(&msg); - debug3("Received reply T:%u I:%u", type, id); + debug3("Received reply T:%d I:%d", type, id); if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); + fatal("ID mismatch (%d != %d)", id, expected_id); if (type == SSH2_FXP_STATUS) { int status = buffer_get_int(&msg); @@ -374,11 +370,10 @@ error("Couldn't read directory: %s", fx2txt(status)); do_close(conn, handle, handle_len); - xfree(handle); return(status); } } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", + fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", SSH2_FXP_NAME, type); count = buffer_get_int(&msg); @@ -419,6 +414,12 @@ } int +do_ls(struct sftp_conn *conn, char *path) +{ + return(do_lsreaddir(conn, path, 1, NULL)); +} + +int do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) { return(do_lsreaddir(conn, path, 0, dir)); @@ -583,7 +584,7 @@ id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); + fatal("ID mismatch (%d != %d)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status = buffer_get_int(&msg); @@ -591,7 +592,7 @@ error("Couldn't canonicalise: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", + fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", SSH2_FXP_NAME, type); count = buffer_get_int(&msg); @@ -664,7 +665,7 @@ status = get_status(conn->fd_in, id); if (status != SSH2_FX_OK) - error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, + error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return(status); @@ -689,7 +690,7 @@ id = buffer_get_int(&msg); if (id != expected_id) - fatal("ID mismatch (%u != %u)", id, expected_id); + fatal("ID mismatch (%d != %d)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status = buffer_get_int(&msg); @@ -697,7 +698,7 @@ error("Couldn't readlink: %s", fx2txt(status)); return(NULL); } else if (type != SSH2_FXP_NAME) - fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", + fatal("Expected SSH2_FXP_NAME(%d) packet, got %d", SSH2_FXP_NAME, type); count = buffer_get_int(&msg); @@ -745,7 +746,6 @@ int read_error, write_errno; u_int64_t offset, size; u_int handle_len, mode, type, id, buflen; - off_t progress_counter; struct request { u_int id; u_int len; @@ -763,13 +763,13 @@ /* XXX: should we preserve set[ug]id? */ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) - mode = a->perm & 0777; + mode = S_IWRITE | (a->perm & 0777); else mode = 0666; if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && - (!S_ISREG(a->perm))) { - error("Cannot download non-regular file: %s", remote_path); + (a->perm & S_IFDIR)) { + error("Cannot download a directory: %s", remote_path); return(-1); } @@ -790,7 +790,7 @@ attrib_clear(&junk); /* Send empty attributes */ encode_attrib(&msg, &junk); send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); + debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); handle = get_handle(conn->fd_in, id, &handle_len); if (handle == NULL) { @@ -798,8 +798,7 @@ return(-1); } - local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, - mode | S_IWRITE); + local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode); if (local_fd == -1) { error("Couldn't open local file \"%s\" for writing: %s", local_path, strerror(errno)); @@ -811,16 +810,6 @@ /* Read from remote and write to local */ write_error = read_error = write_errno = num_req = offset = 0; max_req = 1; - progress_counter = 0; - - if (showprogress) { - if (size) - 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) { char *data; u_int len; @@ -846,7 +835,7 @@ get_msg(conn->fd_in, &msg); type = buffer_get_char(&msg); id = buffer_get_int(&msg); - debug3("Received reply T:%u I:%u R:%d", type, id, max_req); + debug3("Received reply T:%d I:%d R:%d", type, id, max_req); /* Find the request in our queue */ for(req = TAILQ_FIRST(&requests); @@ -873,15 +862,14 @@ (unsigned long long)req->offset + len - 1); if (len > req->len) fatal("Received more data than asked for " - "%u > %u", len, req->len); + "%d > %d", len, req->len); if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || - atomicio(write, local_fd, data, len) != len) && + atomicio(write, local_fd, data, len) != len) && !write_error) { write_errno = errno; write_error = 1; max_req = 0; } - progress_counter += len; xfree(data); if (len == req->len) { @@ -919,14 +907,11 @@ } break; default: - fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", + fatal("Expected SSH2_FXP_DATA(%d) packet, got %d", SSH2_FXP_DATA, type); } } - if (showprogress && size) - stop_progress_meter(); - /* Sanity check */ if (TAILQ_FIRST(&requests) != NULL) fatal("Transfer complete, but requests still in queue"); @@ -946,7 +931,7 @@ /* Override umask and utimes if asked */ if (pflag && fchmod(local_fd, mode) == -1) error("Couldn't set mode on \"%s\": %s", local_path, - strerror(errno)); + strerror(errno)); if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { struct timeval tv[2]; tv[0].tv_sec = a->atime; @@ -954,7 +939,7 @@ tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(local_path, tv) == -1) error("Can't set times on \"%s\": %s", - local_path, strerror(errno)); + local_path, strerror(errno)); } } close(local_fd); @@ -999,11 +984,6 @@ close(local_fd); return(-1); } - if (!S_ISREG(sb.st_mode)) { - error("%s is not a regular file", local_path); - close(local_fd); - return(-1); - } stat_to_attrib(&sb, &a); a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; @@ -1022,7 +1002,7 @@ buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); encode_attrib(&msg, &a); send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); + debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path); buffer_clear(&msg); @@ -1038,11 +1018,6 @@ /* Read from local and write to remote */ offset = 0; - if (showprogress) - start_progress_meter(local_path, sb.st_size, &offset); - else - printf("Uploading %s to %s\n", local_path, remote_path); - for (;;) { int len; @@ -1072,8 +1047,8 @@ buffer_put_int64(&msg, offset); buffer_put_string(&msg, data, len); send_msg(conn->fd_out, &msg); - debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", - id, (unsigned long long)offset, len); + debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", + id, (unsigned long long)offset, len); } else if (TAILQ_FIRST(&acks) == NULL) break; @@ -1102,27 +1077,23 @@ ack = TAILQ_NEXT(ack, tq)) ; if (ack == NULL) - fatal("Can't find request for ID %u", r_id); + fatal("Can't find request for ID %d", 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)); + 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", + debug3("In write loop, ack for %u %d bytes at %llu", ack->id, ack->len, (unsigned long long)ack->offset); ++ackid; - xfree(ack); + free(ack); } offset += len; } - if (showprogress) - stop_progress_meter(); xfree(data); if (close(local_fd) == -1) {