5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
23 #include "silcsftp_fs.h"
24 #include "sftp_util.h"
26 /* SFTP Server context */
29 SilcSFTPMonitors monitors;
30 SilcSFTPMonitor monitor;
31 void *monitor_context;
32 SilcSFTPFilesystem fs;
34 SilcSFTPErrorCallback error;
38 static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer);
40 /* General routine to send SFTP packet to the SFTP client. */
42 static void silc_sftp_send_packet(SilcSFTPServer sftp,
51 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
57 SILC_LOG_HEXDUMP(("SFTP packet to client"), silc_buffer_data(sftp->packet),
58 silc_buffer_len(sftp->packet));
61 while (silc_buffer_len(sftp->packet) > 0) {
62 ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
63 silc_buffer_len(sftp->packet));
65 SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
70 silc_buffer_pull(sftp->packet, ret);
74 silc_buffer_reset(sftp->packet);
77 /* Handles stream I/O */
79 static void silc_sftp_server_io(SilcStream stream, SilcStreamStatus status,
82 SilcSFTPServer sftp = context;
83 unsigned char inbuf[30720];
84 SilcBufferStruct packet;
88 case SILC_STREAM_CAN_READ:
89 SILC_LOG_DEBUG(("Reading data from stream"));
91 /* Read data from stream */
92 ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
95 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
97 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
101 /* Now process the SFTP packet */
102 silc_buffer_set(&packet, inbuf, ret);
103 silc_sftp_server_receive_process(context, &packet);
106 case SILC_STREAM_CAN_WRITE:
107 if (!silc_buffer_headlen(sftp->packet))
110 SILC_LOG_DEBUG(("Writing pending data to stream"));
112 /* Write pending data to stream */
113 silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
114 while (silc_buffer_len(sftp->packet) > 0) {
115 ret = silc_stream_write(stream, sftp->packet->data,
116 silc_buffer_len(sftp->packet));
118 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
119 silc_buffer_reset(sftp->packet);
124 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
125 silc_buffer_reset(sftp->packet);
133 silc_buffer_pull(sftp->packet, ret);
142 /* Sends error to the client */
144 static void silc_sftp_send_error(SilcSFTPServer sftp,
145 SilcSFTPStatus status,
148 SILC_LOG_DEBUG(("Send error %d", status));
150 silc_sftp_send_packet(sftp, SILC_SFTP_STATUS, 16,
152 SILC_STR_UI_INT(status),
153 SILC_STR_UI_INT(0), /* Error */
154 SILC_STR_UI_INT(0), /* Language tag */
158 /* Status callback */
160 static void silc_sftp_server_status(SilcSFTP sftp,
161 SilcSFTPStatus status,
163 const char *language_tag,
166 SilcSFTPServer server = (SilcSFTPServer)sftp;
167 SilcUInt32 id = SILC_PTR_TO_32(context);
170 SILC_LOG_DEBUG(("Status callback"));
171 SILC_LOG_DEBUG(("Request ID: %d", id));
177 mlen = strlen(message);
178 llen = strlen(language_tag);
180 silc_sftp_send_packet(server, SILC_SFTP_STATUS, 16 + mlen + llen,
182 SILC_STR_UI_INT(status),
183 SILC_STR_UI_INT(mlen),
184 SILC_STR_UI32_STRING(message),
185 SILC_STR_UI_INT(llen),
186 SILC_STR_UI32_STRING(language_tag),
190 /* Handle callback */
192 static void silc_sftp_server_handle(SilcSFTP sftp,
193 SilcSFTPStatus status,
194 SilcSFTPHandle handle,
197 SilcSFTPServer server = (SilcSFTPServer)sftp;
198 SilcUInt32 id = SILC_PTR_TO_32(context);
199 unsigned char *hdata;
200 SilcUInt32 hdata_len;
202 SILC_LOG_DEBUG(("Handle callback"));
203 SILC_LOG_DEBUG(("Request ID: %d", id));
205 if (status != SILC_SFTP_STATUS_OK) {
206 silc_sftp_send_error(server, status, id);
210 hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp,
213 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
217 silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len,
219 SILC_STR_UI_INT(hdata_len),
220 SILC_STR_UI_XNSTRING(hdata, hdata_len),
226 static void silc_sftp_server_data(SilcSFTP sftp,
227 SilcSFTPStatus status,
228 const unsigned char *data,
232 SilcSFTPServer server = (SilcSFTPServer)sftp;
233 SilcUInt32 id = SILC_PTR_TO_32(context);
235 SILC_LOG_DEBUG(("Data callback"));
236 SILC_LOG_DEBUG(("Request ID: %d", id));
238 if (status != SILC_SFTP_STATUS_OK) {
239 silc_sftp_send_error(server, status, id);
243 silc_sftp_send_packet(server, SILC_SFTP_DATA, 8 + data_len,
245 SILC_STR_UI_INT(data_len),
246 SILC_STR_UI_XNSTRING(data, data_len),
252 static void silc_sftp_server_name(SilcSFTP sftp,
253 SilcSFTPStatus status,
254 const SilcSFTPName name,
257 SilcSFTPServer server = (SilcSFTPServer)sftp;
258 SilcUInt32 id = SILC_PTR_TO_32(context);
261 SILC_LOG_DEBUG(("Name callback"));
262 SILC_LOG_DEBUG(("Request ID: %d", id));
264 if (status != SILC_SFTP_STATUS_OK) {
265 silc_sftp_send_error(server, status, id);
269 namebuf = silc_sftp_name_encode(name);
271 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
275 silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + silc_buffer_len(namebuf),
277 SILC_STR_DATA(silc_buffer_data(namebuf),
278 silc_buffer_len(namebuf)),
282 /* Attributes callback */
284 static void silc_sftp_server_attr(SilcSFTP sftp,
285 SilcSFTPStatus status,
286 const SilcSFTPAttributes attrs,
289 SilcSFTPServer server = (SilcSFTPServer)sftp;
290 SilcUInt32 id = SILC_PTR_TO_32(context);
293 SILC_LOG_DEBUG(("Attr callback"));
294 SILC_LOG_DEBUG(("Request ID: %d", id));
296 if (status != SILC_SFTP_STATUS_OK) {
297 silc_sftp_send_error(server, status, id);
301 attr_buf = silc_sftp_attr_encode(attrs);
303 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
307 silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + silc_buffer_len(attr_buf),
309 SILC_STR_DATA(silc_buffer_data(attr_buf),
310 silc_buffer_len(attr_buf)),
313 silc_buffer_free(attr_buf);
316 /* Extended callback */
318 static void silc_sftp_server_extended(SilcSFTP sftp,
319 SilcSFTPStatus status,
320 const unsigned char *data,
324 SilcSFTPServer server = (SilcSFTPServer)sftp;
325 SilcUInt32 id = SILC_PTR_TO_32(context);
327 SILC_LOG_DEBUG(("Extended callback"));
328 SILC_LOG_DEBUG(("Request ID: %d", id));
330 if (status != SILC_SFTP_STATUS_OK) {
331 silc_sftp_send_error(server, status, id);
335 silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len,
337 SILC_STR_UI_XNSTRING(data, data_len),
341 /* Starts SFTP server and returns context to it. This function returns the
342 allocated SFTP client context or NULL on error. The `send_packet' is called
343 by the library when it needs to send a packet. The `fs' is the
344 structure containing filesystem access callbacks. */
346 SilcSFTP silc_sftp_server_start(SilcStream stream,
347 SilcSchedule schedule,
348 SilcSFTPErrorCallback error_cb,
350 SilcSFTPFilesystem fs)
352 SilcSFTPServer server;
354 server = silc_calloc(1, sizeof(*server));
357 server->stream = stream;
358 server->error = error_cb;
359 server->context = context;
362 /* We handle the stream now */
363 silc_stream_set_notifier(stream, schedule, silc_sftp_server_io, server);
365 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
367 return (SilcSFTP)server;
370 /* Shutdown's the SFTP server. The caller is responsible of closing
371 the associated socket connection. The SFTP context is freed and is
372 invalid after this function returns. */
374 void silc_sftp_server_shutdown(SilcSFTP sftp)
376 SilcSFTPServer server = (SilcSFTPServer)sftp;
378 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
381 silc_buffer_free(server->packet);
385 /* Sets monitor callback */
387 void silc_sftp_server_set_monitor(SilcSFTP sftp,
388 SilcSFTPMonitors monitors,
389 SilcSFTPMonitor monitor,
392 SilcSFTPServer server = (SilcSFTPServer)sftp;
393 server->monitors = monitors;
394 server->monitor = monitor;
395 server->monitor_context = context;
398 /* Function that is called to process the incmoing SFTP packet. */
399 /* XXX Some day this will go away and we have automatic receive callbacks
400 for SilcSocketConnection API or SilcPacketContext API. */
402 static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer)
404 SilcSFTPServer server = (SilcSFTPServer)sftp;
406 char *filename = NULL, *path = NULL;
407 const unsigned char *payload = NULL;
408 SilcUInt32 payload_len;
410 SilcBufferStruct buf;
412 SilcSFTPAttributes attrs;
413 SilcSFTPHandle handle;
414 SilcSFTPMonitorDataStruct mdata;
416 SILC_LOG_DEBUG(("Start"));
418 /* Parse the packet */
419 type = silc_sftp_packet_decode(buffer, (unsigned char **)&payload,
424 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
426 memset(&mdata, 0, sizeof(mdata));
431 SilcSFTPVersion version;
433 SILC_LOG_DEBUG(("Init request"));
435 ret = silc_buffer_unformat(&buf,
436 SILC_STR_UI_INT(&version),
442 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
443 mdata.version = version;
444 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
445 server->monitor_context);
448 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
449 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
456 SilcSFTPFileOperation pflags;
457 unsigned char *attr_buf;
458 SilcUInt32 attr_len = 0;
459 SilcBufferStruct tmpbuf;
461 SILC_LOG_DEBUG(("Open request"));
463 ret = silc_buffer_unformat(&buf,
464 SILC_STR_UI_INT(&id),
465 SILC_STR_UI32_STRING_ALLOC(&filename),
466 SILC_STR_UI_INT(&pflags),
467 SILC_STR_UI32_NSTRING(&attr_buf,
474 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
475 attrs = silc_sftp_attr_decode(&tmpbuf);
479 attrs = silc_calloc(1, sizeof(*attrs));
485 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
486 mdata.name = filename;
487 mdata.pflags = pflags;
488 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
489 server->monitor_context);
493 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
494 attrs, silc_sftp_server_handle,
498 silc_sftp_attr_free(attrs);
502 case SILC_SFTP_CLOSE:
504 unsigned char *hdata;
505 SilcUInt32 hdata_len;
507 SILC_LOG_DEBUG(("Close request"));
509 ret = silc_buffer_unformat(&buf,
510 SILC_STR_UI_INT(&id),
511 SILC_STR_UI32_NSTRING(&hdata,
518 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
519 (const unsigned char *)hdata,
522 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
527 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
528 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
529 server->monitor_context);
532 /* Close operation */
533 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
534 silc_sftp_server_status, SILC_32_TO_PTR(id));
541 unsigned char *hdata;
542 SilcUInt32 hdata_len;
546 SILC_LOG_DEBUG(("Read request"));
548 ret = silc_buffer_unformat(&buf,
549 SILC_STR_UI_INT(&id),
550 SILC_STR_UI32_NSTRING(&hdata,
552 SILC_STR_UI_INT64(&offset),
553 SILC_STR_UI_INT(&len),
559 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
560 (const unsigned char *)hdata,
563 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
568 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
570 silc_sftp_server_data, SILC_32_TO_PTR(id));
573 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
574 mdata.offset = offset;
575 mdata.data_len = len;
576 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
577 server->monitor_context);
582 case SILC_SFTP_WRITE:
584 unsigned char *hdata;
585 SilcUInt32 hdata_len;
590 SILC_LOG_DEBUG(("Read request"));
592 ret = silc_buffer_unformat(&buf,
593 SILC_STR_UI_INT(&id),
594 SILC_STR_UI32_NSTRING(&hdata,
596 SILC_STR_UI_INT64(&offset),
597 SILC_STR_UI32_NSTRING(&data,
604 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
605 (const unsigned char *)hdata,
608 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
612 /* Write operation */
613 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
614 (const unsigned char *)data, data_len,
615 silc_sftp_server_status, SILC_32_TO_PTR(id));
618 if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
619 mdata.offset = offset;
620 mdata.data_len = data_len;
621 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
622 server->monitor_context);
627 case SILC_SFTP_REMOVE:
629 SILC_LOG_DEBUG(("Remove request"));
631 ret = silc_buffer_unformat(&buf,
632 SILC_STR_UI_INT(&id),
633 SILC_STR_UI32_STRING_ALLOC(&filename),
639 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
640 mdata.name = filename;
641 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
642 server->monitor_context);
645 /* Remove operation */
646 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
647 silc_sftp_server_status, SILC_32_TO_PTR(id));
653 case SILC_SFTP_RENAME:
655 char *newname = NULL;
657 SILC_LOG_DEBUG(("Rename request"));
659 ret = silc_buffer_unformat(&buf,
660 SILC_STR_UI_INT(&id),
661 SILC_STR_UI32_STRING_ALLOC(&filename),
662 SILC_STR_UI32_STRING_ALLOC(&newname),
668 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
669 mdata.name = filename;
670 mdata.name2 = newname;
671 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
672 server->monitor_context);
675 /* Rename operation */
676 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
678 silc_sftp_server_status, SILC_32_TO_PTR(id));
685 case SILC_SFTP_MKDIR:
687 unsigned char *attr_buf;
688 SilcUInt32 attr_len = 0;
689 SilcBufferStruct tmpbuf;
691 SILC_LOG_DEBUG(("Mkdir request"));
693 ret = silc_buffer_unformat(&buf,
694 SILC_STR_UI_INT(&id),
695 SILC_STR_UI32_STRING_ALLOC(&path),
696 SILC_STR_UI32_NSTRING(&attr_buf,
703 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
704 attrs = silc_sftp_attr_decode(&tmpbuf);
708 attrs = silc_calloc(1, sizeof(*attrs));
714 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
716 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
717 server->monitor_context);
720 /* Mkdir operation */
721 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
722 silc_sftp_server_status, SILC_32_TO_PTR(id));
724 silc_sftp_attr_free(attrs);
729 case SILC_SFTP_RMDIR:
731 SILC_LOG_DEBUG(("Rmdir request"));
733 ret = silc_buffer_unformat(&buf,
734 SILC_STR_UI_INT(&id),
735 SILC_STR_UI32_STRING_ALLOC(&path),
741 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
743 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
744 server->monitor_context);
747 /* Rmdir operation */
748 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
749 silc_sftp_server_status, SILC_32_TO_PTR(id));
755 case SILC_SFTP_OPENDIR:
757 SILC_LOG_DEBUG(("Opendir request"));
759 ret = silc_buffer_unformat(&buf,
760 SILC_STR_UI_INT(&id),
761 SILC_STR_UI32_STRING_ALLOC(&path),
767 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
769 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
770 server->monitor_context);
773 /* Opendir operation */
774 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
775 silc_sftp_server_handle, SILC_32_TO_PTR(id));
781 case SILC_SFTP_READDIR:
783 unsigned char *hdata;
784 SilcUInt32 hdata_len;
786 SILC_LOG_DEBUG(("Readdir request"));
788 ret = silc_buffer_unformat(&buf,
789 SILC_STR_UI_INT(&id),
790 SILC_STR_UI32_NSTRING(&hdata,
797 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
798 (const unsigned char *)hdata,
801 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
806 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
807 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
808 server->monitor_context);
811 /* Readdir operation */
812 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
813 silc_sftp_server_name, SILC_32_TO_PTR(id));
819 SILC_LOG_DEBUG(("Stat request"));
821 ret = silc_buffer_unformat(&buf,
822 SILC_STR_UI_INT(&id),
823 SILC_STR_UI32_STRING_ALLOC(&path),
829 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
831 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
832 server->monitor_context);
836 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
837 silc_sftp_server_attr, SILC_32_TO_PTR(id));
843 case SILC_SFTP_LSTAT:
845 SILC_LOG_DEBUG(("Lstat request"));
847 ret = silc_buffer_unformat(&buf,
848 SILC_STR_UI_INT(&id),
849 SILC_STR_UI32_STRING_ALLOC(&path),
855 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
857 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
858 server->monitor_context);
861 /* Lstat operation */
862 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
863 silc_sftp_server_attr, SILC_32_TO_PTR(id));
869 case SILC_SFTP_FSTAT:
871 unsigned char *hdata;
872 SilcUInt32 hdata_len;
874 SILC_LOG_DEBUG(("Fstat request"));
876 ret = silc_buffer_unformat(&buf,
877 SILC_STR_UI_INT(&id),
878 SILC_STR_UI32_NSTRING(&hdata,
885 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
886 (const unsigned char *)hdata,
889 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
894 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
895 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
896 server->monitor_context);
899 /* Fstat operation */
900 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
901 silc_sftp_server_attr, SILC_32_TO_PTR(id));
905 case SILC_SFTP_SETSTAT:
907 unsigned char *attr_buf;
908 SilcUInt32 attr_len = 0;
909 SilcBufferStruct tmpbuf;
911 SILC_LOG_DEBUG(("Setstat request"));
913 ret = silc_buffer_unformat(&buf,
914 SILC_STR_UI_INT(&id),
915 SILC_STR_UI32_STRING_ALLOC(&path),
916 SILC_STR_UI32_NSTRING(&attr_buf,
923 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
924 attrs = silc_sftp_attr_decode(&tmpbuf);
928 attrs = silc_calloc(1, sizeof(*attrs));
934 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
936 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
937 server->monitor_context);
940 /* Setstat operation */
941 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
942 silc_sftp_server_status, SILC_32_TO_PTR(id));
944 silc_sftp_attr_free(attrs);
949 case SILC_SFTP_FSETSTAT:
951 unsigned char *hdata, *attr_buf;
952 SilcUInt32 hdata_len, attr_len = 0;
953 SilcBufferStruct tmpbuf;
955 SILC_LOG_DEBUG(("Fsetstat request"));
957 ret = silc_buffer_unformat(&buf,
958 SILC_STR_UI_INT(&id),
959 SILC_STR_UI32_NSTRING(&hdata,
961 SILC_STR_UI32_NSTRING(&attr_buf,
968 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
969 attrs = silc_sftp_attr_decode(&tmpbuf);
973 attrs = silc_calloc(1, sizeof(*attrs));
979 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
980 (const unsigned char *)hdata,
983 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
988 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
989 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
990 server->monitor_context);
993 /* Fsetstat operation */
994 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
996 silc_sftp_server_status,
999 silc_sftp_attr_free(attrs);
1003 case SILC_SFTP_READLINK:
1005 SILC_LOG_DEBUG(("Readlink request"));
1007 ret = silc_buffer_unformat(&buf,
1008 SILC_STR_UI_INT(&id),
1009 SILC_STR_UI32_STRING_ALLOC(&path),
1015 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
1017 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
1018 server->monitor_context);
1021 /* Readlink operation */
1022 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
1023 silc_sftp_server_name, SILC_32_TO_PTR(id));
1029 case SILC_SFTP_SYMLINK:
1031 char *target = NULL;
1033 SILC_LOG_DEBUG(("Symlink request"));
1035 ret = silc_buffer_unformat(&buf,
1036 SILC_STR_UI_INT(&id),
1037 SILC_STR_UI32_STRING_ALLOC(&path),
1038 SILC_STR_UI32_STRING_ALLOC(&target),
1044 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
1046 mdata.name2 = target;
1047 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
1048 server->monitor_context);
1051 /* Symlink operation */
1052 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
1053 silc_sftp_server_status, SILC_32_TO_PTR(id));
1060 case SILC_SFTP_REALPATH:
1062 SILC_LOG_DEBUG(("Realpath request"));
1064 ret = silc_buffer_unformat(&buf,
1065 SILC_STR_UI_INT(&id),
1066 SILC_STR_UI32_STRING_ALLOC(&path),
1072 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
1074 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
1075 server->monitor_context);
1078 /* Realpath operation */
1079 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
1080 silc_sftp_server_name, SILC_32_TO_PTR(id));
1086 case SILC_SFTP_EXTENDED:
1088 char *request = NULL;
1089 unsigned char *data;
1090 SilcUInt32 data_len;
1092 SILC_LOG_DEBUG(("Extended request"));
1094 ret = silc_buffer_unformat(&buf,
1095 SILC_STR_UI_INT(&id),
1096 SILC_STR_UI32_STRING_ALLOC(&request),
1101 data_len = 8 + strlen(request);
1102 silc_buffer_pull(&buf, data_len);
1103 ret = silc_buffer_unformat(&buf,
1104 SILC_STR_DATA(&data, silc_buffer_len(&buf)),
1108 data_len = silc_buffer_len(&buf);
1111 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1112 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1113 server->monitor_context);
1116 /* Extended operation */
1117 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1118 request, data, data_len,
1119 silc_sftp_server_extended,
1120 SILC_32_TO_PTR(id));
1133 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);