* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
-RCSID("$OpenBSD: sftp-server.c,v 1.46 2004/06/21 17:36:31 avsm Exp $");
+RCSID("$OpenBSD: sftp-server.c,v 1.50 2006/01/02 01:20:31 djm Exp $");
#include "buffer.h"
#include "bufaux.h"
#include "getput.h"
#include "log.h"
#include "xmalloc.h"
+#include "misc.h"
#include "sftp.h"
#include "sftp-common.h"
#define get_string(lenp) buffer_get_string(&iqueue, lenp);
#define TRACE debug
-#ifdef HAVE___PROGNAME
extern char *__progname;
-#else
-char *__progname;
-#endif
/* input and output queue */
Buffer iqueue;
static void
handle_init(void)
{
- int i;
+ u_int i;
for (i = 0; i < sizeof(handles)/sizeof(Handle); i++)
handles[i].use = HANDLE_UNUSED;
static int
handle_new(int use, const char *name, int fd, DIR *dirp)
{
- int i;
+ u_int i;
for (i = 0; i < sizeof(handles)/sizeof(Handle); i++) {
if (handles[i].use == HANDLE_UNUSED) {
static int
handle_is_ok(int i, int type)
{
- return i >= 0 && i < sizeof(handles)/sizeof(Handle) &&
+ return i >= 0 && (u_int)i < sizeof(handles)/sizeof(Handle) &&
handles[i].use == type;
}
len = get_int();
TRACE("read id %u handle %d off %llu len %d", id, handle,
- (u_int64_t)off, len);
+ (unsigned long long)off, len);
if (len > sizeof buf) {
len = sizeof buf;
logit("read change len %d", len);
data = get_string(&len);
TRACE("write id %u handle %d off %llu len %d", id, handle,
- (u_int64_t)off, len);
+ (unsigned long long)off, len);
fd = handle_to_fd(handle);
if (fd >= 0) {
if (lseek(fd, off, SEEK_SET) < 0) {
} else {
/* XXX ATOMICIO ? */
ret = write(fd, data, len);
- if (ret == -1) {
+ if (ret < 0) {
error("process_write: write failed");
status = errno_to_portable(errno);
- } else if (ret == len) {
+ } else if ((size_t)ret == len) {
status = SSH2_FX_OK;
} else {
logit("nothing at all written");
status = errno_to_portable(errno);
else if (S_ISREG(sb.st_mode)) {
/* Race-free rename of regular files */
- if (link(oldpath, newpath) == -1)
- status = errno_to_portable(errno);
- else if (unlink(oldpath) == -1) {
+ if (link(oldpath, newpath) == -1) {
+ if (errno == EOPNOTSUPP
+#ifdef LINK_OPNOTSUPP_ERRNO
+ || errno == LINK_OPNOTSUPP_ERRNO
+#endif
+ ) {
+ struct stat st;
+
+ /*
+ * fs doesn't support links, so fall back to
+ * stat+rename. This is racy.
+ */
+ if (stat(newpath, &st) == -1) {
+ if (rename(oldpath, newpath) == -1)
+ status =
+ errno_to_portable(errno);
+ else
+ status = SSH2_FX_OK;
+ }
+ } else {
+ status = errno_to_portable(errno);
+ }
+ } else if (unlink(oldpath) == -1) {
status = errno_to_portable(errno);
/* clean spare link */
unlink(newpath);
return; /* Incomplete message. */
cp = buffer_ptr(&iqueue);
msg_len = GET_32BIT(cp);
- if (msg_len > 256 * 1024) {
+ if (msg_len > SFTP_MAX_MSG_LENGTH) {
error("bad message ");
exit(11);
}
int in, out, max;
ssize_t len, olen, set_size;
+ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
+ sanitise_stdfd();
+
/* XXX should use getopt */
__progname = ssh_get_progname(av[0]);