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;
364 server = silc_calloc(1, sizeof(*server));
367 server->stream = stream;
368 server->schedule = schedule;
369 server->error = error_cb;
370 server->context = context;
373 /* We handle the stream now */
374 silc_stream_set_notifier(stream, schedule, silc_sftp_server_io, server);
376 SILC_LOG_DEBUG(("Starting SFTP server %p", server));
378 return (SilcSFTP)server;
381 /* Shutdown's the SFTP server. The caller is responsible of closing
382 the associated socket connection. The SFTP context is freed and is
383 invalid after this function returns. */
385 void silc_sftp_server_shutdown(SilcSFTP sftp)
387 SilcSFTPServer server = (SilcSFTPServer)sftp;
389 SILC_LOG_DEBUG(("Stopping SFTP server %p", server));
391 silc_stream_set_notifier(server->stream, server->schedule, NULL, NULL);
393 silc_buffer_free(server->packet);
397 /* Sets monitor callback */
399 void silc_sftp_server_set_monitor(SilcSFTP sftp,
400 SilcSFTPMonitors monitors,
401 SilcSFTPMonitor monitor,
404 SilcSFTPServer server = (SilcSFTPServer)sftp;
405 server->monitors = monitors;
406 server->monitor = monitor;
407 server->monitor_context = context;
410 /* Function that is called to process the incmoing SFTP packet. */
412 static void silc_sftp_server_receive_process(SilcSFTP sftp, SilcBuffer buffer)
414 SilcSFTPServer server = (SilcSFTPServer)sftp;
416 char *filename = NULL, *path = NULL;
417 unsigned char *payload = NULL;
418 SilcUInt32 payload_len;
420 SilcBufferStruct buf;
422 SilcSFTPAttributes attrs;
423 SilcSFTPHandle handle;
424 SilcSFTPMonitorDataStruct mdata;
426 SILC_LOG_DEBUG(("Start"));
428 /* Parse the packet */
429 type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
433 silc_buffer_set(&buf, payload, payload_len);
435 memset(&mdata, 0, sizeof(mdata));
440 unsigned char *hdata;
441 SilcUInt32 hdata_len;
445 SILC_LOG_DEBUG(("Read request"));
447 ret = silc_buffer_unformat(&buf,
448 SILC_STR_UI_INT(&id),
449 SILC_STR_UI32_NSTRING(&hdata,
451 SILC_STR_UI_INT64(&offset),
452 SILC_STR_UI_INT(&len),
458 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
459 (const unsigned char *)hdata,
462 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
467 server->fs->fs->sftp_read(server->fs->fs_context, sftp,
469 silc_sftp_server_data, SILC_32_TO_PTR(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);
481 case SILC_SFTP_WRITE:
483 unsigned char *hdata;
484 SilcUInt32 hdata_len;
489 SILC_LOG_DEBUG(("Read request"));
491 ret = silc_buffer_unformat(&buf,
492 SILC_STR_UI_INT(&id),
493 SILC_STR_UI32_NSTRING(&hdata,
495 SILC_STR_UI_INT64(&offset),
496 SILC_STR_UI32_NSTRING(&data,
503 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
504 (const unsigned char *)hdata,
507 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
511 /* Write operation */
512 server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
513 (const unsigned char *)data, data_len,
514 silc_sftp_server_status, SILC_32_TO_PTR(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);
528 SilcSFTPVersion version;
530 SILC_LOG_DEBUG(("Init request"));
532 ret = silc_buffer_unformat(&buf,
533 SILC_STR_UI_INT(&version),
539 if (server->monitors & SILC_SFTP_MONITOR_INIT && server->monitor) {
540 mdata.version = version;
541 (*server->monitor)(sftp, SILC_SFTP_MONITOR_INIT, &mdata,
542 server->monitor_context);
545 silc_sftp_send_packet(server, SILC_SFTP_VERSION, 4,
546 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
553 SilcSFTPFileOperation pflags;
554 unsigned char *attr_buf;
555 SilcUInt32 attr_len = 0;
556 SilcBufferStruct tmpbuf;
558 SILC_LOG_DEBUG(("Open request"));
560 ret = silc_buffer_unformat(&buf,
561 SILC_STR_UI_INT(&id),
562 SILC_STR_UI32_STRING_ALLOC(&filename),
563 SILC_STR_UI_INT(&pflags),
564 SILC_STR_UI32_NSTRING(&attr_buf,
571 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
572 attrs = silc_sftp_attr_decode(&tmpbuf);
576 attrs = silc_calloc(1, sizeof(*attrs));
582 if (server->monitors & SILC_SFTP_MONITOR_OPEN && server->monitor) {
583 mdata.name = filename;
584 mdata.pflags = pflags;
585 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPEN, &mdata,
586 server->monitor_context);
590 server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
591 attrs, silc_sftp_server_handle,
595 silc_sftp_attr_free(attrs);
599 case SILC_SFTP_CLOSE:
601 unsigned char *hdata;
602 SilcUInt32 hdata_len;
604 SILC_LOG_DEBUG(("Close request"));
606 ret = silc_buffer_unformat(&buf,
607 SILC_STR_UI_INT(&id),
608 SILC_STR_UI32_NSTRING(&hdata,
615 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
616 (const unsigned char *)hdata,
619 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
624 if (server->monitors & SILC_SFTP_MONITOR_CLOSE && server->monitor) {
625 (*server->monitor)(sftp, SILC_SFTP_MONITOR_CLOSE, &mdata,
626 server->monitor_context);
629 /* Close operation */
630 server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
631 silc_sftp_server_status, SILC_32_TO_PTR(id));
636 case SILC_SFTP_REMOVE:
638 SILC_LOG_DEBUG(("Remove request"));
640 ret = silc_buffer_unformat(&buf,
641 SILC_STR_UI_INT(&id),
642 SILC_STR_UI32_STRING_ALLOC(&filename),
648 if (server->monitors & SILC_SFTP_MONITOR_REMOVE && server->monitor) {
649 mdata.name = filename;
650 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REMOVE, &mdata,
651 server->monitor_context);
654 /* Remove operation */
655 server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
656 silc_sftp_server_status, SILC_32_TO_PTR(id));
662 case SILC_SFTP_RENAME:
664 char *newname = NULL;
666 SILC_LOG_DEBUG(("Rename request"));
668 ret = silc_buffer_unformat(&buf,
669 SILC_STR_UI_INT(&id),
670 SILC_STR_UI32_STRING_ALLOC(&filename),
671 SILC_STR_UI32_STRING_ALLOC(&newname),
677 if (server->monitors & SILC_SFTP_MONITOR_RENAME && server->monitor) {
678 mdata.name = filename;
679 mdata.name2 = newname;
680 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RENAME, &mdata,
681 server->monitor_context);
684 /* Rename operation */
685 server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
687 silc_sftp_server_status, SILC_32_TO_PTR(id));
694 case SILC_SFTP_MKDIR:
696 unsigned char *attr_buf;
697 SilcUInt32 attr_len = 0;
698 SilcBufferStruct tmpbuf;
700 SILC_LOG_DEBUG(("Mkdir request"));
702 ret = silc_buffer_unformat(&buf,
703 SILC_STR_UI_INT(&id),
704 SILC_STR_UI32_STRING_ALLOC(&path),
705 SILC_STR_UI32_NSTRING(&attr_buf,
712 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
713 attrs = silc_sftp_attr_decode(&tmpbuf);
717 attrs = silc_calloc(1, sizeof(*attrs));
723 if (server->monitors & SILC_SFTP_MONITOR_MKDIR && server->monitor) {
725 (*server->monitor)(sftp, SILC_SFTP_MONITOR_MKDIR, &mdata,
726 server->monitor_context);
729 /* Mkdir operation */
730 server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
731 silc_sftp_server_status, SILC_32_TO_PTR(id));
733 silc_sftp_attr_free(attrs);
738 case SILC_SFTP_RMDIR:
740 SILC_LOG_DEBUG(("Rmdir request"));
742 ret = silc_buffer_unformat(&buf,
743 SILC_STR_UI_INT(&id),
744 SILC_STR_UI32_STRING_ALLOC(&path),
750 if (server->monitors & SILC_SFTP_MONITOR_RMDIR && server->monitor) {
752 (*server->monitor)(sftp, SILC_SFTP_MONITOR_RMDIR, &mdata,
753 server->monitor_context);
756 /* Rmdir operation */
757 server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
758 silc_sftp_server_status, SILC_32_TO_PTR(id));
764 case SILC_SFTP_OPENDIR:
766 SILC_LOG_DEBUG(("Opendir request"));
768 ret = silc_buffer_unformat(&buf,
769 SILC_STR_UI_INT(&id),
770 SILC_STR_UI32_STRING_ALLOC(&path),
776 if (server->monitors & SILC_SFTP_MONITOR_OPENDIR && server->monitor) {
778 (*server->monitor)(sftp, SILC_SFTP_MONITOR_OPENDIR, &mdata,
779 server->monitor_context);
782 /* Opendir operation */
783 server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
784 silc_sftp_server_handle, SILC_32_TO_PTR(id));
790 case SILC_SFTP_READDIR:
792 unsigned char *hdata;
793 SilcUInt32 hdata_len;
795 SILC_LOG_DEBUG(("Readdir request"));
797 ret = silc_buffer_unformat(&buf,
798 SILC_STR_UI_INT(&id),
799 SILC_STR_UI32_NSTRING(&hdata,
806 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
807 (const unsigned char *)hdata,
810 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
815 if (server->monitors & SILC_SFTP_MONITOR_READDIR && server->monitor) {
816 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READDIR, &mdata,
817 server->monitor_context);
820 /* Readdir operation */
821 server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
822 silc_sftp_server_name, SILC_32_TO_PTR(id));
828 SILC_LOG_DEBUG(("Stat request"));
830 ret = silc_buffer_unformat(&buf,
831 SILC_STR_UI_INT(&id),
832 SILC_STR_UI32_STRING_ALLOC(&path),
838 if (server->monitors & SILC_SFTP_MONITOR_STAT && server->monitor) {
840 (*server->monitor)(sftp, SILC_SFTP_MONITOR_STAT, &mdata,
841 server->monitor_context);
845 server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
846 silc_sftp_server_attr, SILC_32_TO_PTR(id));
852 case SILC_SFTP_LSTAT:
854 SILC_LOG_DEBUG(("Lstat request"));
856 ret = silc_buffer_unformat(&buf,
857 SILC_STR_UI_INT(&id),
858 SILC_STR_UI32_STRING_ALLOC(&path),
864 if (server->monitors & SILC_SFTP_MONITOR_LSTAT && server->monitor) {
866 (*server->monitor)(sftp, SILC_SFTP_MONITOR_LSTAT, &mdata,
867 server->monitor_context);
870 /* Lstat operation */
871 server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
872 silc_sftp_server_attr, SILC_32_TO_PTR(id));
878 case SILC_SFTP_FSTAT:
880 unsigned char *hdata;
881 SilcUInt32 hdata_len;
883 SILC_LOG_DEBUG(("Fstat request"));
885 ret = silc_buffer_unformat(&buf,
886 SILC_STR_UI_INT(&id),
887 SILC_STR_UI32_NSTRING(&hdata,
894 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
895 (const unsigned char *)hdata,
898 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
903 if (server->monitors & SILC_SFTP_MONITOR_FSTAT && server->monitor) {
904 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSTAT, &mdata,
905 server->monitor_context);
908 /* Fstat operation */
909 server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
910 silc_sftp_server_attr, SILC_32_TO_PTR(id));
914 case SILC_SFTP_SETSTAT:
916 unsigned char *attr_buf;
917 SilcUInt32 attr_len = 0;
918 SilcBufferStruct tmpbuf;
920 SILC_LOG_DEBUG(("Setstat request"));
922 ret = silc_buffer_unformat(&buf,
923 SILC_STR_UI_INT(&id),
924 SILC_STR_UI32_STRING_ALLOC(&path),
925 SILC_STR_UI32_NSTRING(&attr_buf,
932 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
933 attrs = silc_sftp_attr_decode(&tmpbuf);
937 attrs = silc_calloc(1, sizeof(*attrs));
943 if (server->monitors & SILC_SFTP_MONITOR_SETSTAT && server->monitor) {
945 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SETSTAT, &mdata,
946 server->monitor_context);
949 /* Setstat operation */
950 server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
951 silc_sftp_server_status,
954 silc_sftp_attr_free(attrs);
959 case SILC_SFTP_FSETSTAT:
961 unsigned char *hdata, *attr_buf;
962 SilcUInt32 hdata_len, attr_len = 0;
963 SilcBufferStruct tmpbuf;
965 SILC_LOG_DEBUG(("Fsetstat request"));
967 ret = silc_buffer_unformat(&buf,
968 SILC_STR_UI_INT(&id),
969 SILC_STR_UI32_NSTRING(&hdata,
971 SILC_STR_UI32_NSTRING(&attr_buf,
978 silc_buffer_set(&tmpbuf, attr_buf, attr_len);
979 attrs = silc_sftp_attr_decode(&tmpbuf);
983 attrs = silc_calloc(1, sizeof(*attrs));
989 handle = server->fs->fs->sftp_get_handle(server->fs->fs_context, sftp,
990 (const unsigned char *)hdata,
993 silc_sftp_send_error(server, SILC_SFTP_STATUS_NO_SUCH_FILE, id);
998 if (server->monitors & SILC_SFTP_MONITOR_FSETSTAT && server->monitor) {
999 (*server->monitor)(sftp, SILC_SFTP_MONITOR_FSETSTAT, &mdata,
1000 server->monitor_context);
1003 /* Fsetstat operation */
1004 server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
1006 silc_sftp_server_status,
1007 SILC_32_TO_PTR(id));
1009 silc_sftp_attr_free(attrs);
1013 case SILC_SFTP_READLINK:
1015 SILC_LOG_DEBUG(("Readlink request"));
1017 ret = silc_buffer_unformat(&buf,
1018 SILC_STR_UI_INT(&id),
1019 SILC_STR_UI32_STRING_ALLOC(&path),
1025 if (server->monitors & SILC_SFTP_MONITOR_READLINK && server->monitor) {
1027 (*server->monitor)(sftp, SILC_SFTP_MONITOR_READLINK, &mdata,
1028 server->monitor_context);
1031 /* Readlink operation */
1032 server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
1033 silc_sftp_server_name, SILC_32_TO_PTR(id));
1039 case SILC_SFTP_SYMLINK:
1041 char *target = NULL;
1043 SILC_LOG_DEBUG(("Symlink request"));
1045 ret = silc_buffer_unformat(&buf,
1046 SILC_STR_UI_INT(&id),
1047 SILC_STR_UI32_STRING_ALLOC(&path),
1048 SILC_STR_UI32_STRING_ALLOC(&target),
1054 if (server->monitors & SILC_SFTP_MONITOR_SYMLINK && server->monitor) {
1056 mdata.name2 = target;
1057 (*server->monitor)(sftp, SILC_SFTP_MONITOR_SYMLINK, &mdata,
1058 server->monitor_context);
1061 /* Symlink operation */
1062 server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
1063 silc_sftp_server_status,
1064 SILC_32_TO_PTR(id));
1071 case SILC_SFTP_REALPATH:
1073 SILC_LOG_DEBUG(("Realpath request"));
1075 ret = silc_buffer_unformat(&buf,
1076 SILC_STR_UI_INT(&id),
1077 SILC_STR_UI32_STRING_ALLOC(&path),
1083 if (server->monitors & SILC_SFTP_MONITOR_REALPATH && server->monitor) {
1085 (*server->monitor)(sftp, SILC_SFTP_MONITOR_REALPATH, &mdata,
1086 server->monitor_context);
1089 /* Realpath operation */
1090 server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
1091 silc_sftp_server_name, SILC_32_TO_PTR(id));
1097 case SILC_SFTP_EXTENDED:
1099 char *request = NULL;
1100 unsigned char *data;
1101 SilcUInt32 data_len;
1103 SILC_LOG_DEBUG(("Extended request"));
1105 ret = silc_buffer_unformat(&buf,
1106 SILC_STR_UI_INT(&id),
1107 SILC_STR_UI32_STRING_ALLOC(&request),
1112 data_len = 8 + strlen(request);
1113 silc_buffer_pull(&buf, data_len);
1114 ret = silc_buffer_unformat(&buf,
1115 SILC_STR_DATA(&data, silc_buffer_len(&buf)),
1119 data_len = silc_buffer_len(&buf);
1122 if (server->monitors & SILC_SFTP_MONITOR_EXTENDED && server->monitor) {
1123 (*server->monitor)(sftp, SILC_SFTP_MONITOR_EXTENDED, &mdata,
1124 server->monitor_context);
1127 /* Extended operation */
1128 server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
1129 request, data, data_len,
1130 silc_sftp_server_extended,
1131 SILC_32_TO_PTR(id));
1144 silc_sftp_send_error(server, SILC_SFTP_STATUS_FAILURE, id);