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[63488];
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"));
409 sftp = silc_calloc(1, sizeof(*sftp));
412 sftp->stream = stream;
413 sftp->version = version_cb;
414 sftp->error = error_cb;
415 sftp->context = context;
416 sftp->schedule = schedule;
417 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
419 /* We handle the stream now */
420 silc_stream_set_notifier(stream, schedule, silc_sftp_client_io, sftp);
422 /* Send the SFTP session initialization to the server */
423 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
424 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
427 return (SilcSFTP)sftp;
430 /* Shutdown's the SFTP client. The caller is responsible of closing
431 the associated socket connection. The SFTP context is freed and is
432 invalid after this function returns. */
434 void silc_sftp_client_shutdown(SilcSFTP context)
436 SilcSFTPClient sftp = (SilcSFTPClient)context;
438 silc_stream_set_notifier(sftp->stream, sftp->schedule, NULL, NULL);
440 silc_buffer_free(sftp->packet);
444 /* Function that is called to process the incmoing SFTP packet. */
446 void silc_sftp_client_receive_process(SilcSFTP context, SilcBuffer buffer)
448 SilcSFTPClient sftp = (SilcSFTPClient)context;
451 unsigned char *payload = NULL;
452 SilcUInt32 payload_len;
454 SilcBufferStruct buf;
457 SILC_LOG_DEBUG(("Process SFTP packet"));
459 /* Parse the packet */
460 type = silc_sftp_packet_decode(buffer, &payload, &payload_len);
464 silc_buffer_set(&buf, payload, payload_len);
469 unsigned char *data = NULL;
470 SilcUInt32 data_len = 0;
472 SILC_LOG_DEBUG(("Data packet"));
474 ret = silc_buffer_unformat(&buf,
475 SILC_STR_UI_INT(&id),
476 SILC_STR_UI32_NSTRING(&data, &data_len),
482 req = silc_sftp_find_request(sftp, id);
486 /* Call the callback */
487 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
492 case SILC_SFTP_VERSION:
494 SilcSFTPVersion version;
496 SILC_LOG_DEBUG(("Version packet"));
498 ret = silc_buffer_unformat(&buf,
499 SILC_STR_UI_INT(&version),
502 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
507 /* Call the callback */
508 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
513 case SILC_SFTP_STATUS:
516 char *message = NULL, *language_tag = NULL;
518 SILC_LOG_DEBUG(("Status packet"));
520 ret = silc_buffer_unformat(&buf,
521 SILC_STR_UI_INT(&id),
522 SILC_STR_UI_INT(&status),
527 if (status != SILC_SFTP_STATUS_OK) {
528 silc_buffer_pull(&buf, 8);
529 ret = silc_buffer_unformat(&buf,
530 SILC_STR_UI32_STRING_ALLOC(&message),
531 SILC_STR_UI32_STRING_ALLOC(&language_tag),
536 silc_buffer_push(&buf, 8);
540 req = silc_sftp_find_request(sftp, id);
543 silc_free(language_tag);
547 /* Call the callback */
548 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
551 silc_free(language_tag);
555 case SILC_SFTP_HANDLE:
557 unsigned char *handle = NULL;
558 SilcUInt32 handle_len;
560 SILC_LOG_DEBUG(("Handle packet"));
562 ret = silc_buffer_unformat(&buf,
563 SILC_STR_UI_INT(&id),
564 SILC_STR_UI32_NSTRING(&handle,
571 req = silc_sftp_find_request(sftp, id);
575 /* Call the callback */
576 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
584 SilcSFTPName name = NULL;
586 SILC_LOG_DEBUG(("Name packet"));
588 ret = silc_buffer_unformat(&buf,
589 SILC_STR_UI_INT(&id),
590 SILC_STR_UI_INT(&count),
596 req = silc_sftp_find_request(sftp, id);
600 silc_buffer_pull(&buf, 8);
601 name = silc_sftp_name_decode(count, &buf);
604 silc_buffer_push(&buf, 8);
606 /* Call the callback */
607 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
608 silc_sftp_name_free(name);
612 case SILC_SFTP_ATTRS:
614 SilcSFTPAttributes attr = NULL;
616 SilcBufferStruct tmpbuf;
618 SILC_LOG_DEBUG(("Attributes packet"));
621 silc_buffer_unformat(&buf,
622 SILC_STR_UI_INT(&id),
623 SILC_STR_DATA(&data, silc_buffer_len(&buf) - 4),
629 req = silc_sftp_find_request(sftp, id);
633 silc_buffer_set(&tmpbuf, data, silc_buffer_len(&buf) - 4);
634 attr = silc_sftp_attr_decode(&tmpbuf);
638 /* Call the callback */
639 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
643 case SILC_SFTP_EXTENDED_REPLY:
645 unsigned char *data = NULL;
647 SILC_LOG_DEBUG(("Extended reply packet"));
649 ret = silc_buffer_unformat(&buf,
650 SILC_STR_UI_INT(&id),
652 silc_buffer_len(&buf) - 4),
658 req = silc_sftp_find_request(sftp, id);
662 /* Call the callback */
663 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
664 data, silc_buffer_len(&buf) - 4);
673 void silc_sftp_open(SilcSFTP sftp,
674 const char *filename,
675 SilcSFTPFileOperation pflags,
676 SilcSFTPAttributes attrs,
677 SilcSFTPHandleCallback callback,
680 SilcSFTPClient client = (SilcSFTPClient)sftp;
682 SilcBuffer attrs_buf;
685 SILC_LOG_DEBUG(("Open request"));
687 req = silc_calloc(1, sizeof(*req));
690 req->id = client->id++;
691 req->type = SILC_SFTP_OPEN;
692 req->handle = callback;
693 req->context = context;
694 silc_list_add(client->requests, req);
696 attrs_buf = silc_sftp_attr_encode(attrs);
699 len = 4 + 4 + strlen(filename) + 4 + silc_buffer_len(attrs_buf);
701 silc_sftp_send_packet(client, req->type, len,
702 SILC_STR_UI_INT(req->id),
703 SILC_STR_UI_INT(strlen(filename)),
704 SILC_STR_UI32_STRING(filename),
705 SILC_STR_UI_INT(pflags),
706 SILC_STR_UI_XNSTRING(attrs_buf->data,
707 silc_buffer_len(attrs_buf)),
710 silc_buffer_free(attrs_buf);
713 void silc_sftp_close(SilcSFTP sftp,
714 SilcSFTPHandle handle,
715 SilcSFTPStatusCallback callback,
718 SilcSFTPClient client = (SilcSFTPClient)sftp;
721 const unsigned char *hdata;
722 SilcUInt32 hdata_len;
724 SILC_LOG_DEBUG(("Close request"));
726 req = silc_calloc(1, sizeof(*req));
729 req->id = client->id++;
730 req->type = SILC_SFTP_CLOSE;
731 req->status = callback;
732 req->context = context;
733 silc_list_add(client->requests, req);
735 silc_sftp_handle_get(handle, &hdata, &hdata_len);
736 len = 4 + 4 + hdata_len;
738 silc_sftp_send_packet(client, req->type, len,
739 SILC_STR_UI_INT(req->id),
740 SILC_STR_UI_INT(hdata_len),
741 SILC_STR_UI_XNSTRING(hdata, hdata_len),
743 silc_sftp_handle_delete(handle);
746 void silc_sftp_read(SilcSFTP sftp,
747 SilcSFTPHandle handle,
750 SilcSFTPDataCallback callback,
753 SilcSFTPClient client = (SilcSFTPClient)sftp;
756 const unsigned char *hdata;
757 SilcUInt32 hdata_len;
759 SILC_LOG_DEBUG(("Read request"));
761 req = silc_calloc(1, sizeof(*req));
764 req->id = client->id++;
765 req->type = SILC_SFTP_READ;
766 req->data = callback;
767 req->context = context;
768 silc_list_add(client->requests, req);
770 silc_sftp_handle_get(handle, &hdata, &hdata_len);
771 len2 = 4 + 4 + hdata_len + 8 + 4;
773 silc_sftp_send_packet(client, req->type, len2,
774 SILC_STR_UI_INT(req->id),
775 SILC_STR_UI_INT(hdata_len),
776 SILC_STR_UI_XNSTRING(hdata, hdata_len),
777 SILC_STR_UI_INT64(offset),
778 SILC_STR_UI_INT(len),
782 void silc_sftp_write(SilcSFTP sftp,
783 SilcSFTPHandle handle,
785 const unsigned char *data,
787 SilcSFTPStatusCallback callback,
790 SilcSFTPClient client = (SilcSFTPClient)sftp;
793 const unsigned char *hdata;
794 SilcUInt32 hdata_len;
796 SILC_LOG_DEBUG(("Write request"));
798 req = silc_calloc(1, sizeof(*req));
801 req->id = client->id++;
802 req->type = SILC_SFTP_WRITE;
803 req->status = callback;
804 req->context = context;
805 silc_list_add(client->requests, req);
807 silc_sftp_handle_get(handle, &hdata, &hdata_len);
808 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
810 silc_sftp_send_packet(client, req->type, len,
811 SILC_STR_UI_INT(req->id),
812 SILC_STR_UI_INT(hdata_len),
813 SILC_STR_UI_XNSTRING(hdata, hdata_len),
814 SILC_STR_UI_INT64(offset),
815 SILC_STR_UI_INT(data_len),
816 SILC_STR_UI_XNSTRING(data, data_len),
820 void silc_sftp_remove(SilcSFTP sftp,
821 const char *filename,
822 SilcSFTPStatusCallback callback,
825 SilcSFTPClient client = (SilcSFTPClient)sftp;
829 SILC_LOG_DEBUG(("Remove request"));
831 req = silc_calloc(1, sizeof(*req));
834 req->id = client->id++;
835 req->type = SILC_SFTP_REMOVE;
836 req->status = callback;
837 req->context = context;
838 silc_list_add(client->requests, req);
840 len = 4 + 4 + strlen(filename);
842 silc_sftp_send_packet(client, req->type, len,
843 SILC_STR_UI_INT(req->id),
844 SILC_STR_UI_INT(strlen(filename)),
845 SILC_STR_UI32_STRING(filename),
849 void silc_sftp_rename(SilcSFTP sftp,
852 SilcSFTPStatusCallback callback,
855 SilcSFTPClient client = (SilcSFTPClient)sftp;
859 SILC_LOG_DEBUG(("Rename request"));
861 req = silc_calloc(1, sizeof(*req));
864 req->id = client->id++;
865 req->type = SILC_SFTP_RENAME;
866 req->status = callback;
867 req->context = context;
868 silc_list_add(client->requests, req);
870 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
872 silc_sftp_send_packet(client, req->type, len,
873 SILC_STR_UI_INT(req->id),
874 SILC_STR_UI_INT(strlen(oldname)),
875 SILC_STR_UI32_STRING(oldname),
876 SILC_STR_UI_INT(strlen(newname)),
877 SILC_STR_UI32_STRING(newname),
881 void silc_sftp_mkdir(SilcSFTP sftp,
883 SilcSFTPAttributes attrs,
884 SilcSFTPStatusCallback callback,
887 SilcSFTPClient client = (SilcSFTPClient)sftp;
890 SilcBuffer attrs_buf;
892 SILC_LOG_DEBUG(("Mkdir request"));
894 req = silc_calloc(1, sizeof(*req));
897 req->id = client->id++;
898 req->type = SILC_SFTP_MKDIR;
899 req->status = callback;
900 req->context = context;
901 silc_list_add(client->requests, req);
903 attrs_buf = silc_sftp_attr_encode(attrs);
906 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
908 silc_sftp_send_packet(client, req->type, len,
909 SILC_STR_UI_INT(req->id),
910 SILC_STR_UI_INT(strlen(path)),
911 SILC_STR_UI32_STRING(path),
912 SILC_STR_UI_XNSTRING(attrs_buf->data,
913 silc_buffer_len(attrs_buf)),
916 silc_buffer_free(attrs_buf);
919 void silc_sftp_rmdir(SilcSFTP sftp,
921 SilcSFTPStatusCallback callback,
924 SilcSFTPClient client = (SilcSFTPClient)sftp;
928 SILC_LOG_DEBUG(("Rmdir request"));
930 req = silc_calloc(1, sizeof(*req));
933 req->id = client->id++;
934 req->type = SILC_SFTP_RMDIR;
935 req->status = callback;
936 req->context = context;
937 silc_list_add(client->requests, req);
939 len = 4 + 4 + strlen(path);
941 silc_sftp_send_packet(client, req->type, len,
942 SILC_STR_UI_INT(req->id),
943 SILC_STR_UI_INT(strlen(path)),
944 SILC_STR_UI32_STRING(path),
948 void silc_sftp_opendir(SilcSFTP sftp,
950 SilcSFTPHandleCallback callback,
953 SilcSFTPClient client = (SilcSFTPClient)sftp;
957 SILC_LOG_DEBUG(("Opendir request"));
959 req = silc_calloc(1, sizeof(*req));
962 req->id = client->id++;
963 req->type = SILC_SFTP_OPENDIR;
964 req->handle = callback;
965 req->context = context;
966 silc_list_add(client->requests, req);
968 len = 4 + 4 + strlen(path);
970 silc_sftp_send_packet(client, req->type, len,
971 SILC_STR_UI_INT(req->id),
972 SILC_STR_UI_INT(strlen(path)),
973 SILC_STR_UI32_STRING(path),
977 void silc_sftp_readdir(SilcSFTP sftp,
978 SilcSFTPHandle handle,
979 SilcSFTPNameCallback callback,
982 SilcSFTPClient client = (SilcSFTPClient)sftp;
985 const unsigned char *hdata;
986 SilcUInt32 hdata_len;
988 SILC_LOG_DEBUG(("Readdir request"));
990 req = silc_calloc(1, sizeof(*req));
993 req->id = client->id++;
994 req->type = SILC_SFTP_READDIR;
995 req->name = callback;
996 req->context = context;
997 silc_list_add(client->requests, req);
999 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1000 len = 4 + 4 + hdata_len;
1002 silc_sftp_send_packet(client, req->type, len,
1003 SILC_STR_UI_INT(req->id),
1004 SILC_STR_UI_INT(hdata_len),
1005 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1009 void silc_sftp_stat(SilcSFTP sftp,
1011 SilcSFTPAttrCallback callback,
1014 SilcSFTPClient client = (SilcSFTPClient)sftp;
1015 SilcSFTPRequest req;
1018 SILC_LOG_DEBUG(("Stat request"));
1020 req = silc_calloc(1, sizeof(*req));
1023 req->id = client->id++;
1024 req->type = SILC_SFTP_STAT;
1025 req->attr = callback;
1026 req->context = context;
1027 silc_list_add(client->requests, req);
1029 len = 4 + 4 + strlen(path);
1031 silc_sftp_send_packet(client, req->type, len,
1032 SILC_STR_UI_INT(req->id),
1033 SILC_STR_UI_INT(strlen(path)),
1034 SILC_STR_UI32_STRING(path),
1038 void silc_sftp_lstat(SilcSFTP sftp,
1040 SilcSFTPAttrCallback callback,
1043 SilcSFTPClient client = (SilcSFTPClient)sftp;
1044 SilcSFTPRequest req;
1047 SILC_LOG_DEBUG(("Lstat request"));
1049 req = silc_calloc(1, sizeof(*req));
1052 req->id = client->id++;
1053 req->type = SILC_SFTP_LSTAT;
1054 req->attr = callback;
1055 req->context = context;
1056 silc_list_add(client->requests, req);
1058 len = 4 + 4 + strlen(path);
1060 silc_sftp_send_packet(client, req->type, len,
1061 SILC_STR_UI_INT(req->id),
1062 SILC_STR_UI_INT(strlen(path)),
1063 SILC_STR_UI32_STRING(path),
1067 void silc_sftp_fstat(SilcSFTP sftp,
1068 SilcSFTPHandle handle,
1069 SilcSFTPAttrCallback callback,
1072 SilcSFTPClient client = (SilcSFTPClient)sftp;
1073 SilcSFTPRequest req;
1075 const unsigned char *hdata;
1076 SilcUInt32 hdata_len;
1078 SILC_LOG_DEBUG(("Fstat request"));
1080 req = silc_calloc(1, sizeof(*req));
1083 req->id = client->id++;
1084 req->type = SILC_SFTP_FSTAT;
1085 req->attr = callback;
1086 req->context = context;
1087 silc_list_add(client->requests, req);
1089 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1090 len = 4 + 4 + hdata_len;
1092 silc_sftp_send_packet(client, req->type, len,
1093 SILC_STR_UI_INT(req->id),
1094 SILC_STR_UI_INT(hdata_len),
1095 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1099 void silc_sftp_setstat(SilcSFTP sftp,
1101 SilcSFTPAttributes attrs,
1102 SilcSFTPStatusCallback callback,
1105 SilcSFTPClient client = (SilcSFTPClient)sftp;
1106 SilcSFTPRequest req;
1108 SilcBuffer attrs_buf;
1110 SILC_LOG_DEBUG(("Setstat request"));
1112 req = silc_calloc(1, sizeof(*req));
1115 req->id = client->id++;
1116 req->type = SILC_SFTP_SETSTAT;
1117 req->status = callback;
1118 req->context = context;
1119 silc_list_add(client->requests, req);
1121 attrs_buf = silc_sftp_attr_encode(attrs);
1124 len = 4 + 4 + strlen(path) + silc_buffer_len(attrs_buf);
1126 silc_sftp_send_packet(client, req->type, len,
1127 SILC_STR_UI_INT(req->id),
1128 SILC_STR_UI_INT(strlen(path)),
1129 SILC_STR_UI32_STRING(path),
1130 SILC_STR_UI_XNSTRING(attrs_buf->data,
1131 silc_buffer_len(attrs_buf)),
1134 silc_buffer_free(attrs_buf);
1137 void silc_sftp_fsetstat(SilcSFTP sftp,
1138 SilcSFTPHandle handle,
1139 SilcSFTPAttributes attrs,
1140 SilcSFTPStatusCallback callback,
1143 SilcSFTPClient client = (SilcSFTPClient)sftp;
1144 SilcSFTPRequest req;
1146 SilcBuffer attrs_buf;
1147 const unsigned char *hdata;
1148 SilcUInt32 hdata_len;
1150 SILC_LOG_DEBUG(("Fsetstat request"));
1152 req = silc_calloc(1, sizeof(*req));
1155 req->id = client->id++;
1156 req->type = SILC_SFTP_FSETSTAT;
1157 req->status = callback;
1158 req->context = context;
1159 silc_list_add(client->requests, req);
1161 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1162 attrs_buf = silc_sftp_attr_encode(attrs);
1165 len = 4 + 4 + hdata_len + silc_buffer_len(attrs_buf);
1167 silc_sftp_send_packet(client, req->type, len,
1168 SILC_STR_UI_INT(req->id),
1169 SILC_STR_UI_INT(hdata_len),
1170 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1171 SILC_STR_UI_XNSTRING(attrs_buf->data,
1172 silc_buffer_len(attrs_buf)),
1175 silc_buffer_free(attrs_buf);
1178 void silc_sftp_readlink(SilcSFTP sftp,
1180 SilcSFTPNameCallback callback,
1183 SilcSFTPClient client = (SilcSFTPClient)sftp;
1184 SilcSFTPRequest req;
1187 SILC_LOG_DEBUG(("Readlink request"));
1189 req = silc_calloc(1, sizeof(*req));
1192 req->id = client->id++;
1193 req->type = SILC_SFTP_READLINK;
1194 req->name = callback;
1195 req->context = context;
1196 silc_list_add(client->requests, req);
1198 len = 4 + 4 + strlen(path);
1200 silc_sftp_send_packet(client, req->type, len,
1201 SILC_STR_UI_INT(req->id),
1202 SILC_STR_UI_INT(strlen(path)),
1203 SILC_STR_UI32_STRING(path),
1207 void silc_sftp_symlink(SilcSFTP sftp,
1208 const char *linkpath,
1209 const char *targetpath,
1210 SilcSFTPStatusCallback callback,
1213 SilcSFTPClient client = (SilcSFTPClient)sftp;
1214 SilcSFTPRequest req;
1217 SILC_LOG_DEBUG(("Symlink request"));
1219 req = silc_calloc(1, sizeof(*req));
1222 req->id = client->id++;
1223 req->type = SILC_SFTP_SYMLINK;
1224 req->status = callback;
1225 req->context = context;
1226 silc_list_add(client->requests, req);
1228 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1230 silc_sftp_send_packet(client, req->type, len,
1231 SILC_STR_UI_INT(req->id),
1232 SILC_STR_UI_INT(strlen(linkpath)),
1233 SILC_STR_UI32_STRING(linkpath),
1234 SILC_STR_UI_INT(strlen(targetpath)),
1235 SILC_STR_UI32_STRING(targetpath),
1239 void silc_sftp_realpath(SilcSFTP sftp,
1241 SilcSFTPNameCallback callback,
1244 SilcSFTPClient client = (SilcSFTPClient)sftp;
1245 SilcSFTPRequest req;
1248 SILC_LOG_DEBUG(("Realpath request"));
1250 req = silc_calloc(1, sizeof(*req));
1253 req->id = client->id++;
1254 req->type = SILC_SFTP_REALPATH;
1255 req->name = callback;
1256 req->context = context;
1257 silc_list_add(client->requests, req);
1259 len = 4 + 4 + strlen(path);
1261 silc_sftp_send_packet(client, req->type, len,
1262 SILC_STR_UI_INT(req->id),
1263 SILC_STR_UI_INT(strlen(path)),
1264 SILC_STR_UI32_STRING(path),
1268 void silc_sftp_extended(SilcSFTP sftp,
1269 const char *request,
1270 const unsigned char *data,
1271 SilcUInt32 data_len,
1272 SilcSFTPExtendedCallback callback,
1275 SilcSFTPClient client = (SilcSFTPClient)sftp;
1276 SilcSFTPRequest req;
1279 SILC_LOG_DEBUG(("Extended request"));
1281 req = silc_calloc(1, sizeof(*req));
1284 req->id = client->id++;
1285 req->type = SILC_SFTP_WRITE;
1286 req->extended = callback;
1287 req->context = context;
1288 silc_list_add(client->requests, req);
1290 len = 4 + 4 + strlen(request) + data_len;
1292 silc_sftp_send_packet(client, req->type, len,
1293 SILC_STR_UI_INT(req->id),
1294 SILC_STR_UI_INT(strlen(request)),
1295 SILC_STR_UI32_STRING(request),
1296 SILC_STR_UI_XNSTRING(data, data_len),