diff options
Diffstat (limited to 'crypto/openssh/sftp-server.c')
| -rw-r--r-- | crypto/openssh/sftp-server.c | 1068 |
1 files changed, 0 insertions, 1068 deletions
diff --git a/crypto/openssh/sftp-server.c b/crypto/openssh/sftp-server.c deleted file mode 100644 index 018a03cc2098..000000000000 --- a/crypto/openssh/sftp-server.c +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "includes.h" -RCSID("$OpenBSD: sftp-server.c,v 1.6 2000/09/07 20:27:53 deraadt Exp $"); - -#include "ssh.h" -#include "buffer.h" -#include "bufaux.h" -#include "getput.h" -#include "xmalloc.h" - -/* version */ -#define SSH_FILEXFER_VERSION 2 - -/* client to server */ -#define SSH_FXP_INIT 1 -#define SSH_FXP_OPEN 3 -#define SSH_FXP_CLOSE 4 -#define SSH_FXP_READ 5 -#define SSH_FXP_WRITE 6 -#define SSH_FXP_LSTAT 7 -#define SSH_FXP_FSTAT 8 -#define SSH_FXP_SETSTAT 9 -#define SSH_FXP_FSETSTAT 10 -#define SSH_FXP_OPENDIR 11 -#define SSH_FXP_READDIR 12 -#define SSH_FXP_REMOVE 13 -#define SSH_FXP_MKDIR 14 -#define SSH_FXP_RMDIR 15 -#define SSH_FXP_REALPATH 16 -#define SSH_FXP_STAT 17 -#define SSH_FXP_RENAME 18 - -/* server to client */ -#define SSH_FXP_VERSION 2 -#define SSH_FXP_STATUS 101 -#define SSH_FXP_HANDLE 102 -#define SSH_FXP_DATA 103 -#define SSH_FXP_NAME 104 -#define SSH_FXP_ATTRS 105 - -/* portable open modes */ -#define SSH_FXF_READ 0x01 -#define SSH_FXF_WRITE 0x02 -#define SSH_FXF_APPEND 0x04 -#define SSH_FXF_CREAT 0x08 -#define SSH_FXF_TRUNC 0x10 -#define SSH_FXF_EXCL 0x20 - -/* attributes */ -#define SSH_FXA_HAVE_SIZE 0x01 -#define SSH_FXA_HAVE_UGID 0x02 -#define SSH_FXA_HAVE_PERM 0x04 -#define SSH_FXA_HAVE_TIME 0x08 - -/* status messages */ -#define SSH_FX_OK 0x00 -#define SSH_FX_EOF 0x01 -#define SSH_FX_NO_SUCH_FILE 0x02 -#define SSH_FX_PERMISSION_DENIED 0x03 -#define SSH_FX_FAILURE 0x04 -#define SSH_FX_BAD_MESSAGE 0x05 -#define SSH_FX_NO_CONNECTION 0x06 -#define SSH_FX_CONNECTION_LOST 0x07 - - -/* helper */ -#define get_int() buffer_get_int(&iqueue); -#define get_string(lenp) buffer_get_string(&iqueue, lenp); -#define TRACE log - -/* input and output queue */ -Buffer iqueue; -Buffer oqueue; - -/* portable attibutes, etc. */ - -typedef struct Attrib Attrib; -typedef struct Stat Stat; - -struct Attrib -{ - u_int32_t flags; - u_int32_t size_high; - u_int32_t size_low; - u_int64_t size; - u_int32_t uid; - u_int32_t gid; - u_int32_t perm; - u_int32_t atime; - u_int32_t mtime; -}; - -struct Stat -{ - char *name; - char *long_name; - Attrib attrib; -}; - -int -errno_to_portable(int unixerrno) -{ - int ret = 0; - switch (unixerrno) { - case 0: - ret = SSH_FX_OK; - break; - case ENOENT: - case ENOTDIR: - case EBADF: - case ELOOP: - ret = SSH_FX_NO_SUCH_FILE; - break; - case EPERM: - case EACCES: - case EFAULT: - ret = SSH_FX_PERMISSION_DENIED; - break; - case ENAMETOOLONG: - case EINVAL: - ret = SSH_FX_BAD_MESSAGE; - break; - default: - ret = SSH_FX_FAILURE; - break; - } - return ret; -} - -int -flags_from_portable(int pflags) -{ - int flags = 0; - if (pflags & SSH_FXF_READ && - pflags & SSH_FXF_WRITE) { - flags = O_RDWR; - } else if (pflags & SSH_FXF_READ) { - flags = O_RDONLY; - } else if (pflags & SSH_FXF_WRITE) { - flags = O_WRONLY; - } - if (pflags & SSH_FXF_CREAT) - flags |= O_CREAT; - if (pflags & SSH_FXF_TRUNC) - flags |= O_TRUNC; - if (pflags & SSH_FXF_EXCL) - flags |= O_EXCL; - return flags; -} - -void -attrib_clear(Attrib *a) -{ - a->flags = 0; - a->size_low = 0; - a->size_high = 0; - a->size = 0; - a->uid = 0; - a->gid = 0; - a->perm = 0; - a->atime = 0; - a->mtime = 0; -} - -Attrib * -decode_attrib(Buffer *b) -{ - static Attrib a; - attrib_clear(&a); - a.flags = buffer_get_int(b); - if (a.flags & SSH_FXA_HAVE_SIZE) { - a.size_high = buffer_get_int(b); - a.size_low = buffer_get_int(b); - a.size = (((u_int64_t) a.size_high) << 32) + a.size_low; - } - if (a.flags & SSH_FXA_HAVE_UGID) { - a.uid = buffer_get_int(b); - a.gid = buffer_get_int(b); - } - if (a.flags & SSH_FXA_HAVE_PERM) { - a.perm = buffer_get_int(b); - } - if (a.flags & SSH_FXA_HAVE_TIME) { - a.atime = buffer_get_int(b); - a.mtime = buffer_get_int(b); - } - return &a; -} - -void -encode_attrib(Buffer *b, Attrib *a) -{ - buffer_put_int(b, a->flags); - if (a->flags & SSH_FXA_HAVE_SIZE) { - buffer_put_int(b, a->size_high); - buffer_put_int(b, a->size_low); - } - if (a->flags & SSH_FXA_HAVE_UGID) { - buffer_put_int(b, a->uid); - buffer_put_int(b, a->gid); - } - if (a->flags & SSH_FXA_HAVE_PERM) { - buffer_put_int(b, a->perm); - } - if (a->flags & SSH_FXA_HAVE_TIME) { - buffer_put_int(b, a->atime); - buffer_put_int(b, a->mtime); - } -} - -Attrib * -stat_to_attrib(struct stat *st) -{ - static Attrib a; - attrib_clear(&a); - a.flags = 0; - a.flags |= SSH_FXA_HAVE_SIZE; - a.size = st->st_size; - a.size_low = a.size; - a.size_high = (u_int32_t) (a.size >> 32); - a.flags |= SSH_FXA_HAVE_UGID; - a.uid = st->st_uid; - a.gid = st->st_gid; - a.flags |= SSH_FXA_HAVE_PERM; - a.perm = st->st_mode; - a.flags |= SSH_FXA_HAVE_TIME; - a.atime = st->st_atime; - a.mtime = st->st_mtime; - return &a; -} - -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]; - -void -handle_init(void) -{ - int i; - for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) - handles[i].use = HANDLE_UNUSED; -} - -int -handle_new(int use, char *name, int fd, DIR *dirp) -{ - int i; - for(i = 0; i < sizeof(handles)/sizeof(Handle); i++) { - if (handles[i].use == HANDLE_UNUSED) { - handles[i].use = use; - handles[i].dirp = dirp; - handles[i].fd = fd; - handles[i].name = name; - return i; - } - } - return -1; -} - -int -handle_is_ok(int i, int type) -{ - return i >= 0 && i < sizeof(handles)/sizeof(Handle) && handles[i].use == type; -} - -int -handle_to_string(int handle, char **stringp, int *hlenp) -{ - char buf[1024]; - if (stringp == NULL || hlenp == NULL) - return -1; - snprintf(buf, sizeof buf, "%d", handle); - *stringp = xstrdup(buf); - *hlenp = strlen(*stringp); - return 0; -} - -int -handle_from_string(char *handle, u_int hlen) -{ -/* XXX OVERFLOW ? */ - char *ep; - long lval = strtol(handle, &ep, 10); - int val = lval; - if (*ep != '\0') - return -1; - if (handle_is_ok(val, HANDLE_FILE) || - handle_is_ok(val, HANDLE_DIR)) - return val; - return -1; -} - -char * -handle_to_name(int handle) -{ - if (handle_is_ok(handle, HANDLE_DIR)|| - handle_is_ok(handle, HANDLE_FILE)) - return handles[handle].name; - return NULL; -} - -DIR * -handle_to_dir(int handle) -{ - if (handle_is_ok(handle, HANDLE_DIR)) - return handles[handle].dirp; - return NULL; -} - -int -handle_to_fd(int handle) -{ - if (handle_is_ok(handle, HANDLE_FILE)) - return handles[handle].fd; - return -1; -} - -int -handle_close(int handle) -{ - int ret = -1; - if (handle_is_ok(handle, HANDLE_FILE)) { - ret = close(handles[handle].fd); - handles[handle].use = HANDLE_UNUSED; - } else if (handle_is_ok(handle, HANDLE_DIR)) { - ret = closedir(handles[handle].dirp); - handles[handle].use = HANDLE_UNUSED; - } else { - errno = ENOENT; - } - return ret; -} - -int -get_handle(void) -{ - char *handle; - int val; - u_int hlen; - handle = get_string(&hlen); - val = handle_from_string(handle, hlen); - xfree(handle); - return val; -} - -/* send replies */ - -void -send_msg(Buffer *m) -{ - int mlen = buffer_len(m); - buffer_put_int(&oqueue, mlen); - buffer_append(&oqueue, buffer_ptr(m), mlen); - buffer_consume(m, mlen); -} - -void -send_status(u_int32_t id, u_int32_t error) -{ - Buffer msg; - TRACE("sent status id %d error %d", id, error); - buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_STATUS); - buffer_put_int(&msg, id); - buffer_put_int(&msg, error); - send_msg(&msg); - buffer_free(&msg); -} -void -send_data_or_handle(char type, u_int32_t id, char *data, int dlen) -{ - Buffer msg; - buffer_init(&msg); - buffer_put_char(&msg, type); - buffer_put_int(&msg, id); - buffer_put_string(&msg, data, dlen); - send_msg(&msg); - buffer_free(&msg); -} - -void -send_data(u_int32_t id, char *data, int dlen) -{ - TRACE("sent data id %d len %d", id, dlen); - send_data_or_handle(SSH_FXP_DATA, id, data, dlen); -} - -void -send_handle(u_int32_t id, int handle) -{ - char *string; - int hlen; - handle_to_string(handle, &string, &hlen); - TRACE("sent handle id %d handle %d", id, handle); - send_data_or_handle(SSH_FXP_HANDLE, id, string, hlen); - xfree(string); -} - -void -send_names(u_int32_t id, int count, Stat *stats) -{ - Buffer msg; - int i; - buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_NAME); - buffer_put_int(&msg, id); - buffer_put_int(&msg, count); - TRACE("sent names id %d count %d", id, count); - for (i = 0; i < count; i++) { - buffer_put_cstring(&msg, stats[i].name); - buffer_put_cstring(&msg, stats[i].long_name); - encode_attrib(&msg, &stats[i].attrib); - } - send_msg(&msg); - buffer_free(&msg); -} - -void -send_attrib(u_int32_t id, Attrib *a) -{ - Buffer msg; - TRACE("sent attrib id %d have 0x%x", id, a->flags); - buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_ATTRS); - buffer_put_int(&msg, id); - encode_attrib(&msg, a); - send_msg(&msg); - buffer_free(&msg); -} - -/* parse incoming */ - -void -process_init(void) -{ - Buffer msg; - int version = buffer_get_int(&iqueue); - - TRACE("client version %d", version); - buffer_init(&msg); - buffer_put_char(&msg, SSH_FXP_VERSION); - buffer_put_int(&msg, SSH_FILEXFER_VERSION); - send_msg(&msg); - buffer_free(&msg); -} - -void -process_open(void) -{ - u_int32_t id, pflags; - Attrib *a; - char *name; - int handle, fd, flags, mode, status = SSH_FX_FAILURE; - - id = get_int(); - name = get_string(NULL); - pflags = get_int(); - a = get_attrib(); - flags = flags_from_portable(pflags); - mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm : 0666; - TRACE("open id %d name %s flags %d mode 0%o", id, name, pflags, mode); - fd = open(name, flags, mode); - if (fd < 0) { - status = errno_to_portable(errno); - } else { - handle = handle_new(HANDLE_FILE, xstrdup(name), fd, NULL); - if (handle < 0) { - close(fd); - } else { - send_handle(id, handle); - status = SSH_FX_OK; - } - } - if (status != SSH_FX_OK) - send_status(id, status); - xfree(name); -} - -void -process_close(void) -{ - u_int32_t id; - int handle, ret, status = SSH_FX_FAILURE; - - id = get_int(); - handle = get_handle(); - TRACE("close id %d handle %d", id, handle); - ret = handle_close(handle); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; - send_status(id, status); -} - -void -process_read(void) -{ - char buf[64*1024]; - u_int32_t id, off_high, off_low, len; - int handle, fd, ret, status = SSH_FX_FAILURE; - u_int64_t off; - - id = get_int(); - handle = get_handle(); - off_high = get_int(); - off_low = get_int(); - len = get_int(); - - off = (((u_int64_t) off_high) << 32) + off_low; - TRACE("read id %d handle %d off %qd len %d", id, handle, off, len); - if (len > sizeof buf) { - len = sizeof buf; - log("read change len %d", len); - } - fd = handle_to_fd(handle); - if (fd >= 0) { - if (lseek(fd, off, SEEK_SET) < 0) { - error("process_read: seek failed"); - status = errno_to_portable(errno); - } else { - ret = read(fd, buf, len); - if (ret < 0) { - status = errno_to_portable(errno); - } else if (ret == 0) { - status = SSH_FX_EOF; - } else { - send_data(id, buf, ret); - status = SSH_FX_OK; - } - } - } - if (status != SSH_FX_OK) - send_status(id, status); -} - -void -process_write(void) -{ - u_int32_t id, off_high, off_low; - u_int64_t off; - u_int len; - int handle, fd, ret, status = SSH_FX_FAILURE; - char *data; - - id = get_int(); - handle = get_handle(); - off_high = get_int(); - off_low = get_int(); - data = get_string(&len); - - off = (((u_int64_t) off_high) << 32) + off_low; - TRACE("write id %d handle %d off %qd len %d", id, handle, off, len); - fd = handle_to_fd(handle); - if (fd >= 0) { - if (lseek(fd, off, SEEK_SET) < 0) { - status = errno_to_portable(errno); - error("process_write: seek failed"); - } else { -/* XXX ATOMICIO ? */ - ret = write(fd, data, len); - if (ret == -1) { - error("process_write: write failed"); - status = errno_to_portable(errno); - } else if (ret == len) { - status = SSH_FX_OK; - } else { - log("nothing at all written"); - } - } - } - send_status(id, status); - xfree(data); -} - -void -process_do_stat(int do_lstat) -{ - Attrib *a; - struct stat st; - u_int32_t id; - char *name; - int ret, status = SSH_FX_FAILURE; - - id = get_int(); - name = get_string(NULL); - TRACE("%sstat id %d name %s", do_lstat ? "l" : "", id, name); - ret = do_lstat ? lstat(name, &st) : stat(name, &st); - if (ret < 0) { - status = errno_to_portable(errno); - } else { - a = stat_to_attrib(&st); - send_attrib(id, a); - status = SSH_FX_OK; - } - if (status != SSH_FX_OK) - send_status(id, status); - xfree(name); -} - -void -process_stat(void) -{ - process_do_stat(0); -} - -void -process_lstat(void) -{ - process_do_stat(1); -} - -void -process_fstat(void) -{ - Attrib *a; - struct stat st; - u_int32_t id; - int fd, ret, handle, status = SSH_FX_FAILURE; - - id = get_int(); - handle = get_handle(); - TRACE("fstat id %d handle %d", id, handle); - fd = handle_to_fd(handle); - if (fd >= 0) { - ret = fstat(fd, &st); - if (ret < 0) { - status = errno_to_portable(errno); - } else { - a = stat_to_attrib(&st); - send_attrib(id, a); - status = SSH_FX_OK; - } - } - if (status != SSH_FX_OK) - send_status(id, status); -} - -struct timeval * -attrib_to_tv(Attrib *a) -{ - static struct timeval tv[2]; - tv[0].tv_sec = a->atime; - tv[0].tv_usec = 0; - tv[1].tv_sec = a->mtime; - tv[1].tv_usec = 0; - return tv; -} - -void -process_setstat(void) -{ - Attrib *a; - u_int32_t id; - char *name; - int ret; - int status = SSH_FX_OK; - - id = get_int(); - name = get_string(NULL); - a = get_attrib(); - TRACE("setstat id %d name %s", id, name); - if (a->flags & SSH_FXA_HAVE_PERM) { - ret = chmod(name, a->perm & 0777); - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH_FXA_HAVE_TIME) { - ret = utimes(name, attrib_to_tv(a)); - if (ret == -1) - status = errno_to_portable(errno); - } - send_status(id, status); - xfree(name); -} - -void -process_fsetstat(void) -{ - Attrib *a; - u_int32_t id; - int handle, fd, ret; - int status = SSH_FX_OK; - - id = get_int(); - handle = get_handle(); - a = get_attrib(); - TRACE("fsetstat id %d handle %d", id, handle); - fd = handle_to_fd(handle); - if (fd < 0) { - status = SSH_FX_FAILURE; - } else { - if (a->flags & SSH_FXA_HAVE_PERM) { - ret = fchmod(fd, a->perm & 0777); - if (ret == -1) - status = errno_to_portable(errno); - } - if (a->flags & SSH_FXA_HAVE_TIME) { - ret = futimes(fd, attrib_to_tv(a)); - if (ret == -1) - status = errno_to_portable(errno); - } - } - send_status(id, status); -} - -void -process_opendir(void) -{ - DIR *dirp = NULL; - char *path; - int handle, status = SSH_FX_FAILURE; - u_int32_t id; - - id = get_int(); - path = get_string(NULL); - TRACE("opendir id %d path %s", id, path); - dirp = opendir(path); - if (dirp == NULL) { - status = errno_to_portable(errno); - } else { - handle = handle_new(HANDLE_DIR, xstrdup(path), 0, dirp); - if (handle < 0) { - closedir(dirp); - } else { - send_handle(id, handle); - status = SSH_FX_OK; - } - - } - if (status != SSH_FX_OK) - send_status(id, status); - xfree(path); -} - -char * -ls_file(char *name, struct stat *st) -{ - char buf[1024]; - snprintf(buf, sizeof buf, "0%o %d %d %qd %d %s", - st->st_mode, st->st_uid, st->st_gid, (long long)st->st_size,(int) st->st_mtime, - name); - return xstrdup(buf); -} - -void -process_readdir(void) -{ - DIR *dirp; - struct dirent *dp; - char *path; - int handle; - u_int32_t id; - - id = get_int(); - handle = get_handle(); - TRACE("readdir id %d handle %d", id, handle); - dirp = handle_to_dir(handle); - path = handle_to_name(handle); - if (dirp == NULL || path == NULL) { - send_status(id, SSH_FX_FAILURE); - } else { - Attrib *a; - struct stat st; - char pathname[1024]; - Stat *stats; - int nstats = 10, count = 0, i; - stats = xmalloc(nstats * sizeof(Stat)); - while ((dp = readdir(dirp)) != NULL) { - if (count >= nstats) { - nstats *= 2; - stats = xrealloc(stats, nstats * sizeof(Stat)); - } -/* XXX OVERFLOW ? */ - snprintf(pathname, sizeof pathname, - "%s/%s", path, dp->d_name); - if (lstat(pathname, &st) < 0) - continue; - a = stat_to_attrib(&st); - stats[count].attrib = *a; - stats[count].name = xstrdup(dp->d_name); - stats[count].long_name = ls_file(dp->d_name, &st); - count++; - /* send up to 100 entries in one message */ - if (count == 100) - break; - } - send_names(id, count, stats); - for(i = 0; i < count; i++) { - xfree(stats[i].name); - xfree(stats[i].long_name); - } - xfree(stats); - } -} - -void -process_remove(void) -{ - char *name; - u_int32_t id; - int status = SSH_FX_FAILURE; - int ret; - - id = get_int(); - name = get_string(NULL); - TRACE("remove id %d name %s", id, name); - ret = remove(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; - send_status(id, status); - xfree(name); -} - -void -process_mkdir(void) -{ - Attrib *a; - u_int32_t id; - char *name; - int ret, mode, status = SSH_FX_FAILURE; - - id = get_int(); - name = get_string(NULL); - a = get_attrib(); - mode = (a->flags & SSH_FXA_HAVE_PERM) ? a->perm & 0777 : 0777; - TRACE("mkdir id %d name %s mode 0%o", id, name, mode); - ret = mkdir(name, mode); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; - send_status(id, status); - xfree(name); -} - -void -process_rmdir(void) -{ - u_int32_t id; - char *name; - int ret, status; - - id = get_int(); - name = get_string(NULL); - TRACE("rmdir id %d name %s", id, name); - ret = rmdir(name); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; - send_status(id, status); - xfree(name); -} - -void -process_realpath(void) -{ - char resolvedname[MAXPATHLEN]; - u_int32_t id; - char *path; - - id = get_int(); - path = get_string(NULL); - TRACE("realpath id %d path %s", id, path); - if (realpath(path, resolvedname) == NULL) { - send_status(id, errno_to_portable(errno)); - } else { - Stat s; - attrib_clear(&s.attrib); - s.name = s.long_name = resolvedname; - send_names(id, 1, &s); - } - xfree(path); -} - -void -process_rename(void) -{ - u_int32_t id; - char *oldpath, *newpath; - int ret, status; - - id = get_int(); - oldpath = get_string(NULL); - newpath = get_string(NULL); - TRACE("rename id %d old %s new %s", id, oldpath, newpath); - ret = rename(oldpath, newpath); - status = (ret == -1) ? errno_to_portable(errno) : SSH_FX_OK; - send_status(id, status); - xfree(oldpath); - xfree(newpath); -} - - -/* stolen from ssh-agent */ - -void -process(void) -{ - unsigned int msg_len; - unsigned int type; - unsigned char *cp; - - if (buffer_len(&iqueue) < 5) - return; /* Incomplete message. */ - cp = (unsigned char *) buffer_ptr(&iqueue); - msg_len = GET_32BIT(cp); - if (msg_len > 256 * 1024) { - error("bad message "); - exit(11); - } - if (buffer_len(&iqueue) < msg_len + 4) - return; - buffer_consume(&iqueue, 4); - type = buffer_get_char(&iqueue); - switch (type) { - case SSH_FXP_INIT: - process_init(); - break; - case SSH_FXP_OPEN: - process_open(); - break; - case SSH_FXP_CLOSE: - process_close(); - break; - case SSH_FXP_READ: - process_read(); - break; - case SSH_FXP_WRITE: - process_write(); - break; - case SSH_FXP_LSTAT: - process_lstat(); - break; - case SSH_FXP_FSTAT: - process_fstat(); - break; - case SSH_FXP_SETSTAT: - process_setstat(); - break; - case SSH_FXP_FSETSTAT: - process_fsetstat(); - break; - case SSH_FXP_OPENDIR: - process_opendir(); - break; - case SSH_FXP_READDIR: - process_readdir(); - break; - case SSH_FXP_REMOVE: - process_remove(); - break; - case SSH_FXP_MKDIR: - process_mkdir(); - break; - case SSH_FXP_RMDIR: - process_rmdir(); - break; - case SSH_FXP_REALPATH: - process_realpath(); - break; - case SSH_FXP_STAT: - process_stat(); - break; - case SSH_FXP_RENAME: - process_rename(); - break; - default: - error("Unknown message %d", type); - break; - } -} - -int -main(int ac, char **av) -{ - fd_set rset, wset; - int in, out, max; - ssize_t len, olen; - - handle_init(); - - in = dup(STDIN_FILENO); - out = dup(STDOUT_FILENO); - - max = 0; - if (in > max) - max = in; - if (out > max) - max = out; - - buffer_init(&iqueue); - buffer_init(&oqueue); - - for (;;) { - FD_ZERO(&rset); - FD_ZERO(&wset); - - FD_SET(in, &rset); - olen = buffer_len(&oqueue); - if (olen > 0) - FD_SET(out, &wset); - - if (select(max+1, &rset, &wset, NULL, NULL) < 0) { - if (errno == EINTR) - continue; - exit(2); - } - - /* copy stdin to iqueue */ - if (FD_ISSET(in, &rset)) { - char buf[4*4096]; - len = read(in, buf, sizeof buf); - if (len == 0) { - debug("read eof"); - exit(0); - } else if (len < 0) { - error("read error"); - exit(1); - } else { - buffer_append(&iqueue, buf, len); - } - } - /* send oqueue to stdout */ - if (FD_ISSET(out, &wset)) { - len = write(out, buffer_ptr(&oqueue), olen); - if (len < 0) { - error("write error"); - exit(1); - } else { - buffer_consume(&oqueue, len); - } - } - /* process requests from client */ - process(); - } -} |
