version 1.123, 2021/03/16 06:15:43 |
version 1.124, 2021/03/19 02:18:28 |
|
|
char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ |
char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ |
|
|
/* Maximum data read that we are willing to accept */ |
/* Maximum data read that we are willing to accept */ |
#define SFTP_MAX_READ_LENGTH (64 * 1024) |
#define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024) |
|
|
/* Our verbosity */ |
/* Our verbosity */ |
static LogLevel log_level = SYSLOG_LEVEL_ERROR; |
static LogLevel log_level = SYSLOG_LEVEL_ERROR; |
|
|
static void |
static void |
process_read(u_int32_t id) |
process_read(u_int32_t id) |
{ |
{ |
u_char buf[SFTP_MAX_READ_LENGTH]; |
static u_char *buf; |
|
static size_t buflen; |
u_int32_t len; |
u_int32_t len; |
int r, handle, fd, ret, status = SSH2_FX_FAILURE; |
int r, handle, fd, ret, status = SSH2_FX_FAILURE; |
u_int64_t off; |
u_int64_t off; |
|
|
(r = sshbuf_get_u32(iqueue, &len)) != 0) |
(r = sshbuf_get_u32(iqueue, &len)) != 0) |
fatal_fr(r, "parse"); |
fatal_fr(r, "parse"); |
|
|
debug("request %u: read \"%s\" (handle %d) off %llu len %d", |
debug("request %u: read \"%s\" (handle %d) off %llu len %u", |
id, handle_to_name(handle), handle, (unsigned long long)off, len); |
id, handle_to_name(handle), handle, (unsigned long long)off, len); |
if (len > sizeof buf) { |
if ((fd = handle_to_fd(handle)) == -1) |
len = sizeof buf; |
goto out; |
debug2("read change len %d", len); |
if (len > SFTP_MAX_READ_LENGTH) { |
|
debug2("read change len %u to %u", len, SFTP_MAX_READ_LENGTH); |
|
len = SFTP_MAX_READ_LENGTH; |
} |
} |
fd = handle_to_fd(handle); |
if (len > buflen) { |
if (fd >= 0) { |
debug3_f("allocate %zu => %u", buflen, len); |
if (lseek(fd, off, SEEK_SET) == -1) { |
if ((buf = realloc(NULL, len)) == NULL) |
error("process_read: seek failed"); |
fatal_f("realloc failed"); |
status = errno_to_portable(errno); |
buflen = len; |
} else { |
|
ret = read(fd, buf, len); |
|
if (ret == -1) { |
|
status = errno_to_portable(errno); |
|
} else if (ret == 0) { |
|
status = SSH2_FX_EOF; |
|
} else { |
|
send_data(id, buf, ret); |
|
status = SSH2_FX_OK; |
|
handle_update_read(handle, ret); |
|
} |
|
} |
|
} |
} |
|
if (lseek(fd, off, SEEK_SET) == -1) { |
|
status = errno_to_portable(errno); |
|
error_f("seek \"%.100s\": %s", handle_to_name(handle), |
|
strerror(errno)); |
|
goto out; |
|
} |
|
if (len == 0) { |
|
/* weird, but not strictly disallowed */ |
|
ret = 0; |
|
} else if ((ret = read(fd, buf, len)) == -1) { |
|
status = errno_to_portable(errno); |
|
error_f("read \"%.100s\": %s", handle_to_name(handle), |
|
strerror(errno)); |
|
goto out; |
|
} else if (ret == 0) { |
|
status = SSH2_FX_EOF; |
|
goto out; |
|
} |
|
send_data(id, buf, ret); |
|
handle_update_read(handle, ret); |
|
/* success */ |
|
status = SSH2_FX_OK; |
|
out: |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
send_status(id, status); |
send_status(id, status); |
} |
} |