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 SilcSchedule schedule;
30 SilcSFTPMonitors monitors;
31 SilcSFTPMonitor monitor;
32 void *monitor_context;
33 SilcSFTPFilesystem fs;
35 SilcSFTPErrorCallback error;
39 static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer);
41 /* General routine to send SFTP packet to the SFTP client. */
43 static void silc_sftp_send_packet(SilcSFTPServer sftp,
52 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
58 SILC_LOG_HEXDUMP(("SFTP packet to client"), silc_buffer_data(sftp->packet),
59 silc_buffer_len(sftp->packet));
62 while (silc_buffer_len(sftp->packet) > 0) {
63 ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
64 silc_buffer_len(sftp->packet));
66 SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
67 sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_NO_CONNECTION,
69 silc_buffer_reset(sftp->packet);
73 sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_EOF, sftp->context);
74 silc_buffer_reset(sftp->packet);
80 silc_buffer_pull(sftp->packet, ret);
84 silc_buffer_reset(sftp->packet);
87 /* Handles stream I/O */
89 static void silc_sftp_server_io(SilcStream stream, SilcStreamStatus status,
92 SilcSFTPServer sftp = context;
93 unsigned char inbuf[33792];
94 SilcBufferStruct packet;
98 case SILC_STREAM_CAN_READ:
99 SILC_LOG_DEBUG(("Reading data from stream"));
101 /* Read data from stream */
102 ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
105 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
107 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
111 /* Now process the SFTP packet */
112 silc_buffer_set(&packet, inbuf, ret);
113 silc_sftp_server_receive_process(context, &packet);
116 case SILC_STREAM_CAN_WRITE:
117 if (!silc_buffer_headlen(sftp->packet))
120 SILC_LOG_DEBUG(("Writing pending data to stream"));
122 /* Write pending data to stream */
123 silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
124 while (silc_buffer_len(sftp->packet) > 0) {
125 ret = silc_stream_write(stream, sftp->packet->data,
126 silc_buffer_len(sftp->packet));
128 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
129 silc_buffer_reset(sftp->packet);
134 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
135 silc_buffer_reset(sftp->packet);
143 silc_buffer_pull(sftp->packet, ret);
152 /* Sends error to the client */
154 static void silc_sftp_send_error(SilcSFTPServer sftp,
155 SilcSFTPStatus status,
158 SILC_LOG_DEBUG(("Send error %d", status));
160 silc_sftp_send_packet(sftp, SILC_SFTP_STATUS, 16,
162 SILC_STR_UI_INT(status),
163 SILC_STR_UI_INT(0), /* Error */
164 SILC_STR_UI_INT(0), /* Language tag */
168 /* Status callback */
170 static void silc_sftp_server_status(SilcSFTP sftp,
171 SilcSFTPStatus status,
173 const char *language_tag,
176 SilcSFTPServer server = (SilcSFTPServer)sftp;
177 SilcUInt32 id = SILC_PTR_TO_32(context);
180 SILC_LOG_DEBUG(("Status callback"));
181 SILC_LOG_DEBUG(("Request ID: %d", id));
187 mlen = strlen(message);
188 llen = strlen(language_tag);
190 silc_sftp_send_packet(server, SILC_SFTP_STATUS, 16 + mlen + llen,
192 SILC_STR_UI_INT(status),
193 SILC_STR_UI_INT(mlen),
194 SILC_STR_UI32_STRING(message),
195 SILC_STR_UI_INT(llen),
196 SILC_STR_UI32_STRING(language_tag),
200 /* Handle callback */
202 static void silc_sftp_server_handle(SilcSFTP sftp,
203 SilcSFTPStatus status,
204 SilcSFTPHandle handle,
207 SilcSFTPServer server = (SilcSFTPServer)sftp;
208 SilcUInt32 id = SILC_PTR_TO_32(context);
209 unsigned char *hdata;
210 SilcUInt32 hdata_len;
212 SILC_LOG_DEBUG(("Handle callback"));
213 SILC_LOG_DEBUG(("Request ID: %d", id));
215 if (status != SILC_SFTP_STATUS_OK) {
216 silc_sftp_send_error(server, status, id);
220 hdata = server->fs->fs->sftp_encode_handle(server->fs->fs_context, sftp,
223 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
227 silc_sftp_send_packet(server, SILC_SFTP_HANDLE, 8 + hdata_len,
229 SILC_STR_UI_INT(hdata_len),
230 SILC_STR_UI_XNSTRING(hdata, hdata_len),
236 static void silc_sftp_server_data(SilcSFTP sftp,
237 SilcSFTPStatus status,
238 const unsigned char *data,
242 SilcSFTPServer server = (SilcSFTPServer)sftp;
243 SilcUInt32 id = SILC_PTR_TO_32(context);
245 SILC_LOG_DEBUG(("Data callback"));
246 SILC_LOG_DEBUG(("Request ID: %d", id));
248 if (status != SILC_SFTP_STATUS_OK) {
249 silc_sftp_send_error(server, status, id);
253 silc_sftp_send_packet(server, SILC_SFTP_DATA, 8 + data_len,
255 SILC_STR_UI_INT(data_len),
256 SILC_STR_UI_XNSTRING(data, data_len),
262 static void silc_sftp_server_name(SilcSFTP sftp,
263 SilcSFTPStatus status,
264 const SilcSFTPName name,
267 SilcSFTPServer server = (SilcSFTPServer)sftp;
268 SilcUInt32 id = SILC_PTR_TO_32(context);
271 SILC_LOG_DEBUG(("Name callback"));
272 SILC_LOG_DEBUG(("Request ID: %d", id));
274 if (status != SILC_SFTP_STATUS_OK) {
275 silc_sftp_send_error(server, status, id);
279 namebuf = silc_sftp_name_encode(name);
281 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
285 silc_sftp_send_packet(server, SILC_SFTP_NAME, 4 + silc_buffer_len(namebuf),
287 SILC_STR_DATA(silc_buffer_data(namebuf),
288 silc_buffer_len(namebuf)),
292 /* Attributes callback */
294 static void silc_sftp_server_attr(SilcSFTP sftp,
295 SilcSFTPStatus status,
296 const SilcSFTPAttributes attrs,
299 SilcSFTPServer server = (SilcSFTPServer)sftp;
300 SilcUInt32 id = SILC_PTR_TO_32(context);
303 SILC_LOG_DEBUG(("Attr callback"));
304 SILC_LOG_DEBUG(("Request ID: %d", id));
306 if (status != SILC_SFTP_STATUS_OK) {
307 silc_sftp_send_error(server, status, id);
311 attr_buf = silc_sftp_attr_encode(attrs);
313 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);
317 silc_sftp_send_packet(server, SILC_SFTP_ATTRS, 4 + silc_buffer_len(attr_buf),
319 SILC_STR_DATA(silc_buffer_data(attr_buf),
320 silc_buffer_len(attr_buf)),
323 silc_buffer_free(attr_buf);
326 /* Extended callback */
328 static void silc_sftp_server_extended(SilcSFTP sftp,
329 SilcSFTPStatus status,
330 const unsigned char *data,
334 SilcSFTPServer server = (SilcSFTPServer)sftp;
335 SilcUInt32 id = SILC_PTR_TO_32(context);
337 SILC_LOG_DEBUG(("Extended callback"));
338 SILC_LOG_DEBUG(("Request ID: %d", id));
340 if (status != SILC_SFTP_STATUS_OK) {
341 silc_sftp_send_error(server, status, id);
345 silc_sftp_send_packet(server, SILC_SFTP_EXTENDED, 4 + data_len,
347 SILC_STR_UI_XNSTRING(data, data_len),
351 /* Starts SFTP server and returns context to it. This function returns the
352 allocated SFTP client context or NULL on error. The `send_packet' is called
353 by the library when it needs to send a packet. The `fs' is the
354 structure containing filesystem access callbacks. */
356 SilcSFTP silc_sftp_server_start(SilcStream stream,
357 SilcSchedule schedule,
358 SilcSFTPErrorCallback error_cb,
360 SilcSFTPFilesystem fs)
362 SilcSFTPServer server;
365 schedule = silc_schedule_get_global();
367 server = silc_calloc(1, sizeof(*server));
370 server->stream = stream;
371 server->schedule = schedule;
372 server->error = error_cb;
373 server->context = context;
376 /* We handle the stream now */
377 silc_stream_set_notifier(stream, schedule, silc_sftp_server_io, server);
379 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
381 return (SilcSFTP)server;
384 /* Shutdown's the SFTP server. The caller is responsible of closing
385 the associated socket connection. The SFTP context is freed and is
386 invalid after this function returns. */
388 void silc_sftp_server_shutdown(SilcSFTP sftp)
390 SilcSFTPServer server = (SilcSFTPServer)sftp;
392 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
394 silc_stream_set_notifier(server->stream, server->schedule, NULL, NULL);
396 silc_buffer_free(server->packet);
400 /* Sets monitor callback */
402 void silc_sftp_server_set_monitor(SilcSFTP sftp,
403 SilcSFTPMonitors monitors,
404 SilcSFTPMonitor monitor,
407 SilcSFTPServer server = (SilcSFTPServer)sftp;
408 server->monitors = monitors;
409 server->monitor = monitor;
410 server->monitor_context = context;
413 /* Function that is called to process the incmoing SFTP packet. */
415 static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer)
417 SilcSFTPServer server = (SilcSFTPServer)sftp;
419 char *filename = NULL, *path = NULL;
420 unsigned char *payload = NULL;
421 SilcUInt32 payload_len;
423 SilcBufferStruct buf;
425 SilcSFTPAttributes attrs;
426 SilcSFTPHandle handle;
427 SilcSFTPMonitorDataStruct mdata;
429 SILC_LOG_DEBUG(("Start"));
431 /* Parse the packet */
432 type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
436 silc_buffer_set(&buf, payload, payload_len);
438 memset(&mdata, 0, sizeof(mdata));
443 unsigned char *hdata;
444 SilcUInt32 hdata_len;
448 SILC_LOG_DEBUG(("Read request"));
450 ret = silc_buffer_unformat(&buf,
451 SILC_STR_UI_INT(&id),
452 SILC_STR_UI32_NSTRING(&hdata,
454 SILC_STR_UI_INT64(&offset),
455 SILC_STR_UI_INT(&len),
461 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
462 (const unsigned char *)hdata,
465 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
470 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
472 silc_sftp_server_data, SILC_32_TO_PTR(id));
475 if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
476 mdata.offset = offset;
477 mdata.data_len = len;
478 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
479 server->monitor_context);
484 case SILC_SFTP_WRITE:
486 unsigned char *hdata;
487 SilcUInt32 hdata_len;
492 SILC_LOG_DEBUG(("Read request"));
494 ret = silc_buffer_unformat(&buf,
495 SILC_STR_UI_INT(&id),
496 SILC_STR_UI32_NSTRING(&hdata,
498 SILC_STR_UI_INT64(&offset),
499 SILC_STR_UI32_NSTRING(&data,
506 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
507 (const unsigned char *)hdata,
510 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
514 /* Write operation */
515 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
516 (const unsigned char *)data, data_len,
517 silc_sftp_server_status, SILC_32_TO_PTR(id));
520 if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
521 mdata.offset = offset;
522 mdata.data_len = data_len;
523 (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
524 server->monitor_context);
531 SilcSFTPVersion version;
533 SILC_LOG_DEBUG(("Init request"));
535 ret = silc_buffer_unformat(&buf,
536 SILC_STR_UI_INT(&version),
542 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
543 mdata.version = version;
544 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
545 server->monitor_context);
548 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
549 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
556 SilcSFTPFileOperation pflags;
557 unsigned char *attr_buf;
558 SilcUInt32 attr_len = 0;
559 SilcBufferStruct tmpbuf;
561 SILC_LOG_DEBUG(("Open request"));
563 ret = silc_buffer_unformat(&buf,
564 SILC_STR_UI_INT(&id),
565 SILC_STR_UI32_STRING_ALLOC(&filename),
566 SILC_STR_UI_INT(&pflags),
567 SILC_STR_UI32_NSTRING(&attr_buf,
574 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
575 attrs = silc_sftp_attr_decode(&tmpbuf);
579 attrs = silc_calloc(1, sizeof(*attrs));
585 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
586 mdata.name = filename;
587 mdata.pflags = pflags;
588 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
589 server->monitor_context);
593 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
594 attrs, silc_sftp_server_handle,
598 silc_sftp_attr_free(attrs);
602 case SILC_SFTP_CLOSE:
604 unsigned char *hdata;
605 SilcUInt32 hdata_len;
607 SILC_LOG_DEBUG(("Close request"));
609 ret = silc_buffer_unformat(&buf,
610 SILC_STR_UI_INT(&id),
611 SILC_STR_UI32_NSTRING(&hdata,
618 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
619 (const unsigned char *)hdata,
622 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
627 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
628 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
629 server->monitor_context);
632 /* Close operation */
633 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
634 silc_sftp_server_status, SILC_32_TO_PTR(id));
639 case SILC_SFTP_REMOVE:
641 SILC_LOG_DEBUG(("Remove request"));
643 ret = silc_buffer_unformat(&buf,
644 SILC_STR_UI_INT(&id),
645 SILC_STR_UI32_STRING_ALLOC(&filename),
651 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
652 mdata.name = filename;
653 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
654 server->monitor_context);
657 /* Remove operation */
658 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
659 silc_sftp_server_status, SILC_32_TO_PTR(id));
665 case SILC_SFTP_RENAME:
667 char *newname = NULL;
669 SILC_LOG_DEBUG(("Rename request"));
671 ret = silc_buffer_unformat(&buf,
672 SILC_STR_UI_INT(&id),
673 SILC_STR_UI32_STRING_ALLOC(&filename),
674 SILC_STR_UI32_STRING_ALLOC(&newname),
680 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
681 mdata.name = filename;
682 mdata.name2 = newname;
683 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
684 server->monitor_context);
687 /* Rename operation */
688 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
690 silc_sftp_server_status, SILC_32_TO_PTR(id));
697 case SILC_SFTP_MKDIR:
699 unsigned char *attr_buf;
700 SilcUInt32 attr_len = 0;
701 SilcBufferStruct tmpbuf;
703 SILC_LOG_DEBUG(("Mkdir request"));
705 ret = silc_buffer_unformat(&buf,
706 SILC_STR_UI_INT(&id),
707 SILC_STR_UI32_STRING_ALLOC(&path),
708 SILC_STR_UI32_NSTRING(&attr_buf,
715 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
716 attrs = silc_sftp_attr_decode(&tmpbuf);
720 attrs = silc_calloc(1, sizeof(*attrs));
726 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
728 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
729 server->monitor_context);
732 /* Mkdir operation */
733 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
734 silc_sftp_server_status, SILC_32_TO_PTR(id));
736 silc_sftp_attr_free(attrs);
741 case SILC_SFTP_RMDIR:
743 SILC_LOG_DEBUG(("Rmdir request"));
745 ret = silc_buffer_unformat(&buf,
746 SILC_STR_UI_INT(&id),
747 SILC_STR_UI32_STRING_ALLOC(&path),
753 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
755 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
756 server->monitor_context);
759 /* Rmdir operation */
760 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
761 silc_sftp_server_status, SILC_32_TO_PTR(id));
767 case SILC_SFTP_OPENDIR:
769 SILC_LOG_DEBUG(("Opendir request"));
771 ret = silc_buffer_unformat(&buf,
772 SILC_STR_UI_INT(&id),
773 SILC_STR_UI32_STRING_ALLOC(&path),
779 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
781 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
782 server->monitor_context);
785 /* Opendir operation */
786 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
787 silc_sftp_server_handle, SILC_32_TO_PTR(id));
793 case SILC_SFTP_READDIR:
795 unsigned char *hdata;
796 SilcUInt32 hdata_len;
798 SILC_LOG_DEBUG(("Readdir request"));
800 ret = silc_buffer_unformat(&buf,
801 SILC_STR_UI_INT(&id),
802 SILC_STR_UI32_NSTRING(&hdata,
809 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
810 (const unsigned char *)hdata,
813 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
818 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
819 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
820 server->monitor_context);
823 /* Readdir operation */
824 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
825 silc_sftp_server_name, SILC_32_TO_PTR(id));
831 SILC_LOG_DEBUG(("Stat request"));
833 ret = silc_buffer_unformat(&buf,
834 SILC_STR_UI_INT(&id),
835 SILC_STR_UI32_STRING_ALLOC(&path),
841 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
843 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
844 server->monitor_context);
848 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
849 silc_sftp_server_attr, SILC_32_TO_PTR(id));
855 case SILC_SFTP_LSTAT:
857 SILC_LOG_DEBUG(("Lstat request"));
859 ret = silc_buffer_unformat(&buf,
860 SILC_STR_UI_INT(&id),
861 SILC_STR_UI32_STRING_ALLOC(&path),
867 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
869 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
870 server->monitor_context);
873 /* Lstat operation */
874 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
875 silc_sftp_server_attr, SILC_32_TO_PTR(id));
881 case SILC_SFTP_FSTAT:
883 unsigned char *hdata;
884 SilcUInt32 hdata_len;
886 SILC_LOG_DEBUG(("Fstat request"));
888 ret = silc_buffer_unformat(&buf,
889 SILC_STR_UI_INT(&id),
890 SILC_STR_UI32_NSTRING(&hdata,
897 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
898 (const unsigned char *)hdata,
901 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
906 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
907 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
908 server->monitor_context);
911 /* Fstat operation */
912 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
913 silc_sftp_server_attr, SILC_32_TO_PTR(id));
917 case SILC_SFTP_SETSTAT:
919 unsigned char *attr_buf;
920 SilcUInt32 attr_len = 0;
921 SilcBufferStruct tmpbuf;
923 SILC_LOG_DEBUG(("Setstat request"));
925 ret = silc_buffer_unformat(&buf,
926 SILC_STR_UI_INT(&id),
927 SILC_STR_UI32_STRING_ALLOC(&path),
928 SILC_STR_UI32_NSTRING(&attr_buf,
935 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
936 attrs = silc_sftp_attr_decode(&tmpbuf);
940 attrs = silc_calloc(1, sizeof(*attrs));
946 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
948 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
949 server->monitor_context);
952 /* Setstat operation */
953 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
954 silc_sftp_server_status,
957 silc_sftp_attr_free(attrs);
962 case SILC_SFTP_FSETSTAT:
964 unsigned char *hdata, *attr_buf;
965 SilcUInt32 hdata_len, attr_len = 0;
966 SilcBufferStruct tmpbuf;
968 SILC_LOG_DEBUG(("Fsetstat request"));
970 ret = silc_buffer_unformat(&buf,
971 SILC_STR_UI_INT(&id),
972 SILC_STR_UI32_NSTRING(&hdata,
974 SILC_STR_UI32_NSTRING(&attr_buf,
981 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
982 attrs = silc_sftp_attr_decode(&tmpbuf);
986 attrs = silc_calloc(1, sizeof(*attrs));
992 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
993 (const unsigned char *)hdata,
996 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
1001 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
1002 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
1003 server->monitor_context);
1006 /* Fsetstat operation */
1007 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
1009 silc_sftp_server_status,
1010 SILC_32_TO_PTR(id));
1012 silc_sftp_attr_free(attrs);
1016 case SILC_SFTP_READLINK:
1018 SILC_LOG_DEBUG(("Readlink request"));
1020 ret = silc_buffer_unformat(&buf,
1021 SILC_STR_UI_INT(&id),
1022 SILC_STR_UI32_STRING_ALLOC(&path),
1028 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
1030 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
1031 server->monitor_context);
1034 /* Readlink operation */
1035 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
1036 silc_sftp_server_name, SILC_32_TO_PTR(id));
1042 case SILC_SFTP_SYMLINK:
1044 char *target = NULL;
1046 SILC_LOG_DEBUG(("Symlink request"));
1048 ret = silc_buffer_unformat(&buf,
1049 SILC_STR_UI_INT(&id),
1050 SILC_STR_UI32_STRING_ALLOC(&path),
1051 SILC_STR_UI32_STRING_ALLOC(&target),
1057 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
1059 mdata.name2 = target;
1060 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
1061 server->monitor_context);
1064 /* Symlink operation */
1065 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
1066 silc_sftp_server_status,
1067 SILC_32_TO_PTR(id));
1074 case SILC_SFTP_REALPATH:
1076 SILC_LOG_DEBUG(("Realpath request"));
1078 ret = silc_buffer_unformat(&buf,
1079 SILC_STR_UI_INT(&id),
1080 SILC_STR_UI32_STRING_ALLOC(&path),
1086 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
1088 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
1089 server->monitor_context);
1092 /* Realpath operation */
1093 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
1094 silc_sftp_server_name, SILC_32_TO_PTR(id));
1100 case SILC_SFTP_EXTENDED:
1102 char *request = NULL;
1103 unsigned char *data;
1104 SilcUInt32 data_len;
1106 SILC_LOG_DEBUG(("Extended request"));
1108 ret = silc_buffer_unformat(&buf,
1109 SILC_STR_UI_INT(&id),
1110 SILC_STR_UI32_STRING_ALLOC(&request),
1115 data_len = 8 + strlen(request);
1116 silc_buffer_pull(&buf, data_len);
1117 ret = silc_buffer_unformat(&buf,
1118 SILC_STR_DATA(&data, silc_buffer_len(&buf)),
1122 data_len = silc_buffer_len(&buf);
1125 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1126 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1127 server->monitor_context);
1130 /* Extended operation */
1131 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1132 request, data, data_len,
1133 silc_sftp_server_extended,
1134 SILC_32_TO_PTR(id));
1147 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);