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 SilcSchedule schedule;
44 SilcSFTPVersionCallback version;
45 SilcSFTPErrorCallback error;
53 struct SilcSFTPHandleStruct {
58 static void silc_sftp_client_receive_process(SilcSFTP context,
61 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
64 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
67 SilcSFTPHandle handle;
69 handle = silc_calloc(1, sizeof(*handle));
72 handle->data = silc_calloc(data_len, sizeof(*handle->data));
75 memcpy(handle->data, data, data_len);
76 handle->data_len = data_len;
81 /* Deletes the handle indicated by the `handle'. */
83 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
85 silc_free(handle->data);
89 /* Returns the handle data of the `handle' to the `data' pointer. */
91 static void silc_sftp_handle_get(SilcSFTPHandle handle,
92 const unsigned char **data,
95 *data = (const unsigned char *)handle->data;
96 *data_len = handle->data_len;
99 /* Generic routine to send SFTP packet to the SFTP server. */
101 static void silc_sftp_send_packet(SilcSFTPClient sftp,
110 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
116 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
117 silc_buffer_len(sftp->packet));
119 /* Send the packet */
120 while (silc_buffer_len(sftp->packet) > 0) {
121 ret = silc_stream_write(sftp->stream, silc_buffer_data(sftp->packet),
122 silc_buffer_len(sftp->packet));
124 SILC_LOG_ERROR(("Error sending SFTP packet type %d", type));
125 sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_NO_CONNECTION,
127 silc_buffer_reset(sftp->packet);
131 sftp->error((SilcSFTP)sftp, SILC_SFTP_STATUS_EOF, sftp->context);
132 silc_buffer_reset(sftp->packet);
138 silc_buffer_pull(sftp->packet, ret);
142 silc_buffer_reset(sftp->packet);
145 /* Finds request by request ID. */
147 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp,
152 SILC_LOG_DEBUG(("Finding request ID: %d", id));
154 silc_list_start(sftp->requests);
155 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
160 SILC_LOG_DEBUG(("Unknown request ID %d", id));
165 /* Function used to call the request callback indicated by the `req'. The
166 `status' will be sent to the callback function as the status of the
167 operation. The variable argument list includes the status and req->type
170 static void silc_sftp_call_request(SilcSFTPClient sftp,
173 SilcSFTPStatus status, ...)
177 SILC_LOG_DEBUG(("Start"));
179 va_start(vp, status);
188 if (status != SILC_SFTP_STATUS_OK) {
190 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
194 data = (unsigned char *)va_arg(vp, unsigned char *);
195 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
198 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
199 data_len, req->context);
204 case SILC_SFTP_OPENDIR:
206 /* Handle returned */
207 SilcSFTPHandle handle;
208 unsigned char *hdata;
209 SilcUInt32 hdata_len;
211 if (status != SILC_SFTP_STATUS_OK) {
213 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
217 hdata = (unsigned char *)va_arg(vp, unsigned char *);
218 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
219 handle = silc_sftp_handle_create(hdata, hdata_len);
222 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
227 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
231 case SILC_SFTP_CLOSE:
232 case SILC_SFTP_WRITE:
233 case SILC_SFTP_REMOVE:
234 case SILC_SFTP_RENAME:
235 case SILC_SFTP_MKDIR:
236 case SILC_SFTP_RMDIR:
237 case SILC_SFTP_SETSTAT:
238 case SILC_SFTP_FSETSTAT:
239 case SILC_SFTP_SYMLINK:
241 /* Status returned */
242 char *message, *language_tag;
244 message = (char *)va_arg(vp, char *);
245 language_tag = (char *)va_arg(vp, char *);
248 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
249 (const char *)language_tag, req->context);
254 case SILC_SFTP_LSTAT:
255 case SILC_SFTP_FSTAT:
257 /* Attributes returned */
258 SilcSFTPAttributes attr;
260 if (status != SILC_SFTP_STATUS_OK) {
262 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
266 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
269 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
274 case SILC_SFTP_READDIR:
275 case SILC_SFTP_REALPATH:
276 case SILC_SFTP_READLINK:
278 /* Name(s) returned */
281 if (status != SILC_SFTP_STATUS_OK) {
283 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
287 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
290 (*req->name)((SilcSFTP)sftp, status, name, req->context);
294 case SILC_SFTP_EXTENDED:
296 /* Extended reply returned */
300 if (status != SILC_SFTP_STATUS_OK) {
302 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
306 data = (unsigned char *)va_arg(vp, unsigned char *);
307 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
310 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
311 data_len, req->context);
316 SILC_LOG_DEBUG(("Unknown request type %d", req->type));
320 /* Remove this request */
321 silc_list_del(sftp->requests, req);
327 /* Handles stream I/O */
329 static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status,
332 SilcSFTPClient sftp = context;
333 unsigned char inbuf[65536];
334 SilcBufferStruct packet;
338 case SILC_STREAM_CAN_READ:
339 SILC_LOG_DEBUG(("Reading data from stream"));
341 /* Read data from stream */
342 ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
345 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
347 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
351 SILC_LOG_DEBUG(("Read %d bytes", ret));
353 /* Now process the SFTP packet */
354 silc_buffer_set(&packet, inbuf, ret);
355 silc_sftp_client_receive_process(context, &packet);
358 case SILC_STREAM_CAN_WRITE:
359 if (!silc_buffer_headlen(sftp->packet))
362 SILC_LOG_DEBUG(("Writing pending data to stream"));
364 /* Write pending data to stream */
365 silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
366 while (silc_buffer_len(sftp->packet) > 0) {
367 ret = silc_stream_write(stream, sftp->packet->data,
368 silc_buffer_len(sftp->packet));
370 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
371 silc_buffer_reset(sftp->packet);
376 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
377 silc_buffer_reset(sftp->packet);
385 silc_buffer_pull(sftp->packet, ret);
394 /* Starts SFTP client and returns context for it. */
396 SilcSFTP silc_sftp_client_start(SilcStream stream,
397 SilcSchedule schedule,
398 SilcSFTPVersionCallback version_cb,
399 SilcSFTPErrorCallback error_cb,
404 SILC_LOG_DEBUG(("Starting SFTP client"));
407 schedule = silc_schedule_get_global();
412 sftp = silc_calloc(1, sizeof(*sftp));
415 sftp->stream = stream;
416 sftp->version = version_cb;
417 sftp->error = error_cb;
418 sftp->context = context;
419 sftp->schedule = schedule;
420 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
422 /* We handle the stream now */
423 silc_stream_set_notifier(stream, schedule, silc_sftp_client_io, sftp);
425 /* Send the SFTP session initialization to the server */
426 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
427 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
430 return (SilcSFTP)sftp;
433 /* Shutdown's the SFTP client. The caller is responsible of closing
434 the associated socket connection. The SFTP context is freed and is
435 invalid after this function returns. */
437 void silc_sftp_client_shutdown(SilcSFTP context)
439 SilcSFTPClient sftp = (SilcSFTPClient)context;
441 silc_stream_set_notifier(sftp->stream, sftp->schedule, NULL, NULL);
443 silc_buffer_free(sftp->packet);
447 /* Function that is called to process the incmoing SFTP packet. */
449 void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer)
451 SilcSFTPClient sftp = (SilcSFTPClient)context;
454 unsigned char *payload = NULL;
455 SilcUInt32 payload_len;
457 SilcBufferStruct buf;
460 SILC_LOG_DEBUG(("Process SFTP packet"));
462 /* Parse the packet */
463 type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
467 silc_buffer_set(&buf, payload, payload_len);
472 unsigned char *data = NULL;
473 SilcUInt32 data_len = 0;
475 SILC_LOG_DEBUG(("Data packet"));
477 ret = silc_buffer_unformat(&buf,
478 SILC_STR_UI_INT(&id),
479 SILC_STR_UI32_NSTRING(&data, &data_len),
485 req = silc_sftp_find_request(sftp, id);
489 /* Call the callback */
490 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
495 case SILC_SFTP_VERSION:
497 SilcSFTPVersion version;
499 SILC_LOG_DEBUG(("Version packet"));
501 ret = silc_buffer_unformat(&buf,
502 SILC_STR_UI_INT(&version),
505 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
510 /* Call the callback */
511 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
516 case SILC_SFTP_STATUS:
519 char *message = NULL, *language_tag = NULL;
521 SILC_LOG_DEBUG(("Status packet"));
523 ret = silc_buffer_unformat(&buf,
524 SILC_STR_UI_INT(&id),
525 SILC_STR_UI_INT(&status),
530 if (status != SILC_SFTP_STATUS_OK) {
531 silc_buffer_pull(&buf, 8);
532 ret = silc_buffer_unformat(&buf,
533 SILC_STR_UI32_STRING_ALLOC(&message),
534 SILC_STR_UI32_STRING_ALLOC(&language_tag),
539 silc_buffer_push(&buf, 8);
543 req = silc_sftp_find_request(sftp, id);
546 silc_free(language_tag);
550 /* Call the callback */
551 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
554 silc_free(language_tag);
558 case SILC_SFTP_HANDLE:
560 unsigned char *handle = NULL;
561 SilcUInt32 handle_len;
563 SILC_LOG_DEBUG(("Handle packet"));
565 ret = silc_buffer_unformat(&buf,
566 SILC_STR_UI_INT(&id),
567 SILC_STR_UI32_NSTRING(&handle,
574 req = silc_sftp_find_request(sftp, id);
578 /* Call the callback */
579 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
587 SilcSFTPName name = NULL;
589 SILC_LOG_DEBUG(("Name packet"));
591 ret = silc_buffer_unformat(&buf,
592 SILC_STR_UI_INT(&id),
593 SILC_STR_UI_INT(&count),
599 req = silc_sftp_find_request(sftp, id);
603 silc_buffer_pull(&buf, 8);
604 name = silc_sftp_name_decode(count, &buf);
607 silc_buffer_push(&buf, 8);
609 /* Call the callback */
610 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
611 silc_sftp_name_free(name);
615 case SILC_SFTP_ATTRS:
617 SilcSFTPAttributes attr = NULL;
619 SilcBufferStruct tmpbuf;
621 SILC_LOG_DEBUG(("Attributes packet"));
624 silc_buffer_unformat(&buf,
625 SILC_STR_UI_INT(&id),
626 SILC_STR_DATA(&data, silc_buffer_len(&buf) - 4),
632 req = silc_sftp_find_request(sftp, id);
636 silc_buffer_set(&tmpbuf, data, silc_buffer_len(&buf) - 4);
637 attr = silc_sftp_attr_decode(&tmpbuf);
641 /* Call the callback */
642 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
646 case SILC_SFTP_EXTENDED_REPLY:
648 unsigned char *data = NULL;
650 SILC_LOG_DEBUG(("Extended reply packet"));
652 ret = silc_buffer_unformat(&buf,
653 SILC_STR_UI_INT(&id),
655 silc_buffer_len(&buf) - 4),
661 req = silc_sftp_find_request(sftp, id);
665 /* Call the callback */
666 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
667 data, silc_buffer_len(&buf) - 4);
676 void silc_sftp_open(SilcSFTP sftp,
677 const char *filename,
678 SilcSFTPFileOperation pflags,
679 SilcSFTPAttributes attrs,
680 SilcSFTPHandleCallback callback,
683 SilcSFTPClient client = (SilcSFTPClient)sftp;
685 SilcBuffer attrs_buf;
688 SILC_LOG_DEBUG(("Open request"));
690 req = silc_calloc(1, sizeof(*req));
693 req->id = client->id++;
694 req->type = SILC_SFTP_OPEN;
695 req->handle = callback;
696 req->context = context;
697 silc_list_add(client->requests, req);
699 attrs_buf = silc_sftp_attr_encode(attrs);
702 len = 4 + 4 + strlen(filename) + 4 + silc_buffer_len(attrs_buf);
704 silc_sftp_send_packet(client, req->type, len,
705 SILC_STR_UI_INT(req->id),
706 SILC_STR_UI_INT(strlen(filename)),
707 SILC_STR_UI32_STRING(filename),
708 SILC_STR_UI_INT(pflags),
709 SILC_STR_UI_XNSTRING(attrs_buf->data,
710 silc_buffer_len(attrs_buf)),
713 silc_buffer_free(attrs_buf);
716 void silc_sftp_close(SilcSFTP sftp,
717 SilcSFTPHandle handle,
718 SilcSFTPStatusCallback callback,
721 SilcSFTPClient client = (SilcSFTPClient)sftp;
724 const unsigned char *hdata;
725 SilcUInt32 hdata_len;
727 SILC_LOG_DEBUG(("Close request"));
729 req = silc_calloc(1, sizeof(*req));
732 req->id = client->id++;
733 req->type = SILC_SFTP_CLOSE;
734 req->status = callback;
735 req->context = context;
736 silc_list_add(client->requests, req);
738 silc_sftp_handle_get(handle, &hdata, &hdata_len);
739 len = 4 + 4 + hdata_len;
741 silc_sftp_send_packet(client, req->type, len,
742 SILC_STR_UI_INT(req->id),
743 SILC_STR_UI_INT(hdata_len),
744 SILC_STR_UI_XNSTRING(hdata, hdata_len),
746 silc_sftp_handle_delete(handle);
749 void silc_sftp_read(SilcSFTP sftp,
750 SilcSFTPHandle handle,
753 SilcSFTPDataCallback callback,
756 SilcSFTPClient client = (SilcSFTPClient)sftp;
759 const unsigned char *hdata;
760 SilcUInt32 hdata_len;
762 SILC_LOG_DEBUG(("Read request"));
764 req = silc_calloc(1, sizeof(*req));
767 req->id = client->id++;
768 req->type = SILC_SFTP_READ;
769 req->data = callback;
770 req->context = context;
771 silc_list_add(client->requests, req);
773 silc_sftp_handle_get(handle, &hdata, &hdata_len);
774 len2 = 4 + 4 + hdata_len + 8 + 4;
776 silc_sftp_send_packet(client, req->type, len2,
777 SILC_STR_UI_INT(req->id),
778 SILC_STR_UI_INT(hdata_len),
779 SILC_STR_UI_XNSTRING(hdata, hdata_len),
780 SILC_STR_UI_INT64(offset),
781 SILC_STR_UI_INT(len),
785 void silc_sftp_write(SilcSFTP sftp,
786 SilcSFTPHandle handle,
788 const unsigned char *data,
790 SilcSFTPStatusCallback callback,
793 SilcSFTPClient client = (SilcSFTPClient)sftp;
796 const unsigned char *hdata;
797 SilcUInt32 hdata_len;
799 SILC_LOG_DEBUG(("Write request"));
801 req = silc_calloc(1, sizeof(*req));
804 req->id = client->id++;
805 req->type = SILC_SFTP_WRITE;
806 req->status = callback;
807 req->context = context;
808 silc_list_add(client->requests, req);
810 silc_sftp_handle_get(handle, &hdata, &hdata_len);
811 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
813 silc_sftp_send_packet(client, req->type, len,
814 SILC_STR_UI_INT(req->id),
815 SILC_STR_UI_INT(hdata_len),
816 SILC_STR_UI_XNSTRING(hdata, hdata_len),
817 SILC_STR_UI_INT64(offset),
818 SILC_STR_UI_INT(data_len),
819 SILC_STR_UI_XNSTRING(data, data_len),
823 void silc_sftp_remove(SilcSFTP sftp,
824 const char *filename,
825 SilcSFTPStatusCallback callback,
828 SilcSFTPClient client = (SilcSFTPClient)sftp;
832 SILC_LOG_DEBUG(("Remove request"));
834 req = silc_calloc(1, sizeof(*req));
837 req->id = client->id++;
838 req->type = SILC_SFTP_REMOVE;
839 req->status = callback;
840 req->context = context;
841 silc_list_add(client->requests, req);
843 len = 4 + 4 + strlen(filename);
845 silc_sftp_send_packet(client, req->type, len,
846 SILC_STR_UI_INT(req->id),
847 SILC_STR_UI_INT(strlen(filename)),
848 SILC_STR_UI32_STRING(filename),
852 void silc_sftp_rename(SilcSFTP sftp,
855 SilcSFTPStatusCallback callback,
858 SilcSFTPClient client = (SilcSFTPClient)sftp;
862 SILC_LOG_DEBUG(("Rename request"));
864 req = silc_calloc(1, sizeof(*req));
867 req->id = client->id++;
868 req->type = SILC_SFTP_RENAME;
869 req->status = callback;
870 req->context = context;
871 silc_list_add(client->requests, req);
873 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
875 silc_sftp_send_packet(client, req->type, len,
876 SILC_STR_UI_INT(req->id),
877 SILC_STR_UI_INT(strlen(oldname)),
878 SILC_STR_UI32_STRING(oldname),
879 SILC_STR_UI_INT(strlen(newname)),
880 SILC_STR_UI32_STRING(newname),
884 void silc_sftp_mkdir(SilcSFTP sftp,
886 SilcSFTPAttributes attrs,
887 SilcSFTPStatusCallback callback,
890 SilcSFTPClient client = (SilcSFTPClient)sftp;
893 SilcBuffer attrs_buf;
895 SILC_LOG_DEBUG(("Mkdir request"));
897 req = silc_calloc(1, sizeof(*req));
900 req->id = client->id++;
901 req->type = SILC_SFTP_MKDIR;
902 req->status = callback;
903 req->context = context;
904 silc_list_add(client->requests, req);
906 attrs_buf = silc_sftp_attr_encode(attrs);
909 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
911 silc_sftp_send_packet(client, req->type, len,
912 SILC_STR_UI_INT(req->id),
913 SILC_STR_UI_INT(strlen(path)),
914 SILC_STR_UI32_STRING(path),
915 SILC_STR_UI_XNSTRING(attrs_buf->data,
916 silc_buffer_len(attrs_buf)),
919 silc_buffer_free(attrs_buf);
922 void silc_sftp_rmdir(SilcSFTP sftp,
924 SilcSFTPStatusCallback callback,
927 SilcSFTPClient client = (SilcSFTPClient)sftp;
931 SILC_LOG_DEBUG(("Rmdir request"));
933 req = silc_calloc(1, sizeof(*req));
936 req->id = client->id++;
937 req->type = SILC_SFTP_RMDIR;
938 req->status = callback;
939 req->context = context;
940 silc_list_add(client->requests, req);
942 len = 4 + 4 + strlen(path);
944 silc_sftp_send_packet(client, req->type, len,
945 SILC_STR_UI_INT(req->id),
946 SILC_STR_UI_INT(strlen(path)),
947 SILC_STR_UI32_STRING(path),
951 void silc_sftp_opendir(SilcSFTP sftp,
953 SilcSFTPHandleCallback callback,
956 SilcSFTPClient client = (SilcSFTPClient)sftp;
960 SILC_LOG_DEBUG(("Opendir request"));
962 req = silc_calloc(1, sizeof(*req));
965 req->id = client->id++;
966 req->type = SILC_SFTP_OPENDIR;
967 req->handle = callback;
968 req->context = context;
969 silc_list_add(client->requests, req);
971 len = 4 + 4 + strlen(path);
973 silc_sftp_send_packet(client, req->type, len,
974 SILC_STR_UI_INT(req->id),
975 SILC_STR_UI_INT(strlen(path)),
976 SILC_STR_UI32_STRING(path),
980 void silc_sftp_readdir(SilcSFTP sftp,
981 SilcSFTPHandle handle,
982 SilcSFTPNameCallback callback,
985 SilcSFTPClient client = (SilcSFTPClient)sftp;
988 const unsigned char *hdata;
989 SilcUInt32 hdata_len;
991 SILC_LOG_DEBUG(("Readdir request"));
993 req = silc_calloc(1, sizeof(*req));
996 req->id = client->id++;
997 req->type = SILC_SFTP_READDIR;
998 req->name = callback;
999 req->context = context;
1000 silc_list_add(client->requests, req);
1002 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1003 len = 4 + 4 + hdata_len;
1005 silc_sftp_send_packet(client, req->type, len,
1006 SILC_STR_UI_INT(req->id),
1007 SILC_STR_UI_INT(hdata_len),
1008 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1012 void silc_sftp_stat(SilcSFTP sftp,
1014 SilcSFTPAttrCallback callback,
1017 SilcSFTPClient client = (SilcSFTPClient)sftp;
1018 SilcSFTPRequest req;
1021 SILC_LOG_DEBUG(("Stat request"));
1023 req = silc_calloc(1, sizeof(*req));
1026 req->id = client->id++;
1027 req->type = SILC_SFTP_STAT;
1028 req->attr = callback;
1029 req->context = context;
1030 silc_list_add(client->requests, req);
1032 len = 4 + 4 + strlen(path);
1034 silc_sftp_send_packet(client, req->type, len,
1035 SILC_STR_UI_INT(req->id),
1036 SILC_STR_UI_INT(strlen(path)),
1037 SILC_STR_UI32_STRING(path),
1041 void silc_sftp_lstat(SilcSFTP sftp,
1043 SilcSFTPAttrCallback callback,
1046 SilcSFTPClient client = (SilcSFTPClient)sftp;
1047 SilcSFTPRequest req;
1050 SILC_LOG_DEBUG(("Lstat request"));
1052 req = silc_calloc(1, sizeof(*req));
1055 req->id = client->id++;
1056 req->type = SILC_SFTP_LSTAT;
1057 req->attr = callback;
1058 req->context = context;
1059 silc_list_add(client->requests, req);
1061 len = 4 + 4 + strlen(path);
1063 silc_sftp_send_packet(client, req->type, len,
1064 SILC_STR_UI_INT(req->id),
1065 SILC_STR_UI_INT(strlen(path)),
1066 SILC_STR_UI32_STRING(path),
1070 void silc_sftp_fstat(SilcSFTP sftp,
1071 SilcSFTPHandle handle,
1072 SilcSFTPAttrCallback callback,
1075 SilcSFTPClient client = (SilcSFTPClient)sftp;
1076 SilcSFTPRequest req;
1078 const unsigned char *hdata;
1079 SilcUInt32 hdata_len;
1081 SILC_LOG_DEBUG(("Fstat request"));
1083 req = silc_calloc(1, sizeof(*req));
1086 req->id = client->id++;
1087 req->type = SILC_SFTP_FSTAT;
1088 req->attr = callback;
1089 req->context = context;
1090 silc_list_add(client->requests, req);
1092 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1093 len = 4 + 4 + hdata_len;
1095 silc_sftp_send_packet(client, req->type, len,
1096 SILC_STR_UI_INT(req->id),
1097 SILC_STR_UI_INT(hdata_len),
1098 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1102 void silc_sftp_setstat(SilcSFTP sftp,
1104 SilcSFTPAttributes attrs,
1105 SilcSFTPStatusCallback callback,
1108 SilcSFTPClient client = (SilcSFTPClient)sftp;
1109 SilcSFTPRequest req;
1111 SilcBuffer attrs_buf;
1113 SILC_LOG_DEBUG(("Setstat request"));
1115 req = silc_calloc(1, sizeof(*req));
1118 req->id = client->id++;
1119 req->type = SILC_SFTP_SETSTAT;
1120 req->status = callback;
1121 req->context = context;
1122 silc_list_add(client->requests, req);
1124 attrs_buf = silc_sftp_attr_encode(attrs);
1127 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
1129 silc_sftp_send_packet(client, req->type, len,
1130 SILC_STR_UI_INT(req->id),
1131 SILC_STR_UI_INT(strlen(path)),
1132 SILC_STR_UI32_STRING(path),
1133 SILC_STR_UI_XNSTRING(attrs_buf->data,
1134 silc_buffer_len(attrs_buf)),
1137 silc_buffer_free(attrs_buf);
1140 void silc_sftp_fsetstat(SilcSFTP sftp,
1141 SilcSFTPHandle handle,
1142 SilcSFTPAttributes attrs,
1143 SilcSFTPStatusCallback callback,
1146 SilcSFTPClient client = (SilcSFTPClient)sftp;
1147 SilcSFTPRequest req;
1149 SilcBuffer attrs_buf;
1150 const unsigned char *hdata;
1151 SilcUInt32 hdata_len;
1153 SILC_LOG_DEBUG(("Fsetstat request"));
1155 req = silc_calloc(1, sizeof(*req));
1158 req->id = client->id++;
1159 req->type = SILC_SFTP_FSETSTAT;
1160 req->status = callback;
1161 req->context = context;
1162 silc_list_add(client->requests, req);
1164 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1165 attrs_buf = silc_sftp_attr_encode(attrs);
1168 len = 4 + 4 + hdata_len + silc_buffer_len(attrs_buf);
1170 silc_sftp_send_packet(client, req->type, len,
1171 SILC_STR_UI_INT(req->id),
1172 SILC_STR_UI_INT(hdata_len),
1173 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1174 SILC_STR_UI_XNSTRING(attrs_buf->data,
1175 silc_buffer_len(attrs_buf)),
1178 silc_buffer_free(attrs_buf);
1181 void silc_sftp_readlink(SilcSFTP sftp,
1183 SilcSFTPNameCallback callback,
1186 SilcSFTPClient client = (SilcSFTPClient)sftp;
1187 SilcSFTPRequest req;
1190 SILC_LOG_DEBUG(("Readlink request"));
1192 req = silc_calloc(1, sizeof(*req));
1195 req->id = client->id++;
1196 req->type = SILC_SFTP_READLINK;
1197 req->name = callback;
1198 req->context = context;
1199 silc_list_add(client->requests, req);
1201 len = 4 + 4 + strlen(path);
1203 silc_sftp_send_packet(client, req->type, len,
1204 SILC_STR_UI_INT(req->id),
1205 SILC_STR_UI_INT(strlen(path)),
1206 SILC_STR_UI32_STRING(path),
1210 void silc_sftp_symlink(SilcSFTP sftp,
1211 const char *linkpath,
1212 const char *targetpath,
1213 SilcSFTPStatusCallback callback,
1216 SilcSFTPClient client = (SilcSFTPClient)sftp;
1217 SilcSFTPRequest req;
1220 SILC_LOG_DEBUG(("Symlink request"));
1222 req = silc_calloc(1, sizeof(*req));
1225 req->id = client->id++;
1226 req->type = SILC_SFTP_SYMLINK;
1227 req->status = callback;
1228 req->context = context;
1229 silc_list_add(client->requests, req);
1231 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1233 silc_sftp_send_packet(client, req->type, len,
1234 SILC_STR_UI_INT(req->id),
1235 SILC_STR_UI_INT(strlen(linkpath)),
1236 SILC_STR_UI32_STRING(linkpath),
1237 SILC_STR_UI_INT(strlen(targetpath)),
1238 SILC_STR_UI32_STRING(targetpath),
1242 void silc_sftp_realpath(SilcSFTP sftp,
1244 SilcSFTPNameCallback callback,
1247 SilcSFTPClient client = (SilcSFTPClient)sftp;
1248 SilcSFTPRequest req;
1251 SILC_LOG_DEBUG(("Realpath request"));
1253 req = silc_calloc(1, sizeof(*req));
1256 req->id = client->id++;
1257 req->type = SILC_SFTP_REALPATH;
1258 req->name = callback;
1259 req->context = context;
1260 silc_list_add(client->requests, req);
1262 len = 4 + 4 + strlen(path);
1264 silc_sftp_send_packet(client, req->type, len,
1265 SILC_STR_UI_INT(req->id),
1266 SILC_STR_UI_INT(strlen(path)),
1267 SILC_STR_UI32_STRING(path),
1271 void silc_sftp_extended(SilcSFTP sftp,
1272 const char *request,
1273 const unsigned char *data,
1274 SilcUInt32 data_len,
1275 SilcSFTPExtendedCallback callback,
1278 SilcSFTPClient client = (SilcSFTPClient)sftp;
1279 SilcSFTPRequest req;
1282 SILC_LOG_DEBUG(("Extended request"));
1284 req = silc_calloc(1, sizeof(*req));
1287 req->id = client->id++;
1288 req->type = SILC_SFTP_WRITE;
1289 req->extended = callback;
1290 req->context = context;
1291 silc_list_add(client->requests, req);
1293 len = 4 + 4 + strlen(request) + data_len;
1295 silc_sftp_send_packet(client, req->type, len,
1296 SILC_STR_UI_INT(req->id),
1297 SILC_STR_UI_INT(strlen(request)),
1298 SILC_STR_UI32_STRING(request),
1299 SILC_STR_UI_XNSTRING(data, data_len),