5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 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.
21 #include "silcincludes.h"
23 #include "silcsftp_fs.h"
24 #include "sftp_util.h"
26 /* SFTP Server context */
28 SilcSFTPSendPacketCallback send_packet;
30 SilcSFTPMonitors monitors;
31 SilcSFTPMonitor monitor;
32 void *monitor_context;
33 SilcSFTPFilesystem fs;
37 /* General routine to send SFTP packet to the SFTP client. */
39 static void silc_sftp_send_packet(SilcSFTPServer sftp,
47 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
53 SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data,
57 (*sftp->send_packet)(sftp->packet, sftp->send_context);
60 sftp->packet->data = sftp->packet->tail = sftp->packet->head;
61 sftp->packet->len = 0;
64 /* Sends error to the client */
66 static void silc_sftp_send_error(SilcSFTPServer sftp,
67 SilcSFTPStatus status,
70 SILC_LOG_DEBUG(("Send error %d", status));
72 silc_sftp_send_packet(sftp, SILC_SFTP_STATUS, 16,
74 SILC_STR_UI_INT(status),
75 SILC_STR_UI_INT(0), /* Error */
76 SILC_STR_UI_INT(0), /* Language tag */
82 static void silc_sftp_server_status(SilcSFTP sftp,
83 SilcSFTPStatus status,
85 const char *language_tag,
88 SilcSFTPServer server = (SilcSFTPServer)sftp;
89 SilcUInt32 id = (SilcUInt32)context;
92 SILC_LOG_DEBUG(("Status callback"));
93 SILC_LOG_DEBUG(("Request ID: %d", id));
99 mlen = strlen(message);
100 llen = strlen(language_tag);
102 silc_sftp_send_packet(server, SILC_SFTP_STATUS, 16 + mlen + llen,
104 SILC_STR_UI_INT(status),
105 SILC_STR_UI_INT(mlen),
106 SILC_STR_UI32_STRING(message),
107 SILC_STR_UI_INT(llen),
108 SILC_STR_UI32_STRING(language_tag),
112 /* Handle callback */
114 static void silc_sftp_server_handle(SilcSFTP sftp,
115 SilcSFTPStatus status,
116 SilcSFTPHandle handle,
119 SilcSFTPServer server = (SilcSFTPServer)sftp;
120 SilcUInt32 id = (SilcUInt32)context;
121 unsigned char *hdata;
122 SilcUInt32 hdata_len;
124 SILC_LOG_DEBUG(("Handle callback"));
125 SILC_LOG_DEBUG(("Request ID: %d", id));
127 if (status != SILC_SFTP_STATUS_OK) {
128 silc_sftp_send_error(server, status, id);
132 hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp,
135 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
139 silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len,
141 SILC_STR_UI_INT(hdata_len),
142 SILC_STR_UI_XNSTRING(hdata, hdata_len),
148 static void silc_sftp_server_data(SilcSFTP sftp,
149 SilcSFTPStatus status,
150 const unsigned char *data,
154 SilcSFTPServer server = (SilcSFTPServer)sftp;
155 SilcUInt32 id = (SilcUInt32)context;
157 SILC_LOG_DEBUG(("Data callback"));
158 SILC_LOG_DEBUG(("Request ID: %d", id));
160 if (status != SILC_SFTP_STATUS_OK) {
161 silc_sftp_send_error(server, status, id);
165 silc_sftp_send_packet(server, SILC_SFTP_DATA, 8 + data_len,
167 SILC_STR_UI_INT(data_len),
168 SILC_STR_UI_XNSTRING(data, data_len),
174 static void silc_sftp_server_name(SilcSFTP sftp,
175 SilcSFTPStatus status,
176 const SilcSFTPName name,
179 SilcSFTPServer server = (SilcSFTPServer)sftp;
180 SilcUInt32 id = (SilcUInt32)context;
183 SILC_LOG_DEBUG(("Name callback"));
184 SILC_LOG_DEBUG(("Request ID: %d", id));
186 if (status != SILC_SFTP_STATUS_OK) {
187 silc_sftp_send_error(server, status, id);
191 namebuf = silc_sftp_name_encode(name);
193 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
197 silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + namebuf->len,
199 SILC_STR_UI_XNSTRING(namebuf->data, namebuf->len),
203 /* Attributes callback */
205 static void silc_sftp_server_attr(SilcSFTP sftp,
206 SilcSFTPStatus status,
207 const SilcSFTPAttributes attrs,
210 SilcSFTPServer server = (SilcSFTPServer)sftp;
211 SilcUInt32 id = (SilcUInt32)context;
214 SILC_LOG_DEBUG(("Attr callback"));
215 SILC_LOG_DEBUG(("Request ID: %d", id));
217 if (status != SILC_SFTP_STATUS_OK) {
218 silc_sftp_send_error(server, status, id);
222 attr_buf = silc_sftp_attr_encode(attrs);
224 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
228 silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len,
230 SILC_STR_UI_XNSTRING(attr_buf->data, attr_buf->len),
233 silc_buffer_free(attr_buf);
236 /* Extended callback */
238 static void silc_sftp_server_extended(SilcSFTP sftp,
239 SilcSFTPStatus status,
240 const unsigned char *data,
244 SilcSFTPServer server = (SilcSFTPServer)sftp;
245 SilcUInt32 id = (SilcUInt32)context;
247 SILC_LOG_DEBUG(("Extended callback"));
248 SILC_LOG_DEBUG(("Request ID: %d", id));
250 if (status != SILC_SFTP_STATUS_OK) {
251 silc_sftp_send_error(server, status, id);
255 silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len,
257 SILC_STR_UI_XNSTRING(data, data_len),
261 /* Starts SFTP server and returns context to it. This function returns the
262 allocated SFTP client context or NULL on error. The `send_packet' is called
263 by the library when it needs to send a packet. The `fs' is the
264 structure containing filesystem access callbacks. */
266 SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet,
268 SilcSFTPFilesystem fs)
270 SilcSFTPServer server;
272 server = silc_calloc(1, sizeof(*server));
275 server->send_packet = send_packet;
276 server->send_context = send_context;
279 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
281 return (SilcSFTP)server;
284 /* Shutdown's the SFTP server. The caller is responsible of closing
285 the associated socket connection. The SFTP context is freed and is
286 invalid after this function returns. */
288 void silc_sftp_server_shutdown(SilcSFTP sftp)
290 SilcSFTPServer server = (SilcSFTPServer)sftp;
292 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
295 silc_buffer_free(server->packet);
299 /* Sets monitor callback */
301 void silc_sftp_server_set_monitor(SilcSFTP sftp,
302 SilcSFTPMonitors monitors,
303 SilcSFTPMonitor monitor,
306 SilcSFTPServer server = (SilcSFTPServer)sftp;
307 server->monitors = monitors;
308 server->monitor = monitor;
309 server->monitor_context = context;
312 /* Function that is called to process the incmoing SFTP packet. */
313 /* XXX Some day this will go away and we have automatic receive callbacks
314 for SilcSocketConnection API or SilcPacketContext API. */
316 void silc_sftp_server_receive_process(SilcSFTP sftp,
317 SilcSocketConnection sock,
318 SilcPacketContext *packet)
320 SilcSFTPServer server = (SilcSFTPServer)sftp;
322 char *filename = NULL, *path = NULL;
323 const unsigned char *payload = NULL;
324 SilcUInt32 payload_len;
326 SilcBufferStruct buf;
328 SilcSFTPAttributes attrs;
329 SilcSFTPHandle handle;
330 SilcSFTPMonitorDataStruct mdata;
332 SILC_LOG_DEBUG(("Start"));
334 /* Parse the packet */
335 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
340 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
342 memset(&mdata, 0, sizeof(mdata));
347 SilcSFTPVersion version;
349 SILC_LOG_DEBUG(("Init request"));
351 ret = silc_buffer_unformat(&buf,
352 SILC_STR_UI_INT(&version),
358 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
359 mdata.version = version;
360 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
361 server->monitor_context);
364 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
365 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
372 SilcSFTPFileOperation pflags;
373 unsigned char *attr_buf;
374 SilcUInt32 attr_len = 0;
375 SilcBufferStruct tmpbuf;
377 SILC_LOG_DEBUG(("Open request"));
379 ret = silc_buffer_unformat(&buf,
380 SILC_STR_UI_INT(&id),
381 SILC_STR_UI32_STRING_ALLOC(&filename),
382 SILC_STR_UI_INT(&pflags),
383 SILC_STR_UI32_NSTRING(&attr_buf,
390 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
391 attrs = silc_sftp_attr_decode(&tmpbuf);
395 attrs = silc_calloc(1, sizeof(*attrs));
401 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
402 mdata.name = filename;
403 mdata.pflags = pflags;
404 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
405 server->monitor_context);
409 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
410 attrs, silc_sftp_server_handle, (void *)id);
413 silc_sftp_attr_free(attrs);
417 case SILC_SFTP_CLOSE:
419 unsigned char *hdata;
420 SilcUInt32 hdata_len;
422 SILC_LOG_DEBUG(("Close request"));
424 ret = silc_buffer_unformat(&buf,
425 SILC_STR_UI_INT(&id),
426 SILC_STR_UI32_NSTRING(&hdata,
433 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
434 (const unsigned char *)hdata,
437 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
442 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
443 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
444 server->monitor_context);
447 /* Close operation */
448 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
449 silc_sftp_server_status, (void *)id);
455 unsigned char *hdata;
456 SilcUInt32 hdata_len;
460 SILC_LOG_DEBUG(("Read request"));
462 ret = silc_buffer_unformat(&buf,
463 SILC_STR_UI_INT(&id),
464 SILC_STR_UI32_NSTRING(&hdata,
466 SILC_STR_UI_INT64(&offset),
467 SILC_STR_UI_INT(&len),
473 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
474 (const unsigned char *)hdata,
477 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
482 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
483 mdata.offset = offset;
484 mdata.data_len = len;
485 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
486 server->monitor_context);
490 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
492 silc_sftp_server_data, (void *)id);
496 case SILC_SFTP_WRITE:
498 unsigned char *hdata;
499 SilcUInt32 hdata_len;
504 SILC_LOG_DEBUG(("Read request"));
506 ret = silc_buffer_unformat(&buf,
507 SILC_STR_UI_INT(&id),
508 SILC_STR_UI32_NSTRING(&hdata,
510 SILC_STR_UI_INT64(&offset),
511 SILC_STR_UI32_NSTRING(&data,
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_WRITE && server->monitor) {
528 mdata.offset = offset;
529 mdata.data_len = data_len;
530 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
531 server->monitor_context);
534 /* Write operation */
535 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
536 (const unsigned char *)data, data_len,
537 silc_sftp_server_status, (void *)id);
541 case SILC_SFTP_REMOVE:
543 SILC_LOG_DEBUG(("Remove request"));
545 ret = silc_buffer_unformat(&buf,
546 SILC_STR_UI_INT(&id),
547 SILC_STR_UI32_STRING_ALLOC(&filename),
553 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
554 mdata.name = filename;
555 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
556 server->monitor_context);
559 /* Remove operation */
560 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
561 silc_sftp_server_status, (void *)id);
567 case SILC_SFTP_RENAME:
569 char *newname = NULL;
571 SILC_LOG_DEBUG(("Rename request"));
573 ret = silc_buffer_unformat(&buf,
574 SILC_STR_UI_INT(&id),
575 SILC_STR_UI32_STRING_ALLOC(&filename),
576 SILC_STR_UI32_STRING_ALLOC(&newname),
582 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
583 mdata.name = filename;
584 mdata.name2 = newname;
585 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
586 server->monitor_context);
589 /* Rename operation */
590 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
592 silc_sftp_server_status, (void *)id);
599 case SILC_SFTP_MKDIR:
601 unsigned char *attr_buf;
602 SilcUInt32 attr_len = 0;
603 SilcBufferStruct tmpbuf;
605 SILC_LOG_DEBUG(("Mkdir request"));
607 ret = silc_buffer_unformat(&buf,
608 SILC_STR_UI_INT(&id),
609 SILC_STR_UI32_STRING_ALLOC(&path),
610 SILC_STR_UI32_NSTRING(&attr_buf,
617 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
618 attrs = silc_sftp_attr_decode(&tmpbuf);
622 attrs = silc_calloc(1, sizeof(*attrs));
628 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
630 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
631 server->monitor_context);
634 /* Mkdir operation */
635 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
636 silc_sftp_server_status, (void *)id);
638 silc_sftp_attr_free(attrs);
643 case SILC_SFTP_RMDIR:
645 SILC_LOG_DEBUG(("Rmdir request"));
647 ret = silc_buffer_unformat(&buf,
648 SILC_STR_UI_INT(&id),
649 SILC_STR_UI32_STRING_ALLOC(&path),
655 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
657 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
658 server->monitor_context);
661 /* Rmdir operation */
662 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
663 silc_sftp_server_status, (void *)id);
669 case SILC_SFTP_OPENDIR:
671 SILC_LOG_DEBUG(("Opendir request"));
673 ret = silc_buffer_unformat(&buf,
674 SILC_STR_UI_INT(&id),
675 SILC_STR_UI32_STRING_ALLOC(&path),
681 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
683 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
684 server->monitor_context);
687 /* Opendir operation */
688 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
689 silc_sftp_server_handle, (void *)id);
695 case SILC_SFTP_READDIR:
697 unsigned char *hdata;
698 SilcUInt32 hdata_len;
700 SILC_LOG_DEBUG(("Readdir request"));
702 ret = silc_buffer_unformat(&buf,
703 SILC_STR_UI_INT(&id),
704 SILC_STR_UI32_NSTRING(&hdata,
711 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
712 (const unsigned char *)hdata,
715 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
720 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
721 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
722 server->monitor_context);
725 /* Readdir operation */
726 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
727 silc_sftp_server_name, (void *)id);
733 SILC_LOG_DEBUG(("Stat request"));
735 ret = silc_buffer_unformat(&buf,
736 SILC_STR_UI_INT(&id),
737 SILC_STR_UI32_STRING_ALLOC(&path),
743 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
745 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
746 server->monitor_context);
750 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
751 silc_sftp_server_attr, (void *)id);
757 case SILC_SFTP_LSTAT:
759 SILC_LOG_DEBUG(("Lstat request"));
761 ret = silc_buffer_unformat(&buf,
762 SILC_STR_UI_INT(&id),
763 SILC_STR_UI32_STRING_ALLOC(&path),
769 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
771 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
772 server->monitor_context);
775 /* Lstat operation */
776 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
777 silc_sftp_server_attr, (void *)id);
783 case SILC_SFTP_FSTAT:
785 unsigned char *hdata;
786 SilcUInt32 hdata_len;
788 SILC_LOG_DEBUG(("Fstat request"));
790 ret = silc_buffer_unformat(&buf,
791 SILC_STR_UI_INT(&id),
792 SILC_STR_UI32_NSTRING(&hdata,
799 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
800 (const unsigned char *)hdata,
803 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
808 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
809 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
810 server->monitor_context);
813 /* Fstat operation */
814 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
815 silc_sftp_server_attr, (void *)id);
819 case SILC_SFTP_SETSTAT:
821 unsigned char *attr_buf;
822 SilcUInt32 attr_len = 0;
823 SilcBufferStruct tmpbuf;
825 SILC_LOG_DEBUG(("Setstat request"));
827 ret = silc_buffer_unformat(&buf,
828 SILC_STR_UI_INT(&id),
829 SILC_STR_UI32_STRING_ALLOC(&path),
830 SILC_STR_UI32_NSTRING(&attr_buf,
837 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
838 attrs = silc_sftp_attr_decode(&tmpbuf);
842 attrs = silc_calloc(1, sizeof(*attrs));
848 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
850 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
851 server->monitor_context);
854 /* Setstat operation */
855 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
856 silc_sftp_server_status, (void *)id);
858 silc_sftp_attr_free(attrs);
863 case SILC_SFTP_FSETSTAT:
865 unsigned char *hdata, *attr_buf;
866 SilcUInt32 hdata_len, attr_len = 0;
867 SilcBufferStruct tmpbuf;
869 SILC_LOG_DEBUG(("Fsetstat request"));
871 ret = silc_buffer_unformat(&buf,
872 SILC_STR_UI_INT(&id),
873 SILC_STR_UI32_NSTRING(&hdata,
875 SILC_STR_UI32_NSTRING(&attr_buf,
882 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
883 attrs = silc_sftp_attr_decode(&tmpbuf);
887 attrs = silc_calloc(1, sizeof(*attrs));
893 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
894 (const unsigned char *)hdata,
897 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
902 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
903 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
904 server->monitor_context);
907 /* Fsetstat operation */
908 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
910 silc_sftp_server_status, (void *)id);
912 silc_sftp_attr_free(attrs);
916 case SILC_SFTP_READLINK:
918 SILC_LOG_DEBUG(("Readlink request"));
920 ret = silc_buffer_unformat(&buf,
921 SILC_STR_UI_INT(&id),
922 SILC_STR_UI32_STRING_ALLOC(&path),
928 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
930 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
931 server->monitor_context);
934 /* Readlink operation */
935 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
936 silc_sftp_server_name, (void *)id);
942 case SILC_SFTP_SYMLINK:
946 SILC_LOG_DEBUG(("Symlink request"));
948 ret = silc_buffer_unformat(&buf,
949 SILC_STR_UI_INT(&id),
950 SILC_STR_UI32_STRING_ALLOC(&path),
951 SILC_STR_UI32_STRING_ALLOC(&target),
957 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
959 mdata.name2 = target;
960 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
961 server->monitor_context);
964 /* Symlink operation */
965 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
966 silc_sftp_server_status, (void *)id);
973 case SILC_SFTP_REALPATH:
975 SILC_LOG_DEBUG(("Realpath request"));
977 ret = silc_buffer_unformat(&buf,
978 SILC_STR_UI_INT(&id),
979 SILC_STR_UI32_STRING_ALLOC(&path),
985 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
987 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
988 server->monitor_context);
991 /* Realpath operation */
992 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
993 silc_sftp_server_name, (void *)id);
999 case SILC_SFTP_EXTENDED:
1001 char *request = NULL;
1002 unsigned char *data;
1003 SilcUInt32 data_len;
1005 SILC_LOG_DEBUG(("Extended request"));
1007 ret = silc_buffer_unformat(&buf,
1008 SILC_STR_UI_INT(&id),
1009 SILC_STR_UI32_STRING_ALLOC(&request),
1014 data_len = 8 + strlen(request);
1015 silc_buffer_pull(&buf, data_len);
1016 ret = silc_buffer_unformat(&buf,
1017 SILC_STR_UI_XNSTRING(&data, buf.len),
1024 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1025 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1026 server->monitor_context);
1029 /* Extended operation */
1030 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1031 request, data, data_len,
1032 silc_sftp_server_extended, (void *)id);
1045 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);