5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2004 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 */
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 = SILC_PTR_TO_32(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 = SILC_PTR_TO_32(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 = SILC_PTR_TO_32(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 = SILC_PTR_TO_32(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 = SILC_PTR_TO_32(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 = SILC_PTR_TO_32(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,
414 silc_sftp_attr_free(attrs);
418 case SILC_SFTP_CLOSE:
420 unsigned char *hdata;
421 SilcUInt32 hdata_len;
423 SILC_LOG_DEBUG(("Close request"));
425 ret = silc_buffer_unformat(&buf,
426 SILC_STR_UI_INT(&id),
427 SILC_STR_UI32_NSTRING(&hdata,
434 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
435 (const unsigned char *)hdata,
438 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
443 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
444 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
445 server->monitor_context);
448 /* Close operation */
449 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
450 silc_sftp_server_status, SILC_32_TO_PTR(id));
457 unsigned char *hdata;
458 SilcUInt32 hdata_len;
462 SILC_LOG_DEBUG(("Read request"));
464 ret = silc_buffer_unformat(&buf,
465 SILC_STR_UI_INT(&id),
466 SILC_STR_UI32_NSTRING(&hdata,
468 SILC_STR_UI_INT64(&offset),
469 SILC_STR_UI_INT(&len),
475 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
476 (const unsigned char *)hdata,
479 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
484 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
486 silc_sftp_server_data, SILC_32_TO_PTR(id));
489 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
490 mdata.offset = offset;
491 mdata.data_len = len;
492 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
493 server->monitor_context);
498 case SILC_SFTP_WRITE:
500 unsigned char *hdata;
501 SilcUInt32 hdata_len;
506 SILC_LOG_DEBUG(("Read request"));
508 ret = silc_buffer_unformat(&buf,
509 SILC_STR_UI_INT(&id),
510 SILC_STR_UI32_NSTRING(&hdata,
512 SILC_STR_UI_INT64(&offset),
513 SILC_STR_UI32_NSTRING(&data,
520 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
521 (const unsigned char *)hdata,
524 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
528 /* Write operation */
529 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
530 (const unsigned char *)data, data_len,
531 silc_sftp_server_status, SILC_32_TO_PTR(id));
534 if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
535 mdata.offset = offset;
536 mdata.data_len = data_len;
537 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
538 server->monitor_context);
543 case SILC_SFTP_REMOVE:
545 SILC_LOG_DEBUG(("Remove request"));
547 ret = silc_buffer_unformat(&buf,
548 SILC_STR_UI_INT(&id),
549 SILC_STR_UI32_STRING_ALLOC(&filename),
555 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
556 mdata.name = filename;
557 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
558 server->monitor_context);
561 /* Remove operation */
562 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
563 silc_sftp_server_status, SILC_32_TO_PTR(id));
569 case SILC_SFTP_RENAME:
571 char *newname = NULL;
573 SILC_LOG_DEBUG(("Rename request"));
575 ret = silc_buffer_unformat(&buf,
576 SILC_STR_UI_INT(&id),
577 SILC_STR_UI32_STRING_ALLOC(&filename),
578 SILC_STR_UI32_STRING_ALLOC(&newname),
584 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
585 mdata.name = filename;
586 mdata.name2 = newname;
587 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
588 server->monitor_context);
591 /* Rename operation */
592 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
594 silc_sftp_server_status, SILC_32_TO_PTR(id));
601 case SILC_SFTP_MKDIR:
603 unsigned char *attr_buf;
604 SilcUInt32 attr_len = 0;
605 SilcBufferStruct tmpbuf;
607 SILC_LOG_DEBUG(("Mkdir request"));
609 ret = silc_buffer_unformat(&buf,
610 SILC_STR_UI_INT(&id),
611 SILC_STR_UI32_STRING_ALLOC(&path),
612 SILC_STR_UI32_NSTRING(&attr_buf,
619 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
620 attrs = silc_sftp_attr_decode(&tmpbuf);
624 attrs = silc_calloc(1, sizeof(*attrs));
630 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
632 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
633 server->monitor_context);
636 /* Mkdir operation */
637 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
638 silc_sftp_server_status, SILC_32_TO_PTR(id));
640 silc_sftp_attr_free(attrs);
645 case SILC_SFTP_RMDIR:
647 SILC_LOG_DEBUG(("Rmdir request"));
649 ret = silc_buffer_unformat(&buf,
650 SILC_STR_UI_INT(&id),
651 SILC_STR_UI32_STRING_ALLOC(&path),
657 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
659 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
660 server->monitor_context);
663 /* Rmdir operation */
664 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
665 silc_sftp_server_status, SILC_32_TO_PTR(id));
671 case SILC_SFTP_OPENDIR:
673 SILC_LOG_DEBUG(("Opendir request"));
675 ret = silc_buffer_unformat(&buf,
676 SILC_STR_UI_INT(&id),
677 SILC_STR_UI32_STRING_ALLOC(&path),
683 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
685 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
686 server->monitor_context);
689 /* Opendir operation */
690 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
691 silc_sftp_server_handle, SILC_32_TO_PTR(id));
697 case SILC_SFTP_READDIR:
699 unsigned char *hdata;
700 SilcUInt32 hdata_len;
702 SILC_LOG_DEBUG(("Readdir request"));
704 ret = silc_buffer_unformat(&buf,
705 SILC_STR_UI_INT(&id),
706 SILC_STR_UI32_NSTRING(&hdata,
713 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
714 (const unsigned char *)hdata,
717 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
722 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
723 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
724 server->monitor_context);
727 /* Readdir operation */
728 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
729 silc_sftp_server_name, SILC_32_TO_PTR(id));
735 SILC_LOG_DEBUG(("Stat request"));
737 ret = silc_buffer_unformat(&buf,
738 SILC_STR_UI_INT(&id),
739 SILC_STR_UI32_STRING_ALLOC(&path),
745 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
747 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
748 server->monitor_context);
752 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
753 silc_sftp_server_attr, SILC_32_TO_PTR(id));
759 case SILC_SFTP_LSTAT:
761 SILC_LOG_DEBUG(("Lstat request"));
763 ret = silc_buffer_unformat(&buf,
764 SILC_STR_UI_INT(&id),
765 SILC_STR_UI32_STRING_ALLOC(&path),
771 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
773 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
774 server->monitor_context);
777 /* Lstat operation */
778 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
779 silc_sftp_server_attr, SILC_32_TO_PTR(id));
785 case SILC_SFTP_FSTAT:
787 unsigned char *hdata;
788 SilcUInt32 hdata_len;
790 SILC_LOG_DEBUG(("Fstat request"));
792 ret = silc_buffer_unformat(&buf,
793 SILC_STR_UI_INT(&id),
794 SILC_STR_UI32_NSTRING(&hdata,
801 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
802 (const unsigned char *)hdata,
805 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
810 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
811 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
812 server->monitor_context);
815 /* Fstat operation */
816 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
817 silc_sftp_server_attr, SILC_32_TO_PTR(id));
821 case SILC_SFTP_SETSTAT:
823 unsigned char *attr_buf;
824 SilcUInt32 attr_len = 0;
825 SilcBufferStruct tmpbuf;
827 SILC_LOG_DEBUG(("Setstat request"));
829 ret = silc_buffer_unformat(&buf,
830 SILC_STR_UI_INT(&id),
831 SILC_STR_UI32_STRING_ALLOC(&path),
832 SILC_STR_UI32_NSTRING(&attr_buf,
839 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
840 attrs = silc_sftp_attr_decode(&tmpbuf);
844 attrs = silc_calloc(1, sizeof(*attrs));
850 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
852 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
853 server->monitor_context);
856 /* Setstat operation */
857 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
858 silc_sftp_server_status, SILC_32_TO_PTR(id));
860 silc_sftp_attr_free(attrs);
865 case SILC_SFTP_FSETSTAT:
867 unsigned char *hdata, *attr_buf;
868 SilcUInt32 hdata_len, attr_len = 0;
869 SilcBufferStruct tmpbuf;
871 SILC_LOG_DEBUG(("Fsetstat request"));
873 ret = silc_buffer_unformat(&buf,
874 SILC_STR_UI_INT(&id),
875 SILC_STR_UI32_NSTRING(&hdata,
877 SILC_STR_UI32_NSTRING(&attr_buf,
884 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
885 attrs = silc_sftp_attr_decode(&tmpbuf);
889 attrs = silc_calloc(1, sizeof(*attrs));
895 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
896 (const unsigned char *)hdata,
899 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
904 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
905 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
906 server->monitor_context);
909 /* Fsetstat operation */
910 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
912 silc_sftp_server_status,
915 silc_sftp_attr_free(attrs);
919 case SILC_SFTP_READLINK:
921 SILC_LOG_DEBUG(("Readlink request"));
923 ret = silc_buffer_unformat(&buf,
924 SILC_STR_UI_INT(&id),
925 SILC_STR_UI32_STRING_ALLOC(&path),
931 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
933 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
934 server->monitor_context);
937 /* Readlink operation */
938 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
939 silc_sftp_server_name, SILC_32_TO_PTR(id));
945 case SILC_SFTP_SYMLINK:
949 SILC_LOG_DEBUG(("Symlink request"));
951 ret = silc_buffer_unformat(&buf,
952 SILC_STR_UI_INT(&id),
953 SILC_STR_UI32_STRING_ALLOC(&path),
954 SILC_STR_UI32_STRING_ALLOC(&target),
960 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
962 mdata.name2 = target;
963 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
964 server->monitor_context);
967 /* Symlink operation */
968 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
969 silc_sftp_server_status, SILC_32_TO_PTR(id));
976 case SILC_SFTP_REALPATH:
978 SILC_LOG_DEBUG(("Realpath request"));
980 ret = silc_buffer_unformat(&buf,
981 SILC_STR_UI_INT(&id),
982 SILC_STR_UI32_STRING_ALLOC(&path),
988 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
990 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
991 server->monitor_context);
994 /* Realpath operation */
995 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
996 silc_sftp_server_name, SILC_32_TO_PTR(id));
1002 case SILC_SFTP_EXTENDED:
1004 char *request = NULL;
1005 unsigned char *data;
1006 SilcUInt32 data_len;
1008 SILC_LOG_DEBUG(("Extended request"));
1010 ret = silc_buffer_unformat(&buf,
1011 SILC_STR_UI_INT(&id),
1012 SILC_STR_UI32_STRING_ALLOC(&request),
1017 data_len = 8 + strlen(request);
1018 silc_buffer_pull(&buf, data_len);
1019 ret = silc_buffer_unformat(&buf,
1020 SILC_STR_UI_XNSTRING(&data, buf.len),
1027 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1028 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1029 server->monitor_context);
1032 /* Extended operation */
1033 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1034 request, data, data_len,
1035 silc_sftp_server_extended,
1036 SILC_32_TO_PTR(id));
1049 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);