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_packet(server, SILC_SFTP_ATTRS, 4 + attr_buf->len,
226 SILC_STR_UI_XNSTRING(attr_buf->data, attr_buf->len),
229 silc_buffer_free(attr_buf);
232 /* Extended callback */
234 static void silc_sftp_server_extended(SilcSFTP sftp,
235 SilcSFTPStatus status,
236 const unsigned char *data,
240 SilcSFTPServer server = (SilcSFTPServer)sftp;
241 SilcUInt32 id = (SilcUInt32)context;
243 SILC_LOG_DEBUG(("Extended callback"));
244 SILC_LOG_DEBUG(("Request ID: %d", id));
246 if (status != SILC_SFTP_STATUS_OK) {
247 silc_sftp_send_error(server, status, id);
251 silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len,
253 SILC_STR_UI_XNSTRING(data, data_len),
257 /* Starts SFTP server and returns context to it. This function returns the
258 allocated SFTP client context or NULL on error. The `send_packet' is called
259 by the library when it needs to send a packet. The `fs' is the
260 structure containing filesystem access callbacks. */
262 SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet,
264 SilcSFTPFilesystem fs)
266 SilcSFTPServer server;
268 server = silc_calloc(1, sizeof(*server));
269 server->send_packet = send_packet;
270 server->send_context = send_context;
273 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
275 return (SilcSFTP)server;
278 /* Shutdown's the SFTP server. The caller is responsible of closing
279 the associated socket connection. The SFTP context is freed and is
280 invalid after this function returns. */
282 void silc_sftp_server_shutdown(SilcSFTP sftp)
284 SilcSFTPServer server = (SilcSFTPServer)sftp;
286 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
289 silc_buffer_free(server->packet);
293 /* Sets monitor callback */
295 void silc_sftp_server_set_monitor(SilcSFTP sftp,
296 SilcSFTPMonitors monitors,
297 SilcSFTPMonitor monitor,
300 SilcSFTPServer server = (SilcSFTPServer)sftp;
301 server->monitors = monitors;
302 server->monitor = monitor;
303 server->monitor_context = context;
306 /* Function that is called to process the incmoing SFTP packet. */
307 /* XXX Some day this will go away and we have automatic receive callbacks
308 for SilcSocketConnection API or SilcPacketContext API. */
310 void silc_sftp_server_receive_process(SilcSFTP sftp,
311 SilcSocketConnection sock,
312 SilcPacketContext *packet)
314 SilcSFTPServer server = (SilcSFTPServer)sftp;
316 char *filename = NULL, *path = NULL;
317 const unsigned char *payload = NULL;
318 SilcUInt32 payload_len;
320 SilcBufferStruct buf;
322 SilcSFTPAttributes attrs;
323 SilcSFTPHandle handle;
324 SilcSFTPMonitorDataStruct mdata;
326 SILC_LOG_DEBUG(("Start"));
328 /* Parse the packet */
329 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
334 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
336 memset(&mdata, 0, sizeof(mdata));
341 SilcSFTPVersion version;
343 SILC_LOG_DEBUG(("Init request"));
345 ret = silc_buffer_unformat(&buf,
346 SILC_STR_UI_INT(&version),
352 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
353 mdata.version = version;
354 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
355 server->monitor_context);
358 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
359 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
366 SilcSFTPFileOperation pflags;
367 unsigned char *attr_buf;
368 SilcUInt32 attr_len = 0;
369 SilcBufferStruct tmpbuf;
371 SILC_LOG_DEBUG(("Open request"));
373 ret = silc_buffer_unformat(&buf,
374 SILC_STR_UI_INT(&id),
375 SILC_STR_UI32_STRING_ALLOC(&filename),
376 SILC_STR_UI_INT(&pflags),
377 SILC_STR_UI32_NSTRING(&attr_buf,
384 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
385 attrs = silc_sftp_attr_decode(&tmpbuf);
387 attrs = silc_calloc(1, sizeof(*attrs));
391 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
392 mdata.name = filename;
393 mdata.pflags = pflags;
394 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
395 server->monitor_context);
399 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
400 attrs, silc_sftp_server_handle, (void *)id);
403 silc_sftp_attr_free(attrs);
407 case SILC_SFTP_CLOSE:
409 unsigned char *hdata;
410 SilcUInt32 hdata_len;
412 SILC_LOG_DEBUG(("Close request"));
414 ret = silc_buffer_unformat(&buf,
415 SILC_STR_UI_INT(&id),
416 SILC_STR_UI32_NSTRING(&hdata,
423 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
424 (const unsigned char *)hdata,
427 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
432 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
433 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
434 server->monitor_context);
437 /* Close operation */
438 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
439 silc_sftp_server_status, (void *)id);
445 unsigned char *hdata;
446 SilcUInt32 hdata_len;
450 SILC_LOG_DEBUG(("Read request"));
452 ret = silc_buffer_unformat(&buf,
453 SILC_STR_UI_INT(&id),
454 SILC_STR_UI32_NSTRING(&hdata,
456 SILC_STR_UI_INT64(&offset),
457 SILC_STR_UI_INT(&len),
463 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
464 (const unsigned char *)hdata,
467 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
472 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
473 mdata.offset = offset;
474 mdata.data_len = len;
475 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
476 server->monitor_context);
480 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
482 silc_sftp_server_data, (void *)id);
486 case SILC_SFTP_WRITE:
488 unsigned char *hdata;
489 SilcUInt32 hdata_len;
494 SILC_LOG_DEBUG(("Read request"));
496 ret = silc_buffer_unformat(&buf,
497 SILC_STR_UI_INT(&id),
498 SILC_STR_UI32_NSTRING(&hdata,
500 SILC_STR_UI_INT64(&offset),
501 SILC_STR_UI32_NSTRING(&data,
508 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
509 (const unsigned char *)hdata,
512 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
517 if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
518 mdata.offset = offset;
519 mdata.data_len = data_len;
520 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
521 server->monitor_context);
524 /* Write operation */
525 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
526 (const unsigned char *)data, data_len,
527 silc_sftp_server_status, (void *)id);
531 case SILC_SFTP_REMOVE:
533 SILC_LOG_DEBUG(("Remove request"));
535 ret = silc_buffer_unformat(&buf,
536 SILC_STR_UI_INT(&id),
537 SILC_STR_UI32_STRING_ALLOC(&filename),
543 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
544 mdata.name = filename;
545 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
546 server->monitor_context);
549 /* Remove operation */
550 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
551 silc_sftp_server_status, (void *)id);
557 case SILC_SFTP_RENAME:
559 char *newname = NULL;
561 SILC_LOG_DEBUG(("Rename request"));
563 ret = silc_buffer_unformat(&buf,
564 SILC_STR_UI_INT(&id),
565 SILC_STR_UI32_STRING_ALLOC(&filename),
566 SILC_STR_UI32_STRING_ALLOC(&newname),
572 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
573 mdata.name = filename;
574 mdata.name2 = newname;
575 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
576 server->monitor_context);
579 /* Rename operation */
580 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
582 silc_sftp_server_status, (void *)id);
589 case SILC_SFTP_MKDIR:
591 unsigned char *attr_buf;
592 SilcUInt32 attr_len = 0;
593 SilcBufferStruct tmpbuf;
595 SILC_LOG_DEBUG(("Mkdir request"));
597 ret = silc_buffer_unformat(&buf,
598 SILC_STR_UI_INT(&id),
599 SILC_STR_UI32_STRING_ALLOC(&path),
600 SILC_STR_UI32_NSTRING(&attr_buf,
607 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
608 attrs = silc_sftp_attr_decode(&tmpbuf);
610 attrs = silc_calloc(1, sizeof(*attrs));
614 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
616 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
617 server->monitor_context);
620 /* Mkdir operation */
621 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
622 silc_sftp_server_status, (void *)id);
624 silc_sftp_attr_free(attrs);
629 case SILC_SFTP_RMDIR:
631 SILC_LOG_DEBUG(("Rmdir request"));
633 ret = silc_buffer_unformat(&buf,
634 SILC_STR_UI_INT(&id),
635 SILC_STR_UI32_STRING_ALLOC(&path),
641 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
643 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
644 server->monitor_context);
647 /* Rmdir operation */
648 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
649 silc_sftp_server_status, (void *)id);
655 case SILC_SFTP_OPENDIR:
657 SILC_LOG_DEBUG(("Opendir request"));
659 ret = silc_buffer_unformat(&buf,
660 SILC_STR_UI_INT(&id),
661 SILC_STR_UI32_STRING_ALLOC(&path),
667 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
669 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
670 server->monitor_context);
673 /* Opendir operation */
674 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
675 silc_sftp_server_handle, (void *)id);
681 case SILC_SFTP_READDIR:
683 unsigned char *hdata;
684 SilcUInt32 hdata_len;
686 SILC_LOG_DEBUG(("Readdir request"));
688 ret = silc_buffer_unformat(&buf,
689 SILC_STR_UI_INT(&id),
690 SILC_STR_UI32_NSTRING(&hdata,
697 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
698 (const unsigned char *)hdata,
701 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
706 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
707 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
708 server->monitor_context);
711 /* Readdir operation */
712 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
713 silc_sftp_server_name, (void *)id);
719 SILC_LOG_DEBUG(("Stat request"));
721 ret = silc_buffer_unformat(&buf,
722 SILC_STR_UI_INT(&id),
723 SILC_STR_UI32_STRING_ALLOC(&path),
729 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
731 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
732 server->monitor_context);
736 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
737 silc_sftp_server_attr, (void *)id);
743 case SILC_SFTP_LSTAT:
745 SILC_LOG_DEBUG(("Lstat request"));
747 ret = silc_buffer_unformat(&buf,
748 SILC_STR_UI_INT(&id),
749 SILC_STR_UI32_STRING_ALLOC(&path),
755 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
757 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
758 server->monitor_context);
761 /* Lstat operation */
762 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
763 silc_sftp_server_attr, (void *)id);
769 case SILC_SFTP_FSTAT:
771 unsigned char *hdata;
772 SilcUInt32 hdata_len;
774 SILC_LOG_DEBUG(("Fstat request"));
776 ret = silc_buffer_unformat(&buf,
777 SILC_STR_UI_INT(&id),
778 SILC_STR_UI32_NSTRING(&hdata,
785 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
786 (const unsigned char *)hdata,
789 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
794 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
795 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
796 server->monitor_context);
799 /* Fstat operation */
800 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
801 silc_sftp_server_attr, (void *)id);
805 case SILC_SFTP_SETSTAT:
807 unsigned char *attr_buf;
808 SilcUInt32 attr_len = 0;
809 SilcBufferStruct tmpbuf;
811 SILC_LOG_DEBUG(("Setstat request"));
813 ret = silc_buffer_unformat(&buf,
814 SILC_STR_UI_INT(&id),
815 SILC_STR_UI32_STRING_ALLOC(&path),
816 SILC_STR_UI32_NSTRING(&attr_buf,
823 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
824 attrs = silc_sftp_attr_decode(&tmpbuf);
826 attrs = silc_calloc(1, sizeof(*attrs));
830 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
832 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
833 server->monitor_context);
836 /* Setstat operation */
837 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
838 silc_sftp_server_status, (void *)id);
840 silc_sftp_attr_free(attrs);
845 case SILC_SFTP_FSETSTAT:
847 unsigned char *hdata, *attr_buf;
848 SilcUInt32 hdata_len, attr_len = 0;
849 SilcBufferStruct tmpbuf;
851 SILC_LOG_DEBUG(("Fsetstat request"));
853 ret = silc_buffer_unformat(&buf,
854 SILC_STR_UI_INT(&id),
855 SILC_STR_UI32_NSTRING(&hdata,
857 SILC_STR_UI32_NSTRING(&attr_buf,
864 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
865 attrs = silc_sftp_attr_decode(&tmpbuf);
867 attrs = silc_calloc(1, sizeof(*attrs));
871 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
872 (const unsigned char *)hdata,
875 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
880 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
881 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
882 server->monitor_context);
885 /* Fsetstat operation */
886 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
888 silc_sftp_server_status, (void *)id);
890 silc_sftp_attr_free(attrs);
894 case SILC_SFTP_READLINK:
896 SILC_LOG_DEBUG(("Readlink request"));
898 ret = silc_buffer_unformat(&buf,
899 SILC_STR_UI_INT(&id),
900 SILC_STR_UI32_STRING_ALLOC(&path),
906 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
908 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
909 server->monitor_context);
912 /* Readlink operation */
913 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
914 silc_sftp_server_name, (void *)id);
920 case SILC_SFTP_SYMLINK:
924 SILC_LOG_DEBUG(("Symlink request"));
926 ret = silc_buffer_unformat(&buf,
927 SILC_STR_UI_INT(&id),
928 SILC_STR_UI32_STRING_ALLOC(&path),
929 SILC_STR_UI32_STRING_ALLOC(&target),
935 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
937 mdata.name2 = target;
938 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
939 server->monitor_context);
942 /* Symlink operation */
943 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
944 silc_sftp_server_status, (void *)id);
951 case SILC_SFTP_REALPATH:
953 SILC_LOG_DEBUG(("Realpath request"));
955 ret = silc_buffer_unformat(&buf,
956 SILC_STR_UI_INT(&id),
957 SILC_STR_UI32_STRING_ALLOC(&path),
963 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
965 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
966 server->monitor_context);
969 /* Realpath operation */
970 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
971 silc_sftp_server_name, (void *)id);
977 case SILC_SFTP_EXTENDED:
979 char *request = NULL;
983 SILC_LOG_DEBUG(("Extended request"));
985 ret = silc_buffer_unformat(&buf,
986 SILC_STR_UI_INT(&id),
987 SILC_STR_UI32_STRING_ALLOC(&request),
992 data_len = 8 + strlen(request);
993 silc_buffer_pull(&buf, data_len);
994 ret = silc_buffer_unformat(&buf,
995 SILC_STR_UI_XNSTRING(&data, buf.len),
1002 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1003 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1004 server->monitor_context);
1007 /* Extended operation */
1008 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1009 request, data, data_len,
1010 silc_sftp_server_extended, (void *)id);
1023 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);