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);
319 /* Remove this request */
320 silc_list_del(sftp->requests, req);
326 /* Handles stream I/O */
328 static void silc_sftp_client_io(SilcStream stream, SilcStreamStatus status,
331 SilcSFTPClient sftp = context;
332 unsigned char inbuf[30720];
333 SilcBufferStruct packet;
337 case SILC_STREAM_CAN_READ:
338 SILC_LOG_DEBUG(("Reading data from stream"));
340 /* Read data from stream */
341 ret = silc_stream_read(stream, inbuf, sizeof(inbuf));
344 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
346 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
350 /* Now process the SFTP packet */
351 silc_buffer_set(&packet, inbuf, ret);
352 silc_sftp_client_receive_process(context, &packet);
355 case SILC_STREAM_CAN_WRITE:
356 if (!silc_buffer_headlen(sftp->packet))
359 SILC_LOG_DEBUG(("Writing pending data to stream"));
361 /* Write pending data to stream */
362 silc_buffer_push(sftp->packet, silc_buffer_headlen(sftp->packet));
363 while (silc_buffer_len(sftp->packet) > 0) {
364 ret = silc_stream_write(stream, sftp->packet->data,
365 silc_buffer_len(sftp->packet));
367 sftp->error(context, SILC_SFTP_STATUS_EOF, sftp->context);
368 silc_buffer_reset(sftp->packet);
373 sftp->error(context, SILC_SFTP_STATUS_NO_CONNECTION, sftp->context);
374 silc_buffer_reset(sftp->packet);
382 silc_buffer_pull(sftp->packet, ret);
391 /* Starts SFTP client and returns context for it. */
393 SilcSFTP silc_sftp_client_start(SilcStream stream,
394 SilcSchedule schedule,
395 SilcSFTPVersionCallback version_cb,
396 SilcSFTPErrorCallback error_cb,
401 SILC_LOG_DEBUG(("Starting SFTP client"));
406 sftp = silc_calloc(1, sizeof(*sftp));
409 sftp->stream = stream;
410 sftp->version = version_cb;
411 sftp->error = error_cb;
412 sftp->context = context;
413 sftp->schedule = schedule;
414 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
416 /* We handle the stream now */
417 silc_stream_set_notifier(stream, schedule, silc_sftp_client_io, sftp);
419 /* Send the SFTP session initialization to the server */
420 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
421 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
424 return (SilcSFTP)sftp;
427 /* Shutdown's the SFTP client. The caller is responsible of closing
428 the associated socket connection. The SFTP context is freed and is
429 invalid after this function returns. */
431 void silc_sftp_client_shutdown(SilcSFTP context)
433 SilcSFTPClient sftp = (SilcSFTPClient)context;
435 silc_stream_set_notifier(sftp->stream, sftp->schedule, NULL, NULL);
437 silc_buffer_free(sftp->packet);
441 /* Function that is called to process the incmoing SFTP packet. */
443 void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer)
445 SilcSFTPClient sftp = (SilcSFTPClient)context;
448 unsigned char *payload = NULL;
449 SilcUInt32 payload_len;
451 SilcBufferStruct buf;
454 SILC_LOG_DEBUG(("Process SFTP packet"));
456 /* Parse the packet */
457 type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
461 silc_buffer_set(&buf, payload, payload_len);
466 unsigned char *data = NULL;
467 SilcUInt32 data_len = 0;
469 SILC_LOG_DEBUG(("Data packet"));
471 ret = silc_buffer_unformat(&buf,
472 SILC_STR_UI_INT(&id),
473 SILC_STR_UI32_NSTRING(&data, &data_len),
479 req = silc_sftp_find_request(sftp, id);
483 /* Call the callback */
484 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
489 case SILC_SFTP_VERSION:
491 SilcSFTPVersion version;
493 SILC_LOG_DEBUG(("Version packet"));
495 ret = silc_buffer_unformat(&buf,
496 SILC_STR_UI_INT(&version),
499 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
504 /* Call the callback */
505 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
510 case SILC_SFTP_STATUS:
513 char *message = NULL, *language_tag = NULL;
515 SILC_LOG_DEBUG(("Status packet"));
517 ret = silc_buffer_unformat(&buf,
518 SILC_STR_UI_INT(&id),
519 SILC_STR_UI_INT(&status),
524 if (status != SILC_SFTP_STATUS_OK) {
525 silc_buffer_pull(&buf, 8);
526 ret = silc_buffer_unformat(&buf,
527 SILC_STR_UI32_STRING_ALLOC(&message),
528 SILC_STR_UI32_STRING_ALLOC(&language_tag),
533 silc_buffer_push(&buf, 8);
537 req = silc_sftp_find_request(sftp, id);
540 silc_free(language_tag);
544 /* Call the callback */
545 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
548 silc_free(language_tag);
552 case SILC_SFTP_HANDLE:
554 unsigned char *handle = NULL;
555 SilcUInt32 handle_len;
557 SILC_LOG_DEBUG(("Handle packet"));
559 ret = silc_buffer_unformat(&buf,
560 SILC_STR_UI_INT(&id),
561 SILC_STR_UI32_NSTRING(&handle,
568 req = silc_sftp_find_request(sftp, id);
572 /* Call the callback */
573 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
581 SilcSFTPName name = NULL;
583 SILC_LOG_DEBUG(("Name packet"));
585 ret = silc_buffer_unformat(&buf,
586 SILC_STR_UI_INT(&id),
587 SILC_STR_UI_INT(&count),
593 req = silc_sftp_find_request(sftp, id);
597 silc_buffer_pull(&buf, 8);
598 name = silc_sftp_name_decode(count, &buf);
601 silc_buffer_push(&buf, 8);
603 /* Call the callback */
604 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
605 silc_sftp_name_free(name);
609 case SILC_SFTP_ATTRS:
611 SilcSFTPAttributes attr = NULL;
613 SilcBufferStruct tmpbuf;
615 SILC_LOG_DEBUG(("Attributes packet"));
618 silc_buffer_unformat(&buf,
619 SILC_STR_UI_INT(&id),
620 SILC_STR_DATA(&data, silc_buffer_len(&buf) - 4),
626 req = silc_sftp_find_request(sftp, id);
630 silc_buffer_set(&tmpbuf, data, silc_buffer_len(&buf) - 4);
631 attr = silc_sftp_attr_decode(&tmpbuf);
635 /* Call the callback */
636 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
640 case SILC_SFTP_EXTENDED_REPLY:
642 unsigned char *data = NULL;
644 SILC_LOG_DEBUG(("Extended reply packet"));
646 ret = silc_buffer_unformat(&buf,
647 SILC_STR_UI_INT(&id),
649 silc_buffer_len(&buf) - 4),
655 req = silc_sftp_find_request(sftp, id);
659 /* Call the callback */
660 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
661 data, silc_buffer_len(&buf) - 4);
670 void silc_sftp_open(SilcSFTP sftp,
671 const char *filename,
672 SilcSFTPFileOperation pflags,
673 SilcSFTPAttributes attrs,
674 SilcSFTPHandleCallback callback,
677 SilcSFTPClient client = (SilcSFTPClient)sftp;
679 SilcBuffer attrs_buf;
682 SILC_LOG_DEBUG(("Open request"));
684 req = silc_calloc(1, sizeof(*req));
687 req->id = client->id++;
688 req->type = SILC_SFTP_OPEN;
689 req->handle = callback;
690 req->context = context;
691 silc_list_add(client->requests, req);
693 attrs_buf = silc_sftp_attr_encode(attrs);
696 len = 4 + 4 + strlen(filename) + 4 + silc_buffer_len(attrs_buf);
698 silc_sftp_send_packet(client, req->type, len,
699 SILC_STR_UI_INT(req->id),
700 SILC_STR_UI_INT(strlen(filename)),
701 SILC_STR_UI32_STRING(filename),
702 SILC_STR_UI_INT(pflags),
703 SILC_STR_UI_XNSTRING(attrs_buf->data,
704 silc_buffer_len(attrs_buf)),
707 silc_buffer_free(attrs_buf);
710 void silc_sftp_close(SilcSFTP sftp,
711 SilcSFTPHandle handle,
712 SilcSFTPStatusCallback callback,
715 SilcSFTPClient client = (SilcSFTPClient)sftp;
718 const unsigned char *hdata;
719 SilcUInt32 hdata_len;
721 SILC_LOG_DEBUG(("Close request"));
723 req = silc_calloc(1, sizeof(*req));
726 req->id = client->id++;
727 req->type = SILC_SFTP_CLOSE;
728 req->status = callback;
729 req->context = context;
730 silc_list_add(client->requests, req);
732 silc_sftp_handle_get(handle, &hdata, &hdata_len);
733 len = 4 + 4 + hdata_len;
735 silc_sftp_send_packet(client, req->type, len,
736 SILC_STR_UI_INT(req->id),
737 SILC_STR_UI_INT(hdata_len),
738 SILC_STR_UI_XNSTRING(hdata, hdata_len),
740 silc_sftp_handle_delete(handle);
743 void silc_sftp_read(SilcSFTP sftp,
744 SilcSFTPHandle handle,
747 SilcSFTPDataCallback callback,
750 SilcSFTPClient client = (SilcSFTPClient)sftp;
753 const unsigned char *hdata;
754 SilcUInt32 hdata_len;
756 SILC_LOG_DEBUG(("Read request"));
758 req = silc_calloc(1, sizeof(*req));
761 req->id = client->id++;
762 req->type = SILC_SFTP_READ;
763 req->data = callback;
764 req->context = context;
765 silc_list_add(client->requests, req);
767 silc_sftp_handle_get(handle, &hdata, &hdata_len);
768 len2 = 4 + 4 + hdata_len + 8 + 4;
770 silc_sftp_send_packet(client, req->type, len2,
771 SILC_STR_UI_INT(req->id),
772 SILC_STR_UI_INT(hdata_len),
773 SILC_STR_UI_XNSTRING(hdata, hdata_len),
774 SILC_STR_UI_INT64(offset),
775 SILC_STR_UI_INT(len),
779 void silc_sftp_write(SilcSFTP sftp,
780 SilcSFTPHandle handle,
782 const unsigned char *data,
784 SilcSFTPStatusCallback callback,
787 SilcSFTPClient client = (SilcSFTPClient)sftp;
790 const unsigned char *hdata;
791 SilcUInt32 hdata_len;
793 SILC_LOG_DEBUG(("Write request"));
795 req = silc_calloc(1, sizeof(*req));
798 req->id = client->id++;
799 req->type = SILC_SFTP_WRITE;
800 req->status = callback;
801 req->context = context;
802 silc_list_add(client->requests, req);
804 silc_sftp_handle_get(handle, &hdata, &hdata_len);
805 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
807 silc_sftp_send_packet(client, req->type, len,
808 SILC_STR_UI_INT(req->id),
809 SILC_STR_UI_INT(hdata_len),
810 SILC_STR_UI_XNSTRING(hdata, hdata_len),
811 SILC_STR_UI_INT64(offset),
812 SILC_STR_UI_INT(data_len),
813 SILC_STR_UI_XNSTRING(data, data_len),
817 void silc_sftp_remove(SilcSFTP sftp,
818 const char *filename,
819 SilcSFTPStatusCallback callback,
822 SilcSFTPClient client = (SilcSFTPClient)sftp;
826 SILC_LOG_DEBUG(("Remove request"));
828 req = silc_calloc(1, sizeof(*req));
831 req->id = client->id++;
832 req->type = SILC_SFTP_REMOVE;
833 req->status = callback;
834 req->context = context;
835 silc_list_add(client->requests, req);
837 len = 4 + 4 + strlen(filename);
839 silc_sftp_send_packet(client, req->type, len,
840 SILC_STR_UI_INT(req->id),
841 SILC_STR_UI_INT(strlen(filename)),
842 SILC_STR_UI32_STRING(filename),
846 void silc_sftp_rename(SilcSFTP sftp,
849 SilcSFTPStatusCallback callback,
852 SilcSFTPClient client = (SilcSFTPClient)sftp;
856 SILC_LOG_DEBUG(("Rename request"));
858 req = silc_calloc(1, sizeof(*req));
861 req->id = client->id++;
862 req->type = SILC_SFTP_RENAME;
863 req->status = callback;
864 req->context = context;
865 silc_list_add(client->requests, req);
867 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
869 silc_sftp_send_packet(client, req->type, len,
870 SILC_STR_UI_INT(req->id),
871 SILC_STR_UI_INT(strlen(oldname)),
872 SILC_STR_UI32_STRING(oldname),
873 SILC_STR_UI_INT(strlen(newname)),
874 SILC_STR_UI32_STRING(newname),
878 void silc_sftp_mkdir(SilcSFTP sftp,
880 SilcSFTPAttributes attrs,
881 SilcSFTPStatusCallback callback,
884 SilcSFTPClient client = (SilcSFTPClient)sftp;
887 SilcBuffer attrs_buf;
889 SILC_LOG_DEBUG(("Mkdir request"));
891 req = silc_calloc(1, sizeof(*req));
894 req->id = client->id++;
895 req->type = SILC_SFTP_MKDIR;
896 req->status = callback;
897 req->context = context;
898 silc_list_add(client->requests, req);
900 attrs_buf = silc_sftp_attr_encode(attrs);
903 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
905 silc_sftp_send_packet(client, req->type, len,
906 SILC_STR_UI_INT(req->id),
907 SILC_STR_UI_INT(strlen(path)),
908 SILC_STR_UI32_STRING(path),
909 SILC_STR_UI_XNSTRING(attrs_buf->data,
910 silc_buffer_len(attrs_buf)),
913 silc_buffer_free(attrs_buf);
916 void silc_sftp_rmdir(SilcSFTP sftp,
918 SilcSFTPStatusCallback callback,
921 SilcSFTPClient client = (SilcSFTPClient)sftp;
925 SILC_LOG_DEBUG(("Rmdir request"));
927 req = silc_calloc(1, sizeof(*req));
930 req->id = client->id++;
931 req->type = SILC_SFTP_RMDIR;
932 req->status = callback;
933 req->context = context;
934 silc_list_add(client->requests, req);
936 len = 4 + 4 + strlen(path);
938 silc_sftp_send_packet(client, req->type, len,
939 SILC_STR_UI_INT(req->id),
940 SILC_STR_UI_INT(strlen(path)),
941 SILC_STR_UI32_STRING(path),
945 void silc_sftp_opendir(SilcSFTP sftp,
947 SilcSFTPHandleCallback callback,
950 SilcSFTPClient client = (SilcSFTPClient)sftp;
954 SILC_LOG_DEBUG(("Opendir request"));
956 req = silc_calloc(1, sizeof(*req));
959 req->id = client->id++;
960 req->type = SILC_SFTP_OPENDIR;
961 req->handle = callback;
962 req->context = context;
963 silc_list_add(client->requests, req);
965 len = 4 + 4 + strlen(path);
967 silc_sftp_send_packet(client, req->type, len,
968 SILC_STR_UI_INT(req->id),
969 SILC_STR_UI_INT(strlen(path)),
970 SILC_STR_UI32_STRING(path),
974 void silc_sftp_readdir(SilcSFTP sftp,
975 SilcSFTPHandle handle,
976 SilcSFTPNameCallback callback,
979 SilcSFTPClient client = (SilcSFTPClient)sftp;
982 const unsigned char *hdata;
983 SilcUInt32 hdata_len;
985 SILC_LOG_DEBUG(("Readdir request"));
987 req = silc_calloc(1, sizeof(*req));
990 req->id = client->id++;
991 req->type = SILC_SFTP_READDIR;
992 req->name = callback;
993 req->context = context;
994 silc_list_add(client->requests, req);
996 silc_sftp_handle_get(handle, &hdata, &hdata_len);
997 len = 4 + 4 + hdata_len;
999 silc_sftp_send_packet(client, req->type, len,
1000 SILC_STR_UI_INT(req->id),
1001 SILC_STR_UI_INT(hdata_len),
1002 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1006 void silc_sftp_stat(SilcSFTP sftp,
1008 SilcSFTPAttrCallback callback,
1011 SilcSFTPClient client = (SilcSFTPClient)sftp;
1012 SilcSFTPRequest req;
1015 SILC_LOG_DEBUG(("Stat request"));
1017 req = silc_calloc(1, sizeof(*req));
1020 req->id = client->id++;
1021 req->type = SILC_SFTP_STAT;
1022 req->attr = callback;
1023 req->context = context;
1024 silc_list_add(client->requests, req);
1026 len = 4 + 4 + strlen(path);
1028 silc_sftp_send_packet(client, req->type, len,
1029 SILC_STR_UI_INT(req->id),
1030 SILC_STR_UI_INT(strlen(path)),
1031 SILC_STR_UI32_STRING(path),
1035 void silc_sftp_lstat(SilcSFTP sftp,
1037 SilcSFTPAttrCallback callback,
1040 SilcSFTPClient client = (SilcSFTPClient)sftp;
1041 SilcSFTPRequest req;
1044 SILC_LOG_DEBUG(("Lstat request"));
1046 req = silc_calloc(1, sizeof(*req));
1049 req->id = client->id++;
1050 req->type = SILC_SFTP_LSTAT;
1051 req->attr = callback;
1052 req->context = context;
1053 silc_list_add(client->requests, req);
1055 len = 4 + 4 + strlen(path);
1057 silc_sftp_send_packet(client, req->type, len,
1058 SILC_STR_UI_INT(req->id),
1059 SILC_STR_UI_INT(strlen(path)),
1060 SILC_STR_UI32_STRING(path),
1064 void silc_sftp_fstat(SilcSFTP sftp,
1065 SilcSFTPHandle handle,
1066 SilcSFTPAttrCallback callback,
1069 SilcSFTPClient client = (SilcSFTPClient)sftp;
1070 SilcSFTPRequest req;
1072 const unsigned char *hdata;
1073 SilcUInt32 hdata_len;
1075 SILC_LOG_DEBUG(("Fstat request"));
1077 req = silc_calloc(1, sizeof(*req));
1080 req->id = client->id++;
1081 req->type = SILC_SFTP_FSTAT;
1082 req->attr = callback;
1083 req->context = context;
1084 silc_list_add(client->requests, req);
1086 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1087 len = 4 + 4 + hdata_len;
1089 silc_sftp_send_packet(client, req->type, len,
1090 SILC_STR_UI_INT(req->id),
1091 SILC_STR_UI_INT(hdata_len),
1092 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1096 void silc_sftp_setstat(SilcSFTP sftp,
1098 SilcSFTPAttributes attrs,
1099 SilcSFTPStatusCallback callback,
1102 SilcSFTPClient client = (SilcSFTPClient)sftp;
1103 SilcSFTPRequest req;
1105 SilcBuffer attrs_buf;
1107 SILC_LOG_DEBUG(("Setstat request"));
1109 req = silc_calloc(1, sizeof(*req));
1112 req->id = client->id++;
1113 req->type = SILC_SFTP_SETSTAT;
1114 req->status = callback;
1115 req->context = context;
1116 silc_list_add(client->requests, req);
1118 attrs_buf = silc_sftp_attr_encode(attrs);
1121 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
1123 silc_sftp_send_packet(client, req->type, len,
1124 SILC_STR_UI_INT(req->id),
1125 SILC_STR_UI_INT(strlen(path)),
1126 SILC_STR_UI32_STRING(path),
1127 SILC_STR_UI_XNSTRING(attrs_buf->data,
1128 silc_buffer_len(attrs_buf)),
1131 silc_buffer_free(attrs_buf);
1134 void silc_sftp_fsetstat(SilcSFTP sftp,
1135 SilcSFTPHandle handle,
1136 SilcSFTPAttributes attrs,
1137 SilcSFTPStatusCallback callback,
1140 SilcSFTPClient client = (SilcSFTPClient)sftp;
1141 SilcSFTPRequest req;
1143 SilcBuffer attrs_buf;
1144 const unsigned char *hdata;
1145 SilcUInt32 hdata_len;
1147 SILC_LOG_DEBUG(("Fsetstat request"));
1149 req = silc_calloc(1, sizeof(*req));
1152 req->id = client->id++;
1153 req->type = SILC_SFTP_FSETSTAT;
1154 req->status = callback;
1155 req->context = context;
1156 silc_list_add(client->requests, req);
1158 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1159 attrs_buf = silc_sftp_attr_encode(attrs);
1162 len = 4 + 4 + hdata_len + silc_buffer_len(attrs_buf);
1164 silc_sftp_send_packet(client, req->type, len,
1165 SILC_STR_UI_INT(req->id),
1166 SILC_STR_UI_INT(hdata_len),
1167 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1168 SILC_STR_UI_XNSTRING(attrs_buf->data,
1169 silc_buffer_len(attrs_buf)),
1172 silc_buffer_free(attrs_buf);
1175 void silc_sftp_readlink(SilcSFTP sftp,
1177 SilcSFTPNameCallback callback,
1180 SilcSFTPClient client = (SilcSFTPClient)sftp;
1181 SilcSFTPRequest req;
1184 SILC_LOG_DEBUG(("Readlink request"));
1186 req = silc_calloc(1, sizeof(*req));
1189 req->id = client->id++;
1190 req->type = SILC_SFTP_READLINK;
1191 req->name = callback;
1192 req->context = context;
1193 silc_list_add(client->requests, req);
1195 len = 4 + 4 + strlen(path);
1197 silc_sftp_send_packet(client, req->type, len,
1198 SILC_STR_UI_INT(req->id),
1199 SILC_STR_UI_INT(strlen(path)),
1200 SILC_STR_UI32_STRING(path),
1204 void silc_sftp_symlink(SilcSFTP sftp,
1205 const char *linkpath,
1206 const char *targetpath,
1207 SilcSFTPStatusCallback callback,
1210 SilcSFTPClient client = (SilcSFTPClient)sftp;
1211 SilcSFTPRequest req;
1214 SILC_LOG_DEBUG(("Symlink request"));
1216 req = silc_calloc(1, sizeof(*req));
1219 req->id = client->id++;
1220 req->type = SILC_SFTP_SYMLINK;
1221 req->status = callback;
1222 req->context = context;
1223 silc_list_add(client->requests, req);
1225 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1227 silc_sftp_send_packet(client, req->type, len,
1228 SILC_STR_UI_INT(req->id),
1229 SILC_STR_UI_INT(strlen(linkpath)),
1230 SILC_STR_UI32_STRING(linkpath),
1231 SILC_STR_UI_INT(strlen(targetpath)),
1232 SILC_STR_UI32_STRING(targetpath),
1236 void silc_sftp_realpath(SilcSFTP sftp,
1238 SilcSFTPNameCallback callback,
1241 SilcSFTPClient client = (SilcSFTPClient)sftp;
1242 SilcSFTPRequest req;
1245 SILC_LOG_DEBUG(("Realpath request"));
1247 req = silc_calloc(1, sizeof(*req));
1250 req->id = client->id++;
1251 req->type = SILC_SFTP_REALPATH;
1252 req->name = callback;
1253 req->context = context;
1254 silc_list_add(client->requests, req);
1256 len = 4 + 4 + strlen(path);
1258 silc_sftp_send_packet(client, req->type, len,
1259 SILC_STR_UI_INT(req->id),
1260 SILC_STR_UI_INT(strlen(path)),
1261 SILC_STR_UI32_STRING(path),
1265 void silc_sftp_extended(SilcSFTP sftp,
1266 const char *request,
1267 const unsigned char *data,
1268 SilcUInt32 data_len,
1269 SilcSFTPExtendedCallback callback,
1272 SilcSFTPClient client = (SilcSFTPClient)sftp;
1273 SilcSFTPRequest req;
1276 SILC_LOG_DEBUG(("Extended request"));
1278 req = silc_calloc(1, sizeof(*req));
1281 req->id = client->id++;
1282 req->type = SILC_SFTP_WRITE;
1283 req->extended = callback;
1284 req->context = context;
1285 silc_list_add(client->requests, req);
1287 len = 4 + 4 + strlen(request) + data_len;
1289 silc_sftp_send_packet(client, req->type, len,
1290 SILC_STR_UI_INT(req->id),
1291 SILC_STR_UI_INT(strlen(request)),
1292 SILC_STR_UI32_STRING(request),
1293 SILC_STR_UI_XNSTRING(data, data_len),