/*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
RCSID("$OpenBSD: sftp-server.c,v 1.47 2004/06/25 05:38:48 dtucker Exp $");
#include "buffer.h"
#include "bufaux.h"
#include "getput.h"
#include "log.h"
#include "xmalloc.h"
#include "sftp.h"
#include "sftp-common.h"
/* helper */
#define get_int64() buffer_get_int64(&iqueue);
#define get_int() buffer_get_int(&iqueue);
#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;
Buffer oqueue;
/* Version of client */
int version;
/* portable attributes, etc. */
typedef struct Stat Stat;
struct Stat {
char *name;
char *long_name;
Attrib attrib;
};
static int
errno_to_portable(int unixerrno)
{
int ret = 0;
switch (unixerrno) {
case 0:
ret = SSH2_FX_OK;
break;
case ENOENT:
case ENOTDIR:
case EBADF:
case ELOOP:
ret = SSH2_FX_NO_SUCH_FILE;
break;
case EPERM:
case EACCES:
case EFAULT:
ret = SSH2_FX_PERMISSION_DENIED;
break;
case ENAMETOOLONG:
case EINVAL:
ret = SSH2_FX_BAD_MESSAGE;
break;
default:
ret = SSH2_FX_FAILURE;
break;
}
return ret;
}
static int
flags_from_portable(int pflags)
{
int flags = 0;
if ((pflags & SSH2_FXF_READ) &&
(pflags & SSH2_FXF_WRITE)) {
flags = O_RDWR;
} else if (pflags & SSH2_FXF_READ) {
flags = O_RDONLY;
} else if (pflags & SSH2_FXF_WRITE) {
flags = O_WRONLY;
}
if (pflags & SSH2_FXF_CREAT)
flags |= O_CREAT;
if (pflags & SSH2_FXF_TRUNC)
flags |= O_TRUNC;
if (pflags & SSH2_FXF_EXCL)
flags |= O_EXCL;
return flags;
}
static Attrib *
get_attrib(void)
{
return decode_attrib(&iqueue);
}
/* handle handles */
typedef struct Handle Handle;
struct Handle {
int use;
DIR *dirp;
int fd;
char *name;
};
enum {
HANDLE_UNUSED,
HANDLE_DIR,
HANDLE_FILE
};
Handle handles[100];
static void
handle_init(void)
{
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;
for (i = 0; i < sizeof(handles)/sizeof(Handle); i