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 "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 {
28 struct SilcSFTPRequestStruct *next;
29 SilcSFTPStatusCallback status;
30 SilcSFTPHandleCallback handle;
31 SilcSFTPDataCallback data;
32 SilcSFTPNameCallback name;
33 SilcSFTPAttrCallback attr;
34 SilcSFTPExtendedCallback extended;
40 /* SFTP client context */
43 SilcSFTPVersionCallback version;
44 SilcSFTPErrorCallback error;
52 struct SilcSFTPHandleStruct {
57 static void silc_sftp_client_receive_process(SilcSFTP context,
60 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
63 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
66 SilcSFTPHandle handle;
68 handle = silc_calloc(1, sizeof(*handle));
71 handle->data = silc_calloc(data_len, sizeof(*handle->data));
74 memcpy(handle->data, data, data_len);
75 handle->data_len = data_len;
80 /* Deletes the handle indicated by the `handle'. */
82 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
84 silc_free(handle->data);
88 /* Returns the handle data of the `handle' to the `data' pointer. */
90 static void silc_sftp_handle_get(SilcSFTPHandle handle,
91 const unsigned char **data,
94 *data = (const unsigned char *)handle->data;
95 *data_len = handle->data_len;
98 /* Generic routine to send SFTP packet to the SFTP server. */
100 static void silc_sftp_send_packet(SilcSFTPClient sftp,
109 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
115 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
116 silc_buffer_len(sftp->packet));
118 /* Send the packet */
119 while (silc_buffer_len(sftp->packet) > 0) {
120 ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
121 silc_buffer_len(sftp->packet));
123 SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
128 silc_buffer_pull(sftp->packet, ret);
132 silc_buffer_reset(sftp->packet);
135 /* Finds request by request ID. */
137 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp,
142 SILC_LOG_DEBUG(("Finding request ID: %d", id));
144 silc_list_start(sftp->requests);
145 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
150 SILC_LOG_DEBUG(("Unknown request ID %d", id));
155 /* Function used to call the request callback indicated by the `req'. The
156 `status' will be sent to the callback function as the status of the
157 operation. The variable argument list includes the status and req->type
160 static void silc_sftp_call_request(SilcSFTPClient sftp,
163 SilcSFTPStatus status, ...)
167 SILC_LOG_DEBUG(("Start"));
169 va_start(vp, status);
178 if (status != SILC_SFTP_STATUS_OK) {
180 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
184 data = (unsigned char *)va_arg(vp, unsigned char *);
185 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
188 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
189 data_len, req->context);
194 case SILC_SFTP_OPENDIR:
196 /* Handle returned */
197 SilcSFTPHandle handle;
198 unsigned char *hdata;
199 SilcUInt32 hdata_len;
201 if (status != SILC_SFTP_STATUS_OK) {
203 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
207 hdata = (unsigned char *)va_arg(vp, unsigned char *);
208 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
209 handle = silc_sftp_handle_create(hdata, hdata_len);
212 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
217 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
221 case SILC_SFTP_CLOSE:
222 case SILC_SFTP_WRITE:
223 case SILC_SFTP_REMOVE:
224 case SILC_SFTP_RENAME:
225 case SILC_SFTP_MKDIR:
226 case SILC_SFTP_RMDIR:
227 case SILC_SFTP_SETSTAT:
228 case SILC_SFTP_FSETSTAT:
229 case SILC_SFTP_SYMLINK:
231 /* Status returned */
232 char *message, *language_tag;
234 message = (char *)va_arg(vp, char *);
235 language_tag = (char *)va_arg(vp, char *);
238 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
239 (const char *)language_tag, req->context);
244 case SILC_SFTP_LSTAT:
245 case SILC_SFTP_FSTAT:
247 /* Attributes returned */
248 SilcSFTPAttributes attr;
250 if (status != SILC_SFTP_STATUS_OK) {
252 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
256 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
259 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
264 case SILC_SFTP_READDIR:
265 case SILC_SFTP_REALPATH:
266 case SILC_SFTP_READLINK:
268 /* Name(s) returned */
271 if (status != SILC_SFTP_STATUS_OK) {
273 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
277 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
280 (*req->name)((SilcSFTP)sftp, status, name, req->context);
284 case SILC_SFTP_EXTENDED:
286 /* Extended reply returned */
290 if (status != SILC_SFTP_STATUS_OK) {
292 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
296 data = (unsigned char *)va_arg(vp, unsigned char *);
297 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
300 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
301 data_len, req->context);
309 /* Remove this request */
310 silc_list_del(sftp->requests, req);
316 /* Handles stream I/O */
318 static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status,
321 SilcSFTPClient sftp = context;
322 unsigned char inbuf[30720];
323 SilcBufferStruct packet;
327 case SILC_STREAM_CAN_READ:
328 SILC_LOG_DEBUG(("Reading data from stream"));
330 /* Read data from stream */
331 ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
334 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
336 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
340 /* Now process the SFTP packet */
341 silc_buffer_set(&packet, inbuf, ret);
342 silc_sftp_client_receive_process(context, &packet);
345 case SILC_STREAM_CAN_WRITE:
346 if (!silc_buffer_headlen(sftp->packet))
349 SILC_LOG_DEBUG(("Writing pending data to stream"));
351 /* Write pending data to stream */
352 silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
353 while (silc_buffer_len(sftp->packet) > 0) {
354 ret = silc_stream_write(stream, sftp->packet->data,
355 silc_buffer_len(sftp->packet));
357 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
358 silc_buffer_reset(sftp->packet);
363 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
364 silc_buffer_reset(sftp->packet);
372 silc_buffer_pull(sftp->packet, ret);
381 /* Starts SFTP client and returns context for it. */
383 SilcSFTP silc_sftp_client_start(SilcStream stream,
384 SilcSchedule schedule,
385 SilcSFTPVersionCallback version_cb,
386 SilcSFTPErrorCallback error_cb,
391 SILC_LOG_DEBUG(("Starting SFTP client"));
396 sftp = silc_calloc(1, sizeof(*sftp));
399 sftp->stream = stream;
400 sftp->version = version_cb;
401 sftp->error = error_cb;
402 sftp->context = context;
403 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
405 /* We handle the stream now */
406 silc_stream_set_notifier(stream, schedule, silc_sftp_client_io, sftp);
408 /* Send the SFTP session initialization to the server */
409 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
410 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
413 return (SilcSFTP)sftp;
416 /* Shutdown's the SFTP client. The caller is responsible of closing
417 the associated socket connection. The SFTP context is freed and is
418 invalid after this function returns. */
420 void silc_sftp_client_shutdown(SilcSFTP context)
422 SilcSFTPClient sftp = (SilcSFTPClient)context;
424 silc_stream_set_notifier(sftp->stream, NULL, NULL, NULL);
426 silc_buffer_free(sftp->packet);
430 /* Function that is called to process the incmoing SFTP packet. */
432 void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer)
434 SilcSFTPClient sftp = (SilcSFTPClient)context;
437 const unsigned char *payload = NULL;
438 SilcUInt32 payload_len;
440 SilcBufferStruct buf;
443 SILC_LOG_DEBUG(("Process SFTP packet"));
445 /* Parse the packet */
446 type = silc_sftp_packet_decode(buffer, (unsigned char **)&payload,
451 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
456 unsigned char *data = NULL;
457 SilcUInt32 data_len = 0;
459 SILC_LOG_DEBUG(("Data packet"));
461 ret = silc_buffer_unformat(&buf,
462 SILC_STR_UI_INT(&id),
463 SILC_STR_UI32_NSTRING(&data, &data_len),
469 req = silc_sftp_find_request(sftp, id);
473 /* Call the callback */
474 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
479 case SILC_SFTP_VERSION:
481 SilcSFTPVersion version;
483 SILC_LOG_DEBUG(("Version packet"));
485 ret = silc_buffer_unformat(&buf,
486 SILC_STR_UI_INT(&version),
489 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
494 /* Call the callback */
495 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
500 case SILC_SFTP_STATUS:
503 char *message = NULL, *language_tag = NULL;
505 SILC_LOG_DEBUG(("Status packet"));
507 ret = silc_buffer_unformat(&buf,
508 SILC_STR_UI_INT(&id),
509 SILC_STR_UI_INT(&status),
514 if (status != SILC_SFTP_STATUS_OK) {
515 silc_buffer_pull(&buf, 8);
516 ret = silc_buffer_unformat(&buf,
517 SILC_STR_UI32_STRING_ALLOC(&message),
518 SILC_STR_UI32_STRING_ALLOC(&language_tag),
523 silc_buffer_push(&buf, 8);
527 req = silc_sftp_find_request(sftp, id);
530 silc_free(language_tag);
534 /* Call the callback */
535 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
538 silc_free(language_tag);
542 case SILC_SFTP_HANDLE:
544 unsigned char *handle = NULL;
545 SilcUInt32 handle_len;
547 SILC_LOG_DEBUG(("Handle packet"));
549 ret = silc_buffer_unformat(&buf,
550 SILC_STR_UI_INT(&id),
551 SILC_STR_UI32_NSTRING(&handle,
558 req = silc_sftp_find_request(sftp, id);
562 /* Call the callback */
563 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
571 SilcSFTPName name = NULL;
573 SILC_LOG_DEBUG(("Name packet"));
575 ret = silc_buffer_unformat(&buf,
576 SILC_STR_UI_INT(&id),
577 SILC_STR_UI_INT(&count),
583 req = silc_sftp_find_request(sftp, id);
587 silc_buffer_pull(&buf, 8);
588 name = silc_sftp_name_decode(count, &buf);
591 silc_buffer_push(&buf, 8);
593 /* Call the callback */
594 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
595 silc_sftp_name_free(name);
599 case SILC_SFTP_ATTRS:
601 SilcSFTPAttributes attr = NULL;
603 SilcBufferStruct tmpbuf;
605 SILC_LOG_DEBUG(("Attributes packet"));
608 silc_buffer_unformat(&buf,
609 SILC_STR_UI_INT(&id),
610 SILC_STR_UI_XNSTRING(&data,
611 silc_buffer_len(&buf) - 4),
617 req = silc_sftp_find_request(sftp, id);
621 silc_buffer_set(&tmpbuf, data, silc_buffer_len(&buf) - 4);
622 attr = silc_sftp_attr_decode(&tmpbuf);
626 /* Call the callback */
627 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
631 case SILC_SFTP_EXTENDED_REPLY:
633 unsigned char *data = NULL;
635 SILC_LOG_DEBUG(("Extended reply packet"));
637 ret = silc_buffer_unformat(&buf,
638 SILC_STR_UI_INT(&id),
639 SILC_STR_UI_XNSTRING(&data, silc_buffer_len(&buf) - 4),
645 req = silc_sftp_find_request(sftp, id);
649 /* Call the callback */
650 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
651 data, silc_buffer_len(&buf) - 4);
660 void silc_sftp_open(SilcSFTP sftp,
661 const char *filename,
662 SilcSFTPFileOperation pflags,
663 SilcSFTPAttributes attrs,
664 SilcSFTPHandleCallback callback,
667 SilcSFTPClient client = (SilcSFTPClient)sftp;
669 SilcBuffer attrs_buf;
672 SILC_LOG_DEBUG(("Open request"));
674 req = silc_calloc(1, sizeof(*req));
677 req->id = client->id++;
678 req->type = SILC_SFTP_OPEN;
679 req->handle = callback;
680 req->context = context;
681 silc_list_add(client->requests, req);
683 attrs_buf = silc_sftp_attr_encode(attrs);
686 len = 4 + 4 + strlen(filename) + 4 + silc_buffer_len(attrs_buf);
688 silc_sftp_send_packet(client, req->type, len,
689 SILC_STR_UI_INT(req->id),
690 SILC_STR_UI_INT(strlen(filename)),
691 SILC_STR_UI32_STRING(filename),
692 SILC_STR_UI_INT(pflags),
693 SILC_STR_UI_XNSTRING(attrs_buf->data,
694 silc_buffer_len(attrs_buf)),
697 silc_buffer_free(attrs_buf);
700 void silc_sftp_close(SilcSFTP sftp,
701 SilcSFTPHandle handle,
702 SilcSFTPStatusCallback callback,
705 SilcSFTPClient client = (SilcSFTPClient)sftp;
708 const unsigned char *hdata;
709 SilcUInt32 hdata_len;
711 SILC_LOG_DEBUG(("Close request"));
713 req = silc_calloc(1, sizeof(*req));
716 req->id = client->id++;
717 req->type = SILC_SFTP_CLOSE;
718 req->status = callback;
719 req->context = context;
720 silc_list_add(client->requests, req);
722 silc_sftp_handle_get(handle, &hdata, &hdata_len);
723 len = 4 + 4 + hdata_len;
725 silc_sftp_send_packet(client, req->type, len,
726 SILC_STR_UI_INT(req->id),
727 SILC_STR_UI_INT(hdata_len),
728 SILC_STR_UI_XNSTRING(hdata, hdata_len),
730 silc_sftp_handle_delete(handle);
733 void silc_sftp_read(SilcSFTP sftp,
734 SilcSFTPHandle handle,
737 SilcSFTPDataCallback callback,
740 SilcSFTPClient client = (SilcSFTPClient)sftp;
743 const unsigned char *hdata;
744 SilcUInt32 hdata_len;
746 SILC_LOG_DEBUG(("Read request"));
748 req = silc_calloc(1, sizeof(*req));
751 req->id = client->id++;
752 req->type = SILC_SFTP_READ;
753 req->data = callback;
754 req->context = context;
755 silc_list_add(client->requests, req);
757 silc_sftp_handle_get(handle, &hdata, &hdata_len);
758 len2 = 4 + 4 + hdata_len + 8 + 4;
760 silc_sftp_send_packet(client, req->type, len2,
761 SILC_STR_UI_INT(req->id),
762 SILC_STR_UI_INT(hdata_len),
763 SILC_STR_UI_XNSTRING(hdata, hdata_len),
764 SILC_STR_UI_INT64(offset),
765 SILC_STR_UI_INT(len),
769 void silc_sftp_write(SilcSFTP sftp,
770 SilcSFTPHandle handle,
772 const unsigned char *data,
774 SilcSFTPStatusCallback callback,
777 SilcSFTPClient client = (SilcSFTPClient)sftp;
780 const unsigned char *hdata;
781 SilcUInt32 hdata_len;
783 SILC_LOG_DEBUG(("Write request"));
785 req = silc_calloc(1, sizeof(*req));
788 req->id = client->id++;
789 req->type = SILC_SFTP_WRITE;
790 req->status = callback;
791 req->context = context;
792 silc_list_add(client->requests, req);
794 silc_sftp_handle_get(handle, &hdata, &hdata_len);
795 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
797 silc_sftp_send_packet(client, req->type, len,
798 SILC_STR_UI_INT(req->id),
799 SILC_STR_UI_INT(hdata_len),
800 SILC_STR_UI_XNSTRING(hdata, hdata_len),
801 SILC_STR_UI_INT64(offset),
802 SILC_STR_UI_INT(data_len),
803 SILC_STR_UI_XNSTRING(data, data_len),
807 void silc_sftp_remove(SilcSFTP sftp,
808 const char *filename,
809 SilcSFTPStatusCallback callback,
812 SilcSFTPClient client = (SilcSFTPClient)sftp;
816 SILC_LOG_DEBUG(("Remove request"));
818 req = silc_calloc(1, sizeof(*req));
821 req->id = client->id++;
822 req->type = SILC_SFTP_REMOVE;
823 req->status = callback;
824 req->context = context;
825 silc_list_add(client->requests, req);
827 len = 4 + 4 + strlen(filename);
829 silc_sftp_send_packet(client, req->type, len,
830 SILC_STR_UI_INT(req->id),
831 SILC_STR_UI_INT(strlen(filename)),
832 SILC_STR_UI32_STRING(filename),
836 void silc_sftp_rename(SilcSFTP sftp,
839 SilcSFTPStatusCallback callback,
842 SilcSFTPClient client = (SilcSFTPClient)sftp;
846 SILC_LOG_DEBUG(("Rename request"));
848 req = silc_calloc(1, sizeof(*req));
851 req->id = client->id++;
852 req->type = SILC_SFTP_RENAME;
853 req->status = callback;
854 req->context = context;
855 silc_list_add(client->requests, req);
857 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
859 silc_sftp_send_packet(client, req->type, len,
860 SILC_STR_UI_INT(req->id),
861 SILC_STR_UI_INT(strlen(oldname)),
862 SILC_STR_UI32_STRING(oldname),
863 SILC_STR_UI_INT(strlen(newname)),
864 SILC_STR_UI32_STRING(newname),
868 void silc_sftp_mkdir(SilcSFTP sftp,
870 SilcSFTPAttributes attrs,
871 SilcSFTPStatusCallback callback,
874 SilcSFTPClient client = (SilcSFTPClient)sftp;
877 SilcBuffer attrs_buf;
879 SILC_LOG_DEBUG(("Mkdir request"));
881 req = silc_calloc(1, sizeof(*req));
884 req->id = client->id++;
885 req->type = SILC_SFTP_MKDIR;
886 req->status = callback;
887 req->context = context;
888 silc_list_add(client->requests, req);
890 attrs_buf = silc_sftp_attr_encode(attrs);
893 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
895 silc_sftp_send_packet(client, req->type, len,
896 SILC_STR_UI_INT(req->id),
897 SILC_STR_UI_INT(strlen(path)),
898 SILC_STR_UI32_STRING(path),
899 SILC_STR_UI_XNSTRING(attrs_buf->data,
900 silc_buffer_len(attrs_buf)),
903 silc_buffer_free(attrs_buf);
906 void silc_sftp_rmdir(SilcSFTP sftp,
908 SilcSFTPStatusCallback callback,
911 SilcSFTPClient client = (SilcSFTPClient)sftp;
915 SILC_LOG_DEBUG(("Rmdir request"));
917 req = silc_calloc(1, sizeof(*req));
920 req->id = client->id++;
921 req->type = SILC_SFTP_RMDIR;
922 req->status = callback;
923 req->context = context;
924 silc_list_add(client->requests, req);
926 len = 4 + 4 + strlen(path);
928 silc_sftp_send_packet(client, req->type, len,
929 SILC_STR_UI_INT(req->id),
930 SILC_STR_UI_INT(strlen(path)),
931 SILC_STR_UI32_STRING(path),
935 void silc_sftp_opendir(SilcSFTP sftp,
937 SilcSFTPHandleCallback callback,
940 SilcSFTPClient client = (SilcSFTPClient)sftp;
944 SILC_LOG_DEBUG(("Opendir request"));
946 req = silc_calloc(1, sizeof(*req));
949 req->id = client->id++;
950 req->type = SILC_SFTP_OPENDIR;
951 req->handle = callback;
952 req->context = context;
953 silc_list_add(client->requests, req);
955 len = 4 + 4 + strlen(path);
957 silc_sftp_send_packet(client, req->type, len,
958 SILC_STR_UI_INT(req->id),
959 SILC_STR_UI_INT(strlen(path)),
960 SILC_STR_UI32_STRING(path),
964 void silc_sftp_readdir(SilcSFTP sftp,
965 SilcSFTPHandle handle,
966 SilcSFTPNameCallback callback,
969 SilcSFTPClient client = (SilcSFTPClient)sftp;
972 const unsigned char *hdata;
973 SilcUInt32 hdata_len;
975 SILC_LOG_DEBUG(("Readdir request"));
977 req = silc_calloc(1, sizeof(*req));
980 req->id = client->id++;
981 req->type = SILC_SFTP_READDIR;
982 req->name = callback;
983 req->context = context;
984 silc_list_add(client->requests, req);
986 silc_sftp_handle_get(handle, &hdata, &hdata_len);
987 len = 4 + 4 + hdata_len;
989 silc_sftp_send_packet(client, req->type, len,
990 SILC_STR_UI_INT(req->id),
991 SILC_STR_UI_INT(hdata_len),
992 SILC_STR_UI_XNSTRING(hdata, hdata_len),
996 void silc_sftp_stat(SilcSFTP sftp,
998 SilcSFTPAttrCallback callback,
1001 SilcSFTPClient client = (SilcSFTPClient)sftp;
1002 SilcSFTPRequest req;
1005 SILC_LOG_DEBUG(("Stat request"));
1007 req = silc_calloc(1, sizeof(*req));
1010 req->id = client->id++;
1011 req->type = SILC_SFTP_STAT;
1012 req->attr = callback;
1013 req->context = context;
1014 silc_list_add(client->requests, req);
1016 len = 4 + 4 + strlen(path);
1018 silc_sftp_send_packet(client, req->type, len,
1019 SILC_STR_UI_INT(req->id),
1020 SILC_STR_UI_INT(strlen(path)),
1021 SILC_STR_UI32_STRING(path),
1025 void silc_sftp_lstat(SilcSFTP sftp,
1027 SilcSFTPAttrCallback callback,
1030 SilcSFTPClient client = (SilcSFTPClient)sftp;
1031 SilcSFTPRequest req;
1034 SILC_LOG_DEBUG(("Lstat request"));
1036 req = silc_calloc(1, sizeof(*req));
1039 req->id = client->id++;
1040 req->type = SILC_SFTP_LSTAT;
1041 req->attr = callback;
1042 req->context = context;
1043 silc_list_add(client->requests, req);
1045 len = 4 + 4 + strlen(path);
1047 silc_sftp_send_packet(client, req->type, len,
1048 SILC_STR_UI_INT(req->id),
1049 SILC_STR_UI_INT(strlen(path)),
1050 SILC_STR_UI32_STRING(path),
1054 void silc_sftp_fstat(SilcSFTP sftp,
1055 SilcSFTPHandle handle,
1056 SilcSFTPAttrCallback callback,
1059 SilcSFTPClient client = (SilcSFTPClient)sftp;
1060 SilcSFTPRequest req;
1062 const unsigned char *hdata;
1063 SilcUInt32 hdata_len;
1065 SILC_LOG_DEBUG(("Fstat request"));
1067 req = silc_calloc(1, sizeof(*req));
1070 req->id = client->id++;
1071 req->type = SILC_SFTP_FSTAT;
1072 req->attr = callback;
1073 req->context = context;
1074 silc_list_add(client->requests, req);
1076 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1077 len = 4 + 4 + hdata_len;
1079 silc_sftp_send_packet(client, req->type, len,
1080 SILC_STR_UI_INT(req->id),
1081 SILC_STR_UI_INT(hdata_len),
1082 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1086 void silc_sftp_setstat(SilcSFTP sftp,
1088 SilcSFTPAttributes attrs,
1089 SilcSFTPStatusCallback callback,
1092 SilcSFTPClient client = (SilcSFTPClient)sftp;
1093 SilcSFTPRequest req;
1095 SilcBuffer attrs_buf;
1097 SILC_LOG_DEBUG(("Setstat request"));
1099 req = silc_calloc(1, sizeof(*req));
1102 req->id = client->id++;
1103 req->type = SILC_SFTP_SETSTAT;
1104 req->status = callback;
1105 req->context = context;
1106 silc_list_add(client->requests, req);
1108 attrs_buf = silc_sftp_attr_encode(attrs);
1111 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
1113 silc_sftp_send_packet(client, req->type, len,
1114 SILC_STR_UI_INT(req->id),
1115 SILC_STR_UI_INT(strlen(path)),
1116 SILC_STR_UI32_STRING(path),
1117 SILC_STR_UI_XNSTRING(attrs_buf->data,
1118 silc_buffer_len(attrs_buf)),
1121 silc_buffer_free(attrs_buf);
1124 void silc_sftp_fsetstat(SilcSFTP sftp,
1125 SilcSFTPHandle handle,
1126 SilcSFTPAttributes attrs,
1127 SilcSFTPStatusCallback callback,
1130 SilcSFTPClient client = (SilcSFTPClient)sftp;
1131 SilcSFTPRequest req;
1133 SilcBuffer attrs_buf;
1134 const unsigned char *hdata;
1135 SilcUInt32 hdata_len;
1137 SILC_LOG_DEBUG(("Fsetstat request"));
1139 req = silc_calloc(1, sizeof(*req));
1142 req->id = client->id++;
1143 req->type = SILC_SFTP_FSETSTAT;
1144 req->status = callback;
1145 req->context = context;
1146 silc_list_add(client->requests, req);
1148 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1149 attrs_buf = silc_sftp_attr_encode(attrs);
1152 len = 4 + 4 + hdata_len + silc_buffer_len(attrs_buf);
1154 silc_sftp_send_packet(client, req->type, len,
1155 SILC_STR_UI_INT(req->id),
1156 SILC_STR_UI_INT(hdata_len),
1157 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1158 SILC_STR_UI_XNSTRING(attrs_buf->data,
1159 silc_buffer_len(attrs_buf)),
1162 silc_buffer_free(attrs_buf);
1165 void silc_sftp_readlink(SilcSFTP sftp,
1167 SilcSFTPNameCallback callback,
1170 SilcSFTPClient client = (SilcSFTPClient)sftp;
1171 SilcSFTPRequest req;
1174 SILC_LOG_DEBUG(("Readlink request"));
1176 req = silc_calloc(1, sizeof(*req));
1179 req->id = client->id++;
1180 req->type = SILC_SFTP_READLINK;
1181 req->name = callback;
1182 req->context = context;
1183 silc_list_add(client->requests, req);
1185 len = 4 + 4 + strlen(path);
1187 silc_sftp_send_packet(client, req->type, len,
1188 SILC_STR_UI_INT(req->id),
1189 SILC_STR_UI_INT(strlen(path)),
1190 SILC_STR_UI32_STRING(path),
1194 void silc_sftp_symlink(SilcSFTP sftp,
1195 const char *linkpath,
1196 const char *targetpath,
1197 SilcSFTPStatusCallback callback,
1200 SilcSFTPClient client = (SilcSFTPClient)sftp;
1201 SilcSFTPRequest req;
1204 SILC_LOG_DEBUG(("Symlink request"));
1206 req = silc_calloc(1, sizeof(*req));
1209 req->id = client->id++;
1210 req->type = SILC_SFTP_SYMLINK;
1211 req->status = callback;
1212 req->context = context;
1213 silc_list_add(client->requests, req);
1215 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1217 silc_sftp_send_packet(client, req->type, len,
1218 SILC_STR_UI_INT(req->id),
1219 SILC_STR_UI_INT(strlen(linkpath)),
1220 SILC_STR_UI32_STRING(linkpath),
1221 SILC_STR_UI_INT(strlen(targetpath)),
1222 SILC_STR_UI32_STRING(targetpath),
1226 void silc_sftp_realpath(SilcSFTP sftp,
1228 SilcSFTPNameCallback callback,
1231 SilcSFTPClient client = (SilcSFTPClient)sftp;
1232 SilcSFTPRequest req;
1235 SILC_LOG_DEBUG(("Realpath request"));
1237 req = silc_calloc(1, sizeof(*req));
1240 req->id = client->id++;
1241 req->type = SILC_SFTP_REALPATH;
1242 req->name = callback;
1243 req->context = context;
1244 silc_list_add(client->requests, req);
1246 len = 4 + 4 + strlen(path);
1248 silc_sftp_send_packet(client, req->type, len,
1249 SILC_STR_UI_INT(req->id),
1250 SILC_STR_UI_INT(strlen(path)),
1251 SILC_STR_UI32_STRING(path),
1255 void silc_sftp_extended(SilcSFTP sftp,
1256 const char *request,
1257 const unsigned char *data,
1258 SilcUInt32 data_len,
1259 SilcSFTPExtendedCallback callback,
1262 SilcSFTPClient client = (SilcSFTPClient)sftp;
1263 SilcSFTPRequest req;
1266 SILC_LOG_DEBUG(("Extended request"));
1268 req = silc_calloc(1, sizeof(*req));
1271 req->id = client->id++;
1272 req->type = SILC_SFTP_WRITE;
1273 req->extended = callback;
1274 req->context = context;
1275 silc_list_add(client->requests, req);
1277 len = 4 + 4 + strlen(request) + data_len;
1279 silc_sftp_send_packet(client, req->type, len,
1280 SILC_STR_UI_INT(req->id),
1281 SILC_STR_UI_INT(strlen(request)),
1282 SILC_STR_UI32_STRING(request),
1283 SILC_STR_UI_XNSTRING(data, data_len),