+++ /dev/null
-/*
-
- sftp_client.c
-
- Author: Pekka Riikonen <priikone@silcnet.org>
-
- Copyright (C) 2001 - 2007 Pekka Riikonen
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
-*/
-/* $Id$ */
-
-#include "silc.h"
-#include "silcsftp.h"
-#include "sftp_util.h"
-
-/* Request context. Every request will allocate this context and set
- the correct callback function according the `type' field. */
-typedef struct SilcSFTPRequestStruct {
- struct SilcSFTPRequestStruct *next;
- SilcSFTPStatusCallback status;
- SilcSFTPHandleCallback handle;
- SilcSFTPDataCallback data;
- SilcSFTPNameCallback name;
- SilcSFTPAttrCallback attr;
- SilcSFTPExtendedCallback extended;
- void *context;
- SilcUInt32 id;
- SilcSFTPPacket type;
-} *SilcSFTPRequest;
-
-/* SFTP client context */
-typedef struct {
- SilcStream stream;
- SilcSchedule schedule;
- SilcSFTPVersionCallback version;
- SilcSFTPErrorCallback error;
- void *context;
- SilcList requests;
- SilcBuffer packet;
- SilcUInt32 id;
-} *SilcSFTPClient;
-
-/* File handle */
-struct SilcSFTPHandleStruct {
- unsigned char *data;
- SilcUInt32 data_len;
-};
-
-static void silc_sftp_client_receive_process(SilcSFTP context,
- SilcBuffer buffer);
-
-/* Creates SilcSFTPHandle and returns pointer to it. The caller must free
- the context. */
-
-static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
- SilcUInt32 data_len)
-{
- SilcSFTPHandle handle;
-
- handle = silc_calloc(1, sizeof(*handle));
- if (!handle)
- return NULL;
- handle->data = silc_calloc(data_len, sizeof(*handle->data));
- if (!handle->data)
- return NULL;
- memcpy(handle->data, data, data_len);
- handle->data_len = data_len;
-
- return handle;
-}
-
-/* Deletes the handle indicated by the `handle'. */
-
-static void silc_sftp_handle_delete(SilcSFTPHandle handle)
-{
- silc_free(handle->data);
- silc_free(handle);
-}
-
-/* Returns the handle data of the `handle' to the `data' pointer. */
-
-static void silc_sftp_handle_get(SilcSFTPHandle handle,
- const unsigned char **data,
- SilcUInt32 *data_len)
-{
- *data = (const unsigned char *)handle->data;
- *data_len = handle->data_len;
-}
-
-/* Generic routine to send SFTP packet to the SFTP server. */
-
-static void silc_sftp_send_packet(SilcSFTPClient sftp,
- SilcSFTPPacket type,
- SilcUInt32 len, ...)
-{
- SilcBuffer tmp;
- va_list vp;
- int ret;
-
- va_start(vp, len);
- tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
- va_end(vp);
- if (!tmp)
- return;
- sftp->packet = tmp;
-
- SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
- silc_buffer_len(sftp->packet));
-
- /* Send the packet */
- while (silc_buffer_len(sftp->packet) > 0) {
- ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
- silc_buffer_len(sftp->packet));
- if (ret == -2) {
- SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
- sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_NO_CONNECTION,
- sftp->context);
- silc_buffer_reset(sftp->packet);
- return;
- }
- if (ret == 0) {
- sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_EOF, sftp->context);
- silc_buffer_reset(sftp->packet);
- return;
- }
- if (ret == -1)
- return;
-
- silc_buffer_pull(sftp->packet, ret);
- }
-
- /* Clear packet */
- silc_buffer_reset(sftp->packet);
-}
-
-/* Finds request by request ID. */
-
-static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp,
- SilcUInt32 id)
-{
- SilcSFTPRequest req;
-
- SILC_LOG_DEBUG(("Finding request ID: %d", id));
-
- silc_list_start(sftp->requests);
- while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
- if (req->id == id)
- return req;
- }
-
- SILC_LOG_DEBUG(("Unknown request ID %d", id));
-
- return NULL;
-}
-
-/* Function used to call the request callback indicated by the `req'. The
- `status' will be sent to the callback function as the status of the
- operation. The variable argument list includes the status and req->type
- specific data. */
-
-static void silc_sftp_call_request(SilcSFTPClient sftp,
- SilcSFTPRequest req,
- SilcSFTPPacket type,
- SilcSFTPStatus status, ...)
-{
- va_list vp;
-
- SILC_LOG_DEBUG(("Start"));
-
- va_start(vp, status);
-
- switch (req->type) {
- case SILC_SFTP_READ:
- {
- /* Data returned */
- unsigned char *data;
- SilcUInt32 data_len;
-
- if (status != SILC_SFTP_STATUS_OK) {
- if (req->data)
- (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
- break;
- }
-
- data = (unsigned char *)va_arg(vp, unsigned char *);
- data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
-
- if (req->data)
- (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
- data_len, req->context);
- }
- break;
-
- case SILC_SFTP_OPEN:
- case SILC_SFTP_OPENDIR:
- {
- /* Handle returned */
- SilcSFTPHandle handle;
- unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- if (status != SILC_SFTP_STATUS_OK) {
- if (req->handle)
- (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
- break;
- }
-
- hdata = (unsigned char *)va_arg(vp, unsigned char *);
- hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
- handle = silc_sftp_handle_create(hdata, hdata_len);
- if (!handle) {
- if (req->handle)
- (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
- break;
- }
-
- if (req->handle)
- (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
- }
- break;
-
- case SILC_SFTP_CLOSE:
- case SILC_SFTP_WRITE:
- case SILC_SFTP_REMOVE:
- case SILC_SFTP_RENAME:
- case SILC_SFTP_MKDIR:
- case SILC_SFTP_RMDIR:
- case SILC_SFTP_SETSTAT:
- case SILC_SFTP_FSETSTAT:
- case SILC_SFTP_SYMLINK:
- {
- /* Status returned */
- char *message, *language_tag;
-
- message = (char *)va_arg(vp, char *);
- language_tag = (char *)va_arg(vp, char *);
-
- if (req->status)
- (*req->status)((SilcSFTP)sftp, status, (const char *)message,
- (const char *)language_tag, req->context);
- }
- break;
-
- case SILC_SFTP_STAT:
- case SILC_SFTP_LSTAT:
- case SILC_SFTP_FSTAT:
- {
- /* Attributes returned */
- SilcSFTPAttributes attr;
-
- if (status != SILC_SFTP_STATUS_OK) {
- if (req->attr)
- (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
- break;
- }
-
- attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
-
- if (req->attr)
- (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
- req->context);
- }
- break;
-
- case SILC_SFTP_READDIR:
- case SILC_SFTP_REALPATH:
- case SILC_SFTP_READLINK:
- {
- /* Name(s) returned */
- SilcSFTPName name;
-
- if (status != SILC_SFTP_STATUS_OK) {
- if (req->name)
- (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
- break;
- }
-
- name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
-
- if (req->name)
- (*req->name)((SilcSFTP)sftp, status, name, req->context);
- }
- break;
-
- case SILC_SFTP_EXTENDED:
- {
- /* Extended reply returned */
- unsigned char *data;
- SilcUInt32 data_len;
-
- if (status != SILC_SFTP_STATUS_OK) {
- if (req->extended)
- (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
- break;
- }
-
- data = (unsigned char *)va_arg(vp, unsigned char *);
- data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
-
- if (req->extended)
- (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
- data_len, req->context);
- }
- break;
-
- default:
- SILC_LOG_DEBUG(("Unknown request type %d", req->type));
- break;
- }
-
- /* Remove this request */
- silc_list_del(sftp->requests, req);
- silc_free(req);
-
- va_end(vp);
-}
-
-/* Handles stream I/O */
-
-static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status,
- void *context)
-{
- SilcSFTPClient sftp = context;
- unsigned char inbuf[65536];
- SilcBufferStruct packet;
- int ret;
-
- switch (status) {
- case SILC_STREAM_CAN_READ:
- SILC_LOG_DEBUG(("Reading data from stream"));
-
- /* Read data from stream */
- ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
- if (ret <= 0) {
- if (ret == 0)
- sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
- if (ret == -2)
- sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
- return;
- }
-
- SILC_LOG_DEBUG(("Read %d bytes", ret));
-
- /* Now process the SFTP packet */
- silc_buffer_set(&packet, inbuf, ret);
- silc_sftp_client_receive_process(context, &packet);
- break;
-
- case SILC_STREAM_CAN_WRITE:
- if (!silc_buffer_headlen(sftp->packet))
- return;
-
- SILC_LOG_DEBUG(("Writing pending data to stream"));
-
- /* Write pending data to stream */
- silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
- while (silc_buffer_len(sftp->packet) > 0) {
- ret = silc_stream_write(stream, sftp->packet->data,
- silc_buffer_len(sftp->packet));
- if (ret == 0) {
- sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
- silc_buffer_reset(sftp->packet);
- return;
- }
-
- if (ret == -2) {
- sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
- silc_buffer_reset(sftp->packet);
- return;
- }
-
- if (ret == -1)
- return;
-
- /* Wrote data */
- silc_buffer_pull(sftp->packet, ret);
- }
- break;
-
- default:
- break;
- }
-}
-
-/* Starts SFTP client and returns context for it. */
-
-SilcSFTP silc_sftp_client_start(SilcStream stream,
- SilcSchedule schedule,
- SilcSFTPVersionCallback version_cb,
- SilcSFTPErrorCallback error_cb,
- void *context)
-{
- SilcSFTPClient sftp;
-
- SILC_LOG_DEBUG(("Starting SFTP client"));
-
- if (!schedule)
- schedule = silc_schedule_get_global();
-
- if (!stream)
- return NULL;
-
- sftp = silc_calloc(1, sizeof(*sftp));
- if (!sftp)
- return NULL;
- sftp->stream = stream;
- sftp->version = version_cb;
- sftp->error = error_cb;
- sftp->context = context;
- sftp->schedule = schedule;
- silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
-
- /* We handle the stream now */
- silc_stream_set_notifier(stream, schedule, silc_sftp_client_io, sftp);
-
- /* Send the SFTP session initialization to the server */
- silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
- SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
- SILC_STR_END);
-
- return (SilcSFTP)sftp;
-}
-
-/* Shutdown's the SFTP client. The caller is responsible of closing
- the associated socket connection. The SFTP context is freed and is
- invalid after this function returns. */
-
-void silc_sftp_client_shutdown(SilcSFTP context)
-{
- SilcSFTPClient sftp = (SilcSFTPClient)context;
-
- silc_stream_set_notifier(sftp->stream, sftp->schedule, NULL, NULL);
- if (sftp->packet)
- silc_buffer_free(sftp->packet);
- silc_free(sftp);
-}
-
-/* Function that is called to process the incmoing SFTP packet. */
-
-void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer)
-{
- SilcSFTPClient sftp = (SilcSFTPClient)context;
- SilcSFTPRequest req;
- SilcSFTPPacket type;
- unsigned char *payload = NULL;
- SilcUInt32 payload_len;
- int ret;
- SilcBufferStruct buf;
- SilcUInt32 id;
-
- SILC_LOG_DEBUG(("Process SFTP packet"));
-
- /* Parse the packet */
- type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
- if (type <= 0)
- return;
-
- silc_buffer_set(&buf, payload, payload_len);
-
- switch (type) {
- case SILC_SFTP_DATA:
- {
- unsigned char *data = NULL;
- SilcUInt32 data_len = 0;
-
- SILC_LOG_DEBUG(("Data packet"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_UI32_NSTRING(&data, &data_len),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- /* Get request */
- req = silc_sftp_find_request(sftp, id);
- if (!req)
- break;
-
- /* Call the callback */
- silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
- data, data_len);
- }
- break;
-
- case SILC_SFTP_VERSION:
- {
- SilcSFTPVersion version;
-
- SILC_LOG_DEBUG(("Version packet"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&version),
- SILC_STR_END);
- if (ret < 0) {
- (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
- sftp->context);
- break;
- }
-
- /* Call the callback */
- (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
- sftp->context);
- }
- break;
-
- case SILC_SFTP_STATUS:
- {
- SilcUInt32 status;
- char *message = NULL, *language_tag = NULL;
-
- SILC_LOG_DEBUG(("Status packet"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_UI_INT(&status),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- if (status != SILC_SFTP_STATUS_OK) {
- silc_buffer_pull(&buf, 8);
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI32_STRING_ALLOC(&message),
- SILC_STR_UI32_STRING_ALLOC(&language_tag),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- silc_buffer_push(&buf, 8);
- }
-
- /* Get request */
- req = silc_sftp_find_request(sftp, id);
- if (!req) {
- silc_free(message);
- silc_free(language_tag);
- break;
- }
-
- /* Call the callback */
- silc_sftp_call_request(sftp, req, type, status, message, language_tag);
-
- silc_free(message);
- silc_free(language_tag);
- }
- break;
-
- case SILC_SFTP_HANDLE:
- {
- unsigned char *handle = NULL;
- SilcUInt32 handle_len;
-
- SILC_LOG_DEBUG(("Handle packet"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_UI32_NSTRING(&handle,
- &handle_len),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- /* Get request */
- req = silc_sftp_find_request(sftp, id);
- if (!req)
- break;
-
- /* Call the callback */
- silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
- handle, handle_len);
- }
- break;
-
- case SILC_SFTP_NAME:
- {
- SilcUInt32 count;
- SilcSFTPName name = NULL;
-
- SILC_LOG_DEBUG(("Name packet"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_UI_INT(&count),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- /* Get request */
- req = silc_sftp_find_request(sftp, id);
- if (!req)
- break;
-
- silc_buffer_pull(&buf, 8);
- name = silc_sftp_name_decode(count, &buf);
- if (!name)
- break;
- silc_buffer_push(&buf, 8);
-
- /* Call the callback */
- silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
- silc_sftp_name_free(name);
- }
- break;
-
- case SILC_SFTP_ATTRS:
- {
- SilcSFTPAttributes attr = NULL;
- unsigned char *data;
- SilcBufferStruct tmpbuf;
-
- SILC_LOG_DEBUG(("Attributes packet"));
-
- ret =
- silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_DATA(&data, silc_buffer_len(&buf) - 4),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- /* Get request */
- req = silc_sftp_find_request(sftp, id);
- if (!req)
- break;
-
- silc_buffer_set(&tmpbuf, data, silc_buffer_len(&buf) - 4);
- attr = silc_sftp_attr_decode(&tmpbuf);
- if (!attr)
- break;
-
- /* Call the callback */
- silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
- }
- break;
-
- case SILC_SFTP_EXTENDED_REPLY:
- {
- unsigned char *data = NULL;
-
- SILC_LOG_DEBUG(("Extended reply packet"));
-
- ret = silc_buffer_unformat(&buf,
- SILC_STR_UI_INT(&id),
- SILC_STR_DATA(&data,
- silc_buffer_len(&buf) - 4),
- SILC_STR_END);
- if (ret < 0)
- break;
-
- /* Get request */
- req = silc_sftp_find_request(sftp, id);
- if (!req)
- break;
-
- /* Call the callback */
- silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
- data, silc_buffer_len(&buf) - 4);
- }
- break;
-
- default:
- break;
- }
-}
-
-void silc_sftp_open(SilcSFTP sftp,
- const char *filename,
- SilcSFTPFileOperation pflags,
- SilcSFTPAttributes attrs,
- SilcSFTPHandleCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcBuffer attrs_buf;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Open request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_OPEN;
- req->handle = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- attrs_buf = silc_sftp_attr_encode(attrs);
- if (!attrs_buf)
- return;
- len = 4 + 4 + strlen(filename) + 4 + silc_buffer_len(attrs_buf);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(filename)),
- SILC_STR_UI32_STRING(filename),
- SILC_STR_UI_INT(pflags),
- SILC_STR_UI_XNSTRING(attrs_buf->data,
- silc_buffer_len(attrs_buf)),
- SILC_STR_END);
-
- silc_buffer_free(attrs_buf);
-}
-
-void silc_sftp_close(SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- const unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- SILC_LOG_DEBUG(("Close request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_CLOSE;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- silc_sftp_handle_get(handle, &hdata, &hdata_len);
- len = 4 + 4 + hdata_len;
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(hdata_len),
- SILC_STR_UI_XNSTRING(hdata, hdata_len),
- SILC_STR_END);
- silc_sftp_handle_delete(handle);
-}
-
-void silc_sftp_read(SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcUInt64 offset,
- SilcUInt32 len,
- SilcSFTPDataCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len2 = 0;
- const unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- SILC_LOG_DEBUG(("Read request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_READ;
- req->data = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- silc_sftp_handle_get(handle, &hdata, &hdata_len);
- len2 = 4 + 4 + hdata_len + 8 + 4;
-
- silc_sftp_send_packet(client, req->type, len2,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(hdata_len),
- SILC_STR_UI_XNSTRING(hdata, hdata_len),
- SILC_STR_UI_INT64(offset),
- SILC_STR_UI_INT(len),
- SILC_STR_END);
-}
-
-void silc_sftp_write(SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcUInt64 offset,
- const unsigned char *data,
- SilcUInt32 data_len,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- const unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- SILC_LOG_DEBUG(("Write request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_WRITE;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- silc_sftp_handle_get(handle, &hdata, &hdata_len);
- len = 4 + 4 + hdata_len + 8 + 4 + data_len;
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(hdata_len),
- SILC_STR_UI_XNSTRING(hdata, hdata_len),
- SILC_STR_UI_INT64(offset),
- SILC_STR_UI_INT(data_len),
- SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_END);
-}
-
-void silc_sftp_remove(SilcSFTP sftp,
- const char *filename,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Remove request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_REMOVE;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(filename);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(filename)),
- SILC_STR_UI32_STRING(filename),
- SILC_STR_END);
-}
-
-void silc_sftp_rename(SilcSFTP sftp,
- const char *oldname,
- const char *newname,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Rename request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_RENAME;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(oldname)),
- SILC_STR_UI32_STRING(oldname),
- SILC_STR_UI_INT(strlen(newname)),
- SILC_STR_UI32_STRING(newname),
- SILC_STR_END);
-}
-
-void silc_sftp_mkdir(SilcSFTP sftp,
- const char *path,
- SilcSFTPAttributes attrs,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- SilcBuffer attrs_buf;
-
- SILC_LOG_DEBUG(("Mkdir request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_MKDIR;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- attrs_buf = silc_sftp_attr_encode(attrs);
- if (!attrs_buf)
- return;
- len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_UI_XNSTRING(attrs_buf->data,
- silc_buffer_len(attrs_buf)),
- SILC_STR_END);
-
- silc_buffer_free(attrs_buf);
-}
-
-void silc_sftp_rmdir(SilcSFTP sftp,
- const char *path,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Rmdir request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_RMDIR;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(path);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_END);
-}
-
-void silc_sftp_opendir(SilcSFTP sftp,
- const char *path,
- SilcSFTPHandleCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Opendir request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_OPENDIR;
- req->handle = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(path);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_END);
-}
-
-void silc_sftp_readdir(SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPNameCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- const unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- SILC_LOG_DEBUG(("Readdir request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_READDIR;
- req->name = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- silc_sftp_handle_get(handle, &hdata, &hdata_len);
- len = 4 + 4 + hdata_len;
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(hdata_len),
- SILC_STR_UI_XNSTRING(hdata, hdata_len),
- SILC_STR_END);
-}
-
-void silc_sftp_stat(SilcSFTP sftp,
- const char *path,
- SilcSFTPAttrCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Stat request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_STAT;
- req->attr = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(path);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_END);
-}
-
-void silc_sftp_lstat(SilcSFTP sftp,
- const char *path,
- SilcSFTPAttrCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Lstat request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_LSTAT;
- req->attr = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(path);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_END);
-}
-
-void silc_sftp_fstat(SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPAttrCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- const unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- SILC_LOG_DEBUG(("Fstat request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_FSTAT;
- req->attr = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- silc_sftp_handle_get(handle, &hdata, &hdata_len);
- len = 4 + 4 + hdata_len;
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(hdata_len),
- SILC_STR_UI_XNSTRING(hdata, hdata_len),
- SILC_STR_END);
-}
-
-void silc_sftp_setstat(SilcSFTP sftp,
- const char *path,
- SilcSFTPAttributes attrs,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- SilcBuffer attrs_buf;
-
- SILC_LOG_DEBUG(("Setstat request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_SETSTAT;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- attrs_buf = silc_sftp_attr_encode(attrs);
- if (!attrs_buf)
- return;
- len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_UI_XNSTRING(attrs_buf->data,
- silc_buffer_len(attrs_buf)),
- SILC_STR_END);
-
- silc_buffer_free(attrs_buf);
-}
-
-void silc_sftp_fsetstat(SilcSFTP sftp,
- SilcSFTPHandle handle,
- SilcSFTPAttributes attrs,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
- SilcBuffer attrs_buf;
- const unsigned char *hdata;
- SilcUInt32 hdata_len;
-
- SILC_LOG_DEBUG(("Fsetstat request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_FSETSTAT;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- silc_sftp_handle_get(handle, &hdata, &hdata_len);
- attrs_buf = silc_sftp_attr_encode(attrs);
- if (!attrs_buf)
- return;
- len = 4 + 4 + hdata_len + silc_buffer_len(attrs_buf);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(hdata_len),
- SILC_STR_UI_XNSTRING(hdata, hdata_len),
- SILC_STR_UI_XNSTRING(attrs_buf->data,
- silc_buffer_len(attrs_buf)),
- SILC_STR_END);
-
- silc_buffer_free(attrs_buf);
-}
-
-void silc_sftp_readlink(SilcSFTP sftp,
- const char *path,
- SilcSFTPNameCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Readlink request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_READLINK;
- req->name = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(path);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_END);
-}
-
-void silc_sftp_symlink(SilcSFTP sftp,
- const char *linkpath,
- const char *targetpath,
- SilcSFTPStatusCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Symlink request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_SYMLINK;
- req->status = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(linkpath)),
- SILC_STR_UI32_STRING(linkpath),
- SILC_STR_UI_INT(strlen(targetpath)),
- SILC_STR_UI32_STRING(targetpath),
- SILC_STR_END);
-}
-
-void silc_sftp_realpath(SilcSFTP sftp,
- const char *path,
- SilcSFTPNameCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Realpath request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_REALPATH;
- req->name = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(path);
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(path)),
- SILC_STR_UI32_STRING(path),
- SILC_STR_END);
-}
-
-void silc_sftp_extended(SilcSFTP sftp,
- const char *request,
- const unsigned char *data,
- SilcUInt32 data_len,
- SilcSFTPExtendedCallback callback,
- void *context)
-{
- SilcSFTPClient client = (SilcSFTPClient)sftp;
- SilcSFTPRequest req;
- SilcUInt32 len = 0;
-
- SILC_LOG_DEBUG(("Extended request"));
-
- req = silc_calloc(1, sizeof(*req));
- if (!req)
- return;
- req->id = client->id++;
- req->type = SILC_SFTP_WRITE;
- req->extended = callback;
- req->context = context;
- silc_list_add(client->requests, req);
-
- len = 4 + 4 + strlen(request) + data_len;
-
- silc_sftp_send_packet(client, req->type, len,
- SILC_STR_UI_INT(req->id),
- SILC_STR_UI_INT(strlen(request)),
- SILC_STR_UI32_STRING(request),
- SILC_STR_UI_XNSTRING(data, data_len),
- SILC_STR_END);
-}