version 1.43, 2003/06/25 22:39:36 |
version 1.43.2.2, 2004/08/19 22:37:32 |
|
|
/* |
/* |
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. |
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Permission to use, copy, modify, and distribute this software for any |
* modification, are permitted provided that the following conditions |
* purpose with or without fee is hereby granted, provided that the above |
* are met: |
* copyright notice and this permission notice appear in all copies. |
* 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 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
* 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" |
#include "includes.h" |
RCSID("$OpenBSD$"); |
RCSID("$OpenBSD$"); |
|
|
} |
} |
|
|
static int |
static int |
handle_new(int use, char *name, int fd, DIR *dirp) |
handle_new(int use, const char *name, int fd, DIR *dirp) |
{ |
{ |
int i; |
int i; |
|
|
|
|
} |
} |
|
|
static int |
static int |
handle_from_string(char *handle, u_int hlen) |
handle_from_string(const char *handle, u_int hlen) |
{ |
{ |
int val; |
int val; |
|
|
|
|
} |
} |
|
|
static void |
static void |
send_status(u_int32_t id, u_int32_t error) |
send_status(u_int32_t id, u_int32_t status) |
{ |
{ |
Buffer msg; |
Buffer msg; |
const char *status_messages[] = { |
const char *status_messages[] = { |
|
|
"Unknown error" /* Others */ |
"Unknown error" /* Others */ |
}; |
}; |
|
|
TRACE("sent status id %u error %u", id, error); |
TRACE("sent status id %u error %u", id, status); |
buffer_init(&msg); |
buffer_init(&msg); |
buffer_put_char(&msg, SSH2_FXP_STATUS); |
buffer_put_char(&msg, SSH2_FXP_STATUS); |
buffer_put_int(&msg, id); |
buffer_put_int(&msg, id); |
buffer_put_int(&msg, error); |
buffer_put_int(&msg, status); |
if (version >= 3) { |
if (version >= 3) { |
buffer_put_cstring(&msg, |
buffer_put_cstring(&msg, |
status_messages[MIN(error,SSH2_FX_MAX)]); |
status_messages[MIN(status,SSH2_FX_MAX)]); |
buffer_put_cstring(&msg, ""); |
buffer_put_cstring(&msg, ""); |
} |
} |
send_msg(&msg); |
send_msg(&msg); |
buffer_free(&msg); |
buffer_free(&msg); |
} |
} |
static void |
static void |
send_data_or_handle(char type, u_int32_t id, char *data, int dlen) |
send_data_or_handle(char type, u_int32_t id, const char *data, int dlen) |
{ |
{ |
Buffer msg; |
Buffer msg; |
|
|
|
|
} |
} |
|
|
static void |
static void |
send_data(u_int32_t id, char *data, int dlen) |
send_data(u_int32_t id, const char *data, int dlen) |
{ |
{ |
TRACE("sent data id %u len %d", id, dlen); |
TRACE("sent data id %u len %d", id, dlen); |
send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); |
send_data_or_handle(SSH2_FXP_DATA, id, data, dlen); |
|
|
} |
} |
|
|
static void |
static void |
send_names(u_int32_t id, int count, Stat *stats) |
send_names(u_int32_t id, int count, const Stat *stats) |
{ |
{ |
Buffer msg; |
Buffer msg; |
int i; |
int i; |
|
|
} |
} |
|
|
static void |
static void |
send_attrib(u_int32_t id, Attrib *a) |
send_attrib(u_int32_t id, const Attrib *a) |
{ |
{ |
Buffer msg; |
Buffer msg; |
|
|
|
|
} |
} |
|
|
static struct timeval * |
static struct timeval * |
attrib_to_tv(Attrib *a) |
attrib_to_tv(const Attrib *a) |
{ |
{ |
static struct timeval tv[2]; |
static struct timeval tv[2]; |
|
|
|
|
status = errno_to_portable(errno); |
status = errno_to_portable(errno); |
else if (S_ISREG(sb.st_mode)) { |
else if (S_ISREG(sb.st_mode)) { |
/* Race-free rename of regular files */ |
/* Race-free rename of regular files */ |
if (link(oldpath, newpath) == -1) |
if (link(oldpath, newpath) == -1) { |
|
if (errno == EOPNOTSUPP) { |
|
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); |
status = errno_to_portable(errno); |
else if (unlink(oldpath) == -1) { |
|
status = errno_to_portable(errno); |
|
/* clean spare link */ |
/* clean spare link */ |
unlink(newpath); |
unlink(newpath); |
} else |
} else |
|
|
{ |
{ |
u_int32_t id; |
u_int32_t id; |
int len; |
int len; |
char link[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
char *path; |
char *path; |
|
|
id = get_int(); |
id = get_int(); |
path = get_string(NULL); |
path = get_string(NULL); |
TRACE("readlink id %u path %s", id, path); |
TRACE("readlink id %u path %s", id, path); |
if ((len = readlink(path, link, sizeof(link) - 1)) == -1) |
if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) |
send_status(id, errno_to_portable(errno)); |
send_status(id, errno_to_portable(errno)); |
else { |
else { |
Stat s; |
Stat s; |
|
|
link[len] = '\0'; |
buf[len] = '\0'; |
attrib_clear(&s.attrib); |
attrib_clear(&s.attrib); |
s.name = s.long_name = link; |
s.name = s.long_name = buf; |
send_names(id, 1, &s); |
send_names(id, 1, &s); |
} |
} |
xfree(path); |
xfree(path); |