5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2005 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 "sftp_util.h"
25 /* Request context. Every request will allocate this context and set
26 the correct callback function according the `type' field. */
27 typedef struct SilcSFTPRequestStruct {
30 SilcSFTPStatusCallback status;
31 SilcSFTPHandleCallback handle;
32 SilcSFTPDataCallback data;
33 SilcSFTPNameCallback name;
34 SilcSFTPAttrCallback attr;
35 SilcSFTPExtendedCallback extended;
37 struct SilcSFTPRequestStruct *next;
40 /* SFTP client context */
43 SilcSFTPVersionCallback version;
44 void *version_context;
51 struct SilcSFTPHandleStruct {
56 static void silc_sftp_client_receive_process(SilcSFTP context,
59 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
62 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
65 SilcSFTPHandle handle;
67 handle = silc_calloc(1, sizeof(*handle));
70 handle->data = silc_calloc(data_len, sizeof(*handle->data));
73 memcpy(handle->data, data, data_len);
74 handle->data_len = data_len;
79 /* Deletes the handle indicated by the `handle'. */
81 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
83 silc_free(handle->data);
87 /* Returns the handle data of the `handle' to the `data' pointer. */
89 static void silc_sftp_handle_get(SilcSFTPHandle handle,
90 const unsigned char **data,
93 *data = (const unsigned char *)handle->data;
94 *data_len = handle->data_len;
97 /* General routine to send SFTP packet to the SFTP server. */
99 static void silc_sftp_send_packet(SilcSFTPClient sftp,
107 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
113 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
114 silc_buffer_len(sftp->packet));
116 /* Send the packet */
117 silc_stream_write(sftp->stream, sftp->packet->data,
118 silc_buffer_len(sftp->packet));
121 silc_buffer_reset(sftp->packet);
124 /* Finds request by request ID. */
126 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp,
131 SILC_LOG_DEBUG(("Finding request ID: %d", id));
133 silc_list_start(sftp->requests);
134 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
139 SILC_LOG_DEBUG(("Unknown request ID"));
144 /* Function used to call the request callback indicated by the `req'. The
145 `status' will be sent to the callback function as the status of the
146 operation. The variable argument list includes the status and req->type
149 static void silc_sftp_call_request(SilcSFTPClient sftp,
152 SilcSFTPStatus status, ...)
156 SILC_LOG_DEBUG(("Start"));
158 va_start(vp, status);
167 if (status != SILC_SFTP_STATUS_OK) {
169 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
173 data = (unsigned char *)va_arg(vp, unsigned char *);
174 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
177 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
178 data_len, req->context);
183 case SILC_SFTP_OPENDIR:
185 /* Handle returned */
186 SilcSFTPHandle handle;
187 unsigned char *hdata;
188 SilcUInt32 hdata_len;
190 if (status != SILC_SFTP_STATUS_OK) {
192 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
196 hdata = (unsigned char *)va_arg(vp, unsigned char *);
197 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
198 handle = silc_sftp_handle_create(hdata, hdata_len);
201 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
206 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
210 case SILC_SFTP_CLOSE:
211 case SILC_SFTP_WRITE:
212 case SILC_SFTP_REMOVE:
213 case SILC_SFTP_RENAME:
214 case SILC_SFTP_MKDIR:
215 case SILC_SFTP_RMDIR:
216 case SILC_SFTP_SETSTAT:
217 case SILC_SFTP_FSETSTAT:
218 case SILC_SFTP_SYMLINK:
220 /* Status returned */
221 char *message, *language_tag;
223 message = (char *)va_arg(vp, char *);
224 language_tag = (char *)va_arg(vp, char *);
227 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
228 (const char *)language_tag, req->context);
233 case SILC_SFTP_LSTAT:
234 case SILC_SFTP_FSTAT:
236 /* Attributes returned */
237 SilcSFTPAttributes attr;
239 if (status != SILC_SFTP_STATUS_OK) {
241 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
245 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
248 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
253 case SILC_SFTP_READDIR:
254 case SILC_SFTP_REALPATH:
255 case SILC_SFTP_READLINK:
257 /* Name(s) returned */
260 if (status != SILC_SFTP_STATUS_OK) {
262 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
266 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
269 (*req->name)((SilcSFTP)sftp, status, name, req->context);
273 case SILC_SFTP_EXTENDED:
275 /* Extended reply returned */
279 if (status != SILC_SFTP_STATUS_OK) {
281 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
285 data = (unsigned char *)va_arg(vp, unsigned char *);
286 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
289 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
290 data_len, req->context);
298 /* Remove this request */
299 silc_list_del(sftp->requests, req);
305 /* Handles stream IO */
307 static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status,
310 SilcSFTPClient sftp = context;
314 case SILC_STREAM_CAN_WRITE:
315 if (!silc_buffer_headlen(&sftp->packet))
318 SILC_LOG_DEBUG(("Writing pending data to stream"));
320 /* Write pending data to stream */
321 silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
322 while (silc_buffer_len(sftp->packet) > 0) {
323 ret = silc_stream_write(stream, sftp->packet->data,
324 silc_buffer_len(sftp->packet));
328 silc_buffer_reset(sftp->packet);
335 silc_buffer_reset(sftp->packet);
340 /* Cannot write now, write later. */
341 silc_buffer_pull(sftp->packet, silc_buffer_len(sftp->packet));
346 silc_buffer_pull(sftp->packet, ret);
350 case SILC_STREAM_CAN_READ:
351 SILC_LOG_DEBUG(("Reading data from stream"));
353 /* Make sure we have fair amount of free space in inbuf */
354 if (silc_buffer_taillen(&ps->inbuf) < SILC_PACKET_DEFAULT_SIZE)
355 if (!silc_buffer_realloc(&ps->inbuf, silc_buffer_truelen(&ps->inbuf) +
356 SILC_PACKET_DEFAULT_SIZE * 2))
359 /* Read data from stream */
360 ret = silc_stream_read(ps->stream, &ps->inbuf.tail,
361 silc_buffer_taillen(&ps->inbuf));
365 SILC_PACKET_CALLBACK_EOS(ps);
366 silc_buffer_reset(&ps->inbuf);
372 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
373 silc_buffer_reset(&ps->inbuf);
378 /* Cannot read now, do it later. */
379 silc_buffer_pull(&ps->inbuf, silc_buffer_len(&ps->inbuf));
384 silc_buffer_pull_tail(&ps->inbuf, ret);
386 /* Now process the data */
387 silc_sftp_client_receive_process(sftp);
395 /* Starts SFTP client and returns context for it. */
397 SilcSFTP silc_sftp_client_start(SilcStream stream,
398 SilcSFTPVersionCallback callback,
406 sftp = silc_calloc(1, sizeof(*sftp));
409 sftp->stream = stream;
410 sftp->version = callback;
411 sftp->version_context = context;
412 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
414 /* We handle the stream now */
415 silc_stream_set_notifier(stream, silc_sftp_client_io, sftp);
417 /* Send the SFTP session initialization to the server */
418 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
419 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
422 return (SilcSFTP)sftp;
425 /* Shutdown's the SFTP client. The caller is responsible of closing
426 the associated socket connection. The SFTP context is freed and is
427 invalid after this function returns. */
429 void silc_sftp_client_shutdown(SilcSFTP context)
431 SilcSFTPClient sftp = (SilcSFTPClient)context;
434 silc_buffer_free(sftp->packet);
438 /* Function that is called to process the incmoing SFTP packet. */
440 void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer)
442 SilcSFTPClient sftp = (SilcSFTPClient)context;
445 const unsigned char *payload = NULL;
446 SilcUInt32 payload_len;
448 SilcBufferStruct buf;
451 SILC_LOG_DEBUG(("Start"));
453 /* Parse the packet */
454 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
459 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
462 case SILC_SFTP_VERSION:
464 SilcSFTPVersion version;
466 SILC_LOG_DEBUG(("Version packet"));
468 ret = silc_buffer_unformat(&buf,
469 SILC_STR_UI_INT(&version),
472 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
473 sftp->version_context);
477 /* Call the callback */
478 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
479 sftp->version_context);
483 case SILC_SFTP_STATUS:
486 char *message = NULL, *language_tag = NULL;
488 SILC_LOG_DEBUG(("Status packet"));
490 ret = silc_buffer_unformat(&buf,
491 SILC_STR_UI_INT(&id),
492 SILC_STR_UI_INT(&status),
497 if (status != SILC_SFTP_STATUS_OK) {
498 silc_buffer_pull(&buf, 8);
499 ret = silc_buffer_unformat(&buf,
500 SILC_STR_UI32_STRING_ALLOC(&message),
501 SILC_STR_UI32_STRING_ALLOC(&language_tag),
506 silc_buffer_push(&buf, 8);
510 req = silc_sftp_find_request(sftp, id);
513 silc_free(language_tag);
517 /* Call the callback */
518 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
521 silc_free(language_tag);
525 case SILC_SFTP_HANDLE:
527 unsigned char *handle = NULL;
528 SilcUInt32 handle_len;
530 SILC_LOG_DEBUG(("Handle packet"));
532 ret = silc_buffer_unformat(&buf,
533 SILC_STR_UI_INT(&id),
534 SILC_STR_UI32_NSTRING(&handle,
541 req = silc_sftp_find_request(sftp, id);
545 /* Call the callback */
546 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
553 unsigned char *data = NULL;
554 SilcUInt32 data_len = 0;
556 SILC_LOG_DEBUG(("Data packet"));
558 ret = silc_buffer_unformat(&buf,
559 SILC_STR_UI_INT(&id),
560 SILC_STR_UI32_NSTRING(&data, &data_len),
566 req = silc_sftp_find_request(sftp, id);
570 /* Call the callback */
571 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
579 SilcSFTPName name = NULL;
581 SILC_LOG_DEBUG(("Name packet"));
583 ret = silc_buffer_unformat(&buf,
584 SILC_STR_UI_INT(&id),
585 SILC_STR_UI_INT(&count),
591 req = silc_sftp_find_request(sftp, id);
595 silc_buffer_pull(&buf, 8);
596 name = silc_sftp_name_decode(count, &buf);
599 silc_buffer_push(&buf, 8);
601 /* Call the callback */
602 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
603 silc_sftp_name_free(name);
607 case SILC_SFTP_ATTRS:
609 SilcSFTPAttributes attr = NULL;
611 SilcBufferStruct tmpbuf;
613 SILC_LOG_DEBUG(("Attributes packet"));
616 silc_buffer_unformat(&buf,
617 SILC_STR_UI_INT(&id),
618 SILC_STR_UI_XNSTRING(&data,
619 silc_buffer_len(&buf) - 4),
625 req = silc_sftp_find_request(sftp, id);
629 silc_buffer_set(&tmpbuf, data, silc_buffer_len(&buf) - 4);
630 attr = silc_sftp_attr_decode(&tmpbuf);
634 /* Call the callback */
635 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
639 case SILC_SFTP_EXTENDED_REPLY:
641 unsigned char *data = NULL;
643 SILC_LOG_DEBUG(("Extended reply packet"));
645 ret = silc_buffer_unformat(&buf,
646 SILC_STR_UI_INT(&id),
647 SILC_STR_UI_XNSTRING(&data, silc_buffer_len(&buf) - 4),
653 req = silc_sftp_find_request(sftp, id);
657 /* Call the callback */
658 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
659 data, silc_buffer_len(&buf) - 4);
668 void silc_sftp_open(SilcSFTP sftp,
669 const char *filename,
670 SilcSFTPFileOperation pflags,
671 SilcSFTPAttributes attrs,
672 SilcSFTPHandleCallback callback,
675 SilcSFTPClient client = (SilcSFTPClient)sftp;
677 SilcBuffer attrs_buf;
680 SILC_LOG_DEBUG(("Open request"));
682 req = silc_calloc(1, sizeof(*req));
685 req->id = client->id++;
686 req->type = SILC_SFTP_OPEN;
687 req->handle = callback;
688 req->context = context;
689 silc_list_add(client->requests, req);
691 attrs_buf = silc_sftp_attr_encode(attrs);
694 len = 4 + 4 + strlen(filename) + 4 + silc_buffer_len(attrs_buf);
696 silc_sftp_send_packet(client, req->type, len,
697 SILC_STR_UI_INT(req->id),
698 SILC_STR_UI_INT(strlen(filename)),
699 SILC_STR_UI32_STRING(filename),
700 SILC_STR_UI_INT(pflags),
701 SILC_STR_UI_XNSTRING(attrs_buf->data,
702 silc_buffer_len(attrs_buf)),
705 silc_buffer_free(attrs_buf);
708 void silc_sftp_close(SilcSFTP sftp,
709 SilcSFTPHandle handle,
710 SilcSFTPStatusCallback callback,
713 SilcSFTPClient client = (SilcSFTPClient)sftp;
716 const unsigned char *hdata;
717 SilcUInt32 hdata_len;
719 SILC_LOG_DEBUG(("Close request"));
721 req = silc_calloc(1, sizeof(*req));
724 req->id = client->id++;
725 req->type = SILC_SFTP_CLOSE;
726 req->status = callback;
727 req->context = context;
728 silc_list_add(client->requests, req);
730 silc_sftp_handle_get(handle, &hdata, &hdata_len);
731 len = 4 + 4 + hdata_len;
733 silc_sftp_send_packet(client, req->type, len,
734 SILC_STR_UI_INT(req->id),
735 SILC_STR_UI_INT(hdata_len),
736 SILC_STR_UI_XNSTRING(hdata, hdata_len),
738 silc_sftp_handle_delete(handle);
741 void silc_sftp_read(SilcSFTP sftp,
742 SilcSFTPHandle handle,
745 SilcSFTPDataCallback callback,
748 SilcSFTPClient client = (SilcSFTPClient)sftp;
751 const unsigned char *hdata;
752 SilcUInt32 hdata_len;
754 SILC_LOG_DEBUG(("Read request"));
756 req = silc_calloc(1, sizeof(*req));
759 req->id = client->id++;
760 req->type = SILC_SFTP_READ;
761 req->data = callback;
762 req->context = context;
763 silc_list_add(client->requests, req);
765 silc_sftp_handle_get(handle, &hdata, &hdata_len);
766 len2 = 4 + 4 + hdata_len + 8 + 4;
768 silc_sftp_send_packet(client, req->type, len2,
769 SILC_STR_UI_INT(req->id),
770 SILC_STR_UI_INT(hdata_len),
771 SILC_STR_UI_XNSTRING(hdata, hdata_len),
772 SILC_STR_UI_INT64(offset),
773 SILC_STR_UI_INT(len),
777 void silc_sftp_write(SilcSFTP sftp,
778 SilcSFTPHandle handle,
780 const unsigned char *data,
782 SilcSFTPStatusCallback callback,
785 SilcSFTPClient client = (SilcSFTPClient)sftp;
788 const unsigned char *hdata;
789 SilcUInt32 hdata_len;
791 SILC_LOG_DEBUG(("Write request"));
793 req = silc_calloc(1, sizeof(*req));
796 req->id = client->id++;
797 req->type = SILC_SFTP_WRITE;
798 req->status = callback;
799 req->context = context;
800 silc_list_add(client->requests, req);
802 silc_sftp_handle_get(handle, &hdata, &hdata_len);
803 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
805 silc_sftp_send_packet(client, req->type, len,
806 SILC_STR_UI_INT(req->id),
807 SILC_STR_UI_INT(hdata_len),
808 SILC_STR_UI_XNSTRING(hdata, hdata_len),
809 SILC_STR_UI_INT64(offset),
810 SILC_STR_UI_INT(data_len),
811 SILC_STR_UI_XNSTRING(data, data_len),
815 void silc_sftp_remove(SilcSFTP sftp,
816 const char *filename,
817 SilcSFTPStatusCallback callback,
820 SilcSFTPClient client = (SilcSFTPClient)sftp;
824 SILC_LOG_DEBUG(("Remove request"));
826 req = silc_calloc(1, sizeof(*req));
829 req->id = client->id++;
830 req->type = SILC_SFTP_REMOVE;
831 req->status = callback;
832 req->context = context;
833 silc_list_add(client->requests, req);
835 len = 4 + 4 + strlen(filename);
837 silc_sftp_send_packet(client, req->type, len,
838 SILC_STR_UI_INT(req->id),
839 SILC_STR_UI_INT(strlen(filename)),
840 SILC_STR_UI32_STRING(filename),
844 void silc_sftp_rename(SilcSFTP sftp,
847 SilcSFTPStatusCallback callback,
850 SilcSFTPClient client = (SilcSFTPClient)sftp;
854 SILC_LOG_DEBUG(("Rename request"));
856 req = silc_calloc(1, sizeof(*req));
859 req->id = client->id++;
860 req->type = SILC_SFTP_RENAME;
861 req->status = callback;
862 req->context = context;
863 silc_list_add(client->requests, req);
865 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
867 silc_sftp_send_packet(client, req->type, len,
868 SILC_STR_UI_INT(req->id),
869 SILC_STR_UI_INT(strlen(oldname)),
870 SILC_STR_UI32_STRING(oldname),
871 SILC_STR_UI_INT(strlen(newname)),
872 SILC_STR_UI32_STRING(newname),
876 void silc_sftp_mkdir(SilcSFTP sftp,
878 SilcSFTPAttributes attrs,
879 SilcSFTPStatusCallback callback,
882 SilcSFTPClient client = (SilcSFTPClient)sftp;
885 SilcBuffer attrs_buf;
887 SILC_LOG_DEBUG(("Mkdir request"));
889 req = silc_calloc(1, sizeof(*req));
892 req->id = client->id++;
893 req->type = SILC_SFTP_MKDIR;
894 req->status = callback;
895 req->context = context;
896 silc_list_add(client->requests, req);
898 attrs_buf = silc_sftp_attr_encode(attrs);
901 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
903 silc_sftp_send_packet(client, req->type, len,
904 SILC_STR_UI_INT(req->id),
905 SILC_STR_UI_INT(strlen(path)),
906 SILC_STR_UI32_STRING(path),
907 SILC_STR_UI_XNSTRING(attrs_buf->data,
908 silc_buffer_len(attrs_buf)),
911 silc_buffer_free(attrs_buf);
914 void silc_sftp_rmdir(SilcSFTP sftp,
916 SilcSFTPStatusCallback callback,
919 SilcSFTPClient client = (SilcSFTPClient)sftp;
923 SILC_LOG_DEBUG(("Rmdir request"));
925 req = silc_calloc(1, sizeof(*req));
928 req->id = client->id++;
929 req->type = SILC_SFTP_RMDIR;
930 req->status = callback;
931 req->context = context;
932 silc_list_add(client->requests, req);
934 len = 4 + 4 + strlen(path);
936 silc_sftp_send_packet(client, req->type, len,
937 SILC_STR_UI_INT(req->id),
938 SILC_STR_UI_INT(strlen(path)),
939 SILC_STR_UI32_STRING(path),
943 void silc_sftp_opendir(SilcSFTP sftp,
945 SilcSFTPHandleCallback callback,
948 SilcSFTPClient client = (SilcSFTPClient)sftp;
952 SILC_LOG_DEBUG(("Opendir request"));
954 req = silc_calloc(1, sizeof(*req));
957 req->id = client->id++;
958 req->type = SILC_SFTP_OPENDIR;
959 req->handle = callback;
960 req->context = context;
961 silc_list_add(client->requests, req);
963 len = 4 + 4 + strlen(path);
965 silc_sftp_send_packet(client, req->type, len,
966 SILC_STR_UI_INT(req->id),
967 SILC_STR_UI_INT(strlen(path)),
968 SILC_STR_UI32_STRING(path),
972 void silc_sftp_readdir(SilcSFTP sftp,
973 SilcSFTPHandle handle,
974 SilcSFTPNameCallback callback,
977 SilcSFTPClient client = (SilcSFTPClient)sftp;
980 const unsigned char *hdata;
981 SilcUInt32 hdata_len;
983 SILC_LOG_DEBUG(("Readdir request"));
985 req = silc_calloc(1, sizeof(*req));
988 req->id = client->id++;
989 req->type = SILC_SFTP_READDIR;
990 req->name = callback;
991 req->context = context;
992 silc_list_add(client->requests, req);
994 silc_sftp_handle_get(handle, &hdata, &hdata_len);
995 len = 4 + 4 + hdata_len;
997 silc_sftp_send_packet(client, req->type, len,
998 SILC_STR_UI_INT(req->id),
999 SILC_STR_UI_INT(hdata_len),
1000 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1004 void silc_sftp_stat(SilcSFTP sftp,
1006 SilcSFTPAttrCallback callback,
1009 SilcSFTPClient client = (SilcSFTPClient)sftp;
1010 SilcSFTPRequest req;
1013 SILC_LOG_DEBUG(("Stat request"));
1015 req = silc_calloc(1, sizeof(*req));
1018 req->id = client->id++;
1019 req->type = SILC_SFTP_STAT;
1020 req->attr = callback;
1021 req->context = context;
1022 silc_list_add(client->requests, req);
1024 len = 4 + 4 + strlen(path);
1026 silc_sftp_send_packet(client, req->type, len,
1027 SILC_STR_UI_INT(req->id),
1028 SILC_STR_UI_INT(strlen(path)),
1029 SILC_STR_UI32_STRING(path),
1033 void silc_sftp_lstat(SilcSFTP sftp,
1035 SilcSFTPAttrCallback callback,
1038 SilcSFTPClient client = (SilcSFTPClient)sftp;
1039 SilcSFTPRequest req;
1042 SILC_LOG_DEBUG(("Lstat request"));
1044 req = silc_calloc(1, sizeof(*req));
1047 req->id = client->id++;
1048 req->type = SILC_SFTP_LSTAT;
1049 req->attr = callback;
1050 req->context = context;
1051 silc_list_add(client->requests, req);
1053 len = 4 + 4 + strlen(path);
1055 silc_sftp_send_packet(client, req->type, len,
1056 SILC_STR_UI_INT(req->id),
1057 SILC_STR_UI_INT(strlen(path)),
1058 SILC_STR_UI32_STRING(path),
1062 void silc_sftp_fstat(SilcSFTP sftp,
1063 SilcSFTPHandle handle,
1064 SilcSFTPAttrCallback callback,
1067 SilcSFTPClient client = (SilcSFTPClient)sftp;
1068 SilcSFTPRequest req;
1070 const unsigned char *hdata;
1071 SilcUInt32 hdata_len;
1073 SILC_LOG_DEBUG(("Fstat request"));
1075 req = silc_calloc(1, sizeof(*req));
1078 req->id = client->id++;
1079 req->type = SILC_SFTP_FSTAT;
1080 req->attr = callback;
1081 req->context = context;
1082 silc_list_add(client->requests, req);
1084 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1085 len = 4 + 4 + hdata_len;
1087 silc_sftp_send_packet(client, req->type, len,
1088 SILC_STR_UI_INT(req->id),
1089 SILC_STR_UI_INT(hdata_len),
1090 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1094 void silc_sftp_setstat(SilcSFTP sftp,
1096 SilcSFTPAttributes attrs,
1097 SilcSFTPStatusCallback callback,
1100 SilcSFTPClient client = (SilcSFTPClient)sftp;
1101 SilcSFTPRequest req;
1103 SilcBuffer attrs_buf;
1105 SILC_LOG_DEBUG(("Setstat request"));
1107 req = silc_calloc(1, sizeof(*req));
1110 req->id = client->id++;
1111 req->type = SILC_SFTP_SETSTAT;
1112 req->status = callback;
1113 req->context = context;
1114 silc_list_add(client->requests, req);
1116 attrs_buf = silc_sftp_attr_encode(attrs);
1119 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
1121 silc_sftp_send_packet(client, req->type, len,
1122 SILC_STR_UI_INT(req->id),
1123 SILC_STR_UI_INT(strlen(path)),
1124 SILC_STR_UI32_STRING(path),
1125 SILC_STR_UI_XNSTRING(attrs_buf->data,
1126 silc_buffer_len(attrs_buf)),
1129 silc_buffer_free(attrs_buf);
1132 void silc_sftp_fsetstat(SilcSFTP sftp,
1133 SilcSFTPHandle handle,
1134 SilcSFTPAttributes attrs,
1135 SilcSFTPStatusCallback callback,
1138 SilcSFTPClient client = (SilcSFTPClient)sftp;
1139 SilcSFTPRequest req;
1141 SilcBuffer attrs_buf;
1142 const unsigned char *hdata;
1143 SilcUInt32 hdata_len;
1145 SILC_LOG_DEBUG(("Fsetstat request"));
1147 req = silc_calloc(1, sizeof(*req));
1150 req->id = client->id++;
1151 req->type = SILC_SFTP_FSETSTAT;
1152 req->status = callback;
1153 req->context = context;
1154 silc_list_add(client->requests, req);
1156 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1157 attrs_buf = silc_sftp_attr_encode(attrs);
1160 len = 4 + 4 + hdata_len + silc_buffer_len(attrs_buf);
1162 silc_sftp_send_packet(client, req->type, len,
1163 SILC_STR_UI_INT(req->id),
1164 SILC_STR_UI_INT(hdata_len),
1165 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1166 SILC_STR_UI_XNSTRING(attrs_buf->data,
1167 silc_buffer_len(attrs_buf)),
1170 silc_buffer_free(attrs_buf);
1173 void silc_sftp_readlink(SilcSFTP sftp,
1175 SilcSFTPNameCallback callback,
1178 SilcSFTPClient client = (SilcSFTPClient)sftp;
1179 SilcSFTPRequest req;
1182 SILC_LOG_DEBUG(("Readlink request"));
1184 req = silc_calloc(1, sizeof(*req));
1187 req->id = client->id++;
1188 req->type = SILC_SFTP_READLINK;
1189 req->name = callback;
1190 req->context = context;
1191 silc_list_add(client->requests, req);
1193 len = 4 + 4 + strlen(path);
1195 silc_sftp_send_packet(client, req->type, len,
1196 SILC_STR_UI_INT(req->id),
1197 SILC_STR_UI_INT(strlen(path)),
1198 SILC_STR_UI32_STRING(path),
1202 void silc_sftp_symlink(SilcSFTP sftp,
1203 const char *linkpath,
1204 const char *targetpath,
1205 SilcSFTPStatusCallback callback,
1208 SilcSFTPClient client = (SilcSFTPClient)sftp;
1209 SilcSFTPRequest req;
1212 SILC_LOG_DEBUG(("Symlink request"));
1214 req = silc_calloc(1, sizeof(*req));
1217 req->id = client->id++;
1218 req->type = SILC_SFTP_SYMLINK;
1219 req->status = callback;
1220 req->context = context;
1221 silc_list_add(client->requests, req);
1223 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1225 silc_sftp_send_packet(client, req->type, len,
1226 SILC_STR_UI_INT(req->id),
1227 SILC_STR_UI_INT(strlen(linkpath)),
1228 SILC_STR_UI32_STRING(linkpath),
1229 SILC_STR_UI_INT(strlen(targetpath)),
1230 SILC_STR_UI32_STRING(targetpath),
1234 void silc_sftp_realpath(SilcSFTP sftp,
1236 SilcSFTPNameCallback callback,
1239 SilcSFTPClient client = (SilcSFTPClient)sftp;
1240 SilcSFTPRequest req;
1243 SILC_LOG_DEBUG(("Realpath request"));
1245 req = silc_calloc(1, sizeof(*req));
1248 req->id = client->id++;
1249 req->type = SILC_SFTP_REALPATH;
1250 req->name = callback;
1251 req->context = context;
1252 silc_list_add(client->requests, req);
1254 len = 4 + 4 + strlen(path);
1256 silc_sftp_send_packet(client, req->type, len,
1257 SILC_STR_UI_INT(req->id),
1258 SILC_STR_UI_INT(strlen(path)),
1259 SILC_STR_UI32_STRING(path),
1263 void silc_sftp_extended(SilcSFTP sftp,
1264 const char *request,
1265 const unsigned char *data,
1266 SilcUInt32 data_len,
1267 SilcSFTPExtendedCallback callback,
1270 SilcSFTPClient client = (SilcSFTPClient)sftp;
1271 SilcSFTPRequest req;
1274 SILC_LOG_DEBUG(("Extended request"));
1276 req = silc_calloc(1, sizeof(*req));
1279 req->id = client->id++;
1280 req->type = SILC_SFTP_WRITE;
1281 req->extended = callback;
1282 req->context = context;
1283 silc_list_add(client->requests, req);
1285 len = 4 + 4 + strlen(request) + data_len;
1287 silc_sftp_send_packet(client, req->type, len,
1288 SILC_STR_UI_INT(req->id),
1289 SILC_STR_UI_INT(strlen(request)),
1290 SILC_STR_UI32_STRING(request),
1291 SILC_STR_UI_XNSTRING(data, data_len),