5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 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.
21 #include "silcincludes.h"
23 #include "sftp_util.h"
25 /* Request context. Every request will allocate this context and set
26 the correct callback function according the `type' field. */
27 typedef struct SilcSFTPRequestStruct {
30 SilcSFTPStatusCallback status;
31 SilcSFTPHandleCallback handle;
32 SilcSFTPDataCallback data;
33 SilcSFTPNameCallback name;
34 SilcSFTPAttrCallback attr;
35 SilcSFTPExtendedCallback extended;
37 struct SilcSFTPRequestStruct *next;
40 /* SFTP client context */
42 SilcSFTPSendPacketCallback send_packet;
44 SilcSFTPVersionCallback version;
45 void *version_context;
52 struct SilcSFTPHandleStruct {
57 /* Creates SilcSFTPHandle and returns pointer to it. The caller must free
60 static SilcSFTPHandle silc_sftp_handle_create(unsigned char *data,
63 SilcSFTPHandle handle;
65 handle = silc_calloc(1, sizeof(*handle));
68 handle->data = silc_calloc(data_len, sizeof(*handle->data));
71 memcpy(handle->data, data, data_len);
72 handle->data_len = data_len;
77 /* Deletes the handle indicated by the `handle'. */
79 static void silc_sftp_handle_delete(SilcSFTPHandle handle)
81 silc_free(handle->data);
85 /* Returns the handle data of the `handle' to the `data' pointer. */
87 static void silc_sftp_handle_get(SilcSFTPHandle handle,
88 const unsigned char **data,
91 *data = (const unsigned char *)handle->data;
92 *data_len = handle->data_len;
95 /* General routine to send SFTP packet to the SFTP server. */
97 static void silc_sftp_send_packet(SilcSFTPClient sftp,
105 tmp = silc_sftp_packet_encode_vp(type, sftp->packet, len, vp);
111 SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
114 /* Send the packet */
115 (*sftp->send_packet)(sftp->packet, sftp->send_context);
118 sftp->packet->data = sftp->packet->tail = sftp->packet->head;
119 sftp->packet->len = 0;
122 /* Finds request by request ID. */
124 static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, SilcUInt32 id)
128 SILC_LOG_DEBUG(("Finding request ID: %d", id));
130 silc_list_start(sftp->requests);
131 while ((req = silc_list_get(sftp->requests)) != SILC_LIST_END) {
136 SILC_LOG_DEBUG(("Unknown request ID"));
141 /* Function used to call the request callback indicated by the `req'. The
142 `status' will be sent to the callback function as the status of the
143 operation. The variable argument list includes the status and req->type
146 static void silc_sftp_call_request(SilcSFTPClient sftp,
149 SilcSFTPStatus status, ...)
153 SILC_LOG_DEBUG(("Start"));
155 va_start(vp, status);
164 if (status != SILC_SFTP_STATUS_OK) {
166 (*req->data)((SilcSFTP)sftp, status, NULL, 0, req->context);
170 data = (unsigned char *)va_arg(vp, unsigned char *);
171 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
174 (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
175 data_len, req->context);
180 case SILC_SFTP_OPENDIR:
182 /* Handle returned */
183 SilcSFTPHandle handle;
184 unsigned char *hdata;
185 SilcUInt32 hdata_len;
187 if (status != SILC_SFTP_STATUS_OK) {
189 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
193 hdata = (unsigned char *)va_arg(vp, unsigned char *);
194 hdata_len = (SilcUInt32)va_arg(vp, SilcUInt32);
195 handle = silc_sftp_handle_create(hdata, hdata_len);
198 (*req->handle)((SilcSFTP)sftp, status, NULL, req->context);
203 (*req->handle)((SilcSFTP)sftp, status, handle, req->context);
207 case SILC_SFTP_CLOSE:
208 case SILC_SFTP_WRITE:
209 case SILC_SFTP_REMOVE:
210 case SILC_SFTP_RENAME:
211 case SILC_SFTP_MKDIR:
212 case SILC_SFTP_RMDIR:
213 case SILC_SFTP_SETSTAT:
214 case SILC_SFTP_FSETSTAT:
215 case SILC_SFTP_SYMLINK:
217 /* Status returned */
218 char *message, *language_tag;
220 message = (char *)va_arg(vp, char *);
221 language_tag = (char *)va_arg(vp, char *);
224 (*req->status)((SilcSFTP)sftp, status, (const char *)message,
225 (const char *)language_tag, req->context);
230 case SILC_SFTP_LSTAT:
231 case SILC_SFTP_FSTAT:
233 /* Attributes returned */
234 SilcSFTPAttributes attr;
236 if (status != SILC_SFTP_STATUS_OK) {
238 (*req->attr)((SilcSFTP)sftp, status, NULL, req->context);
242 attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
245 (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
250 case SILC_SFTP_READDIR:
251 case SILC_SFTP_REALPATH:
252 case SILC_SFTP_READLINK:
254 /* Name(s) returned */
257 if (status != SILC_SFTP_STATUS_OK) {
259 (*req->name)((SilcSFTP)sftp, status, NULL, req->context);
263 name = (SilcSFTPName)va_arg(vp, SilcSFTPName);
266 (*req->name)((SilcSFTP)sftp, status, name, req->context);
270 case SILC_SFTP_EXTENDED:
272 /* Extended reply returned */
276 if (status != SILC_SFTP_STATUS_OK) {
278 (*req->extended)((SilcSFTP)sftp, status, NULL, 0, req->context);
282 data = (unsigned char *)va_arg(vp, unsigned char *);
283 data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
286 (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
287 data_len, req->context);
295 /* Remove this request */
296 silc_list_del(sftp->requests, req);
302 /* Starts SFTP client and returns context for it. The version callback
303 indicated by the `callback' will be called after the SFTP session has
304 been started and server has returned the version of the protocol. The
305 SFTP client context is returned in the callback too. This returns
306 allocated SFTP client context or NULL on error. */
308 SilcSFTP silc_sftp_client_start(SilcSFTPSendPacketCallback send_packet,
310 SilcSFTPVersionCallback callback,
318 sftp = silc_calloc(1, sizeof(*sftp));
321 sftp->send_packet = send_packet;
322 sftp->send_context = send_context;
323 sftp->version = callback;
324 sftp->version_context = context;
325 silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
327 /* Send the SFTP session initialization to the server */
328 silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
329 SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
332 return (SilcSFTP)sftp;
335 /* Shutdown's the SFTP client. The caller is responsible of closing
336 the associated socket connection. The SFTP context is freed and is
337 invalid after this function returns. */
339 void silc_sftp_client_shutdown(SilcSFTP context)
341 SilcSFTPClient sftp = (SilcSFTPClient)context;
344 silc_buffer_free(sftp->packet);
348 /* Function that is called to process the incmoing SFTP packet. */
349 /* XXX Some day this will go away and we have automatic receive callbacks
350 for SilcSocketConnection API or SilcPacketContext API. */
352 void silc_sftp_client_receive_process(SilcSFTP context,
353 SilcSocketConnection sock,
354 SilcPacketContext *packet)
356 SilcSFTPClient sftp = (SilcSFTPClient)context;
359 const unsigned char *payload = NULL;
360 SilcUInt32 payload_len;
362 SilcBufferStruct buf;
365 SILC_LOG_DEBUG(("Start"));
367 /* Parse the packet */
368 type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
373 silc_buffer_set(&buf, (unsigned char *)payload, payload_len);
376 case SILC_SFTP_VERSION:
378 SilcSFTPVersion version;
380 SILC_LOG_DEBUG(("Version packet"));
382 ret = silc_buffer_unformat(&buf,
383 SILC_STR_UI_INT(&version),
386 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
387 sftp->version_context);
391 /* Call the callback */
392 (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
393 sftp->version_context);
397 case SILC_SFTP_STATUS:
400 char *message = NULL, *language_tag = NULL;
402 SILC_LOG_DEBUG(("Status packet"));
404 ret = silc_buffer_unformat(&buf,
405 SILC_STR_UI_INT(&id),
406 SILC_STR_UI_INT(&status),
411 if (status != SILC_SFTP_STATUS_OK) {
412 silc_buffer_pull(&buf, 8);
413 ret = silc_buffer_unformat(&buf,
414 SILC_STR_UI32_STRING_ALLOC(&message),
415 SILC_STR_UI32_STRING_ALLOC(&language_tag),
420 silc_buffer_push(&buf, 8);
424 req = silc_sftp_find_request(sftp, id);
427 silc_free(language_tag);
431 /* Call the callback */
432 silc_sftp_call_request(sftp, req, type, status, message, language_tag);
435 silc_free(language_tag);
439 case SILC_SFTP_HANDLE:
441 unsigned char *handle = NULL;
442 SilcUInt32 handle_len;
444 SILC_LOG_DEBUG(("Handle packet"));
446 ret = silc_buffer_unformat(&buf,
447 SILC_STR_UI_INT(&id),
448 SILC_STR_UI32_NSTRING(&handle,
455 req = silc_sftp_find_request(sftp, id);
459 /* Call the callback */
460 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
467 unsigned char *data = NULL;
468 SilcUInt32 data_len = 0;
470 SILC_LOG_DEBUG(("Data packet"));
472 ret = silc_buffer_unformat(&buf,
473 SILC_STR_UI_INT(&id),
474 SILC_STR_UI32_NSTRING(&data, &data_len),
480 req = silc_sftp_find_request(sftp, id);
484 /* Call the callback */
485 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
493 SilcSFTPName name = NULL;
495 SILC_LOG_DEBUG(("Name packet"));
497 ret = silc_buffer_unformat(&buf,
498 SILC_STR_UI_INT(&id),
499 SILC_STR_UI_INT(&count),
505 req = silc_sftp_find_request(sftp, id);
509 silc_buffer_pull(&buf, 8);
510 name = silc_sftp_name_decode(count, &buf);
513 silc_buffer_push(&buf, 8);
515 /* Call the callback */
516 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, name);
517 silc_sftp_name_free(name);
521 case SILC_SFTP_ATTRS:
523 SilcSFTPAttributes attr = NULL;
525 SilcBufferStruct tmpbuf;
527 SILC_LOG_DEBUG(("Attributes packet"));
529 ret = silc_buffer_unformat(&buf,
530 SILC_STR_UI_INT(&id),
531 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
537 req = silc_sftp_find_request(sftp, id);
541 silc_buffer_set(&tmpbuf, data, buf.len - 4);
542 attr = silc_sftp_attr_decode(&tmpbuf);
546 /* Call the callback */
547 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, attr);
551 case SILC_SFTP_EXTENDED_REPLY:
553 unsigned char *data = NULL;
555 SILC_LOG_DEBUG(("Extended reply packet"));
557 ret = silc_buffer_unformat(&buf,
558 SILC_STR_UI_INT(&id),
559 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
565 req = silc_sftp_find_request(sftp, id);
569 /* Call the callback */
570 silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
580 void silc_sftp_open(SilcSFTP sftp,
581 const char *filename,
582 SilcSFTPFileOperation pflags,
583 SilcSFTPAttributes attrs,
584 SilcSFTPHandleCallback callback,
587 SilcSFTPClient client = (SilcSFTPClient)sftp;
589 SilcBuffer attrs_buf;
592 SILC_LOG_DEBUG(("Open request"));
594 req = silc_calloc(1, sizeof(*req));
597 req->id = client->id++;
598 req->type = SILC_SFTP_OPEN;
599 req->handle = callback;
600 req->context = context;
601 silc_list_add(client->requests, req);
603 attrs_buf = silc_sftp_attr_encode(attrs);
606 len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
608 silc_sftp_send_packet(client, req->type, len,
609 SILC_STR_UI_INT(req->id),
610 SILC_STR_UI_INT(strlen(filename)),
611 SILC_STR_UI32_STRING(filename),
612 SILC_STR_UI_INT(pflags),
613 SILC_STR_UI_XNSTRING(attrs_buf->data,
617 silc_buffer_free(attrs_buf);
620 void silc_sftp_close(SilcSFTP sftp,
621 SilcSFTPHandle handle,
622 SilcSFTPStatusCallback callback,
625 SilcSFTPClient client = (SilcSFTPClient)sftp;
628 const unsigned char *hdata;
629 SilcUInt32 hdata_len;
631 SILC_LOG_DEBUG(("Close request"));
633 req = silc_calloc(1, sizeof(*req));
636 req->id = client->id++;
637 req->type = SILC_SFTP_CLOSE;
638 req->status = callback;
639 req->context = context;
640 silc_list_add(client->requests, req);
642 silc_sftp_handle_get(handle, &hdata, &hdata_len);
643 len = 4 + 4 + hdata_len;
645 silc_sftp_send_packet(client, req->type, len,
646 SILC_STR_UI_INT(req->id),
647 SILC_STR_UI_INT(hdata_len),
648 SILC_STR_UI_XNSTRING(hdata, hdata_len),
652 void silc_sftp_read(SilcSFTP sftp,
653 SilcSFTPHandle handle,
656 SilcSFTPDataCallback callback,
659 SilcSFTPClient client = (SilcSFTPClient)sftp;
662 const unsigned char *hdata;
663 SilcUInt32 hdata_len;
665 SILC_LOG_DEBUG(("Read request"));
667 req = silc_calloc(1, sizeof(*req));
670 req->id = client->id++;
671 req->type = SILC_SFTP_READ;
672 req->data = callback;
673 req->context = context;
674 silc_list_add(client->requests, req);
676 silc_sftp_handle_get(handle, &hdata, &hdata_len);
677 len2 = 4 + 4 + hdata_len + 8 + 4;
679 silc_sftp_send_packet(client, req->type, len2,
680 SILC_STR_UI_INT(req->id),
681 SILC_STR_UI_INT(hdata_len),
682 SILC_STR_UI_XNSTRING(hdata, hdata_len),
683 SILC_STR_UI_INT64(offset),
684 SILC_STR_UI_INT(len),
688 void silc_sftp_write(SilcSFTP sftp,
689 SilcSFTPHandle handle,
691 const unsigned char *data,
693 SilcSFTPStatusCallback callback,
696 SilcSFTPClient client = (SilcSFTPClient)sftp;
699 const unsigned char *hdata;
700 SilcUInt32 hdata_len;
702 SILC_LOG_DEBUG(("Write request"));
704 req = silc_calloc(1, sizeof(*req));
707 req->id = client->id++;
708 req->type = SILC_SFTP_WRITE;
709 req->status = callback;
710 req->context = context;
711 silc_list_add(client->requests, req);
713 silc_sftp_handle_get(handle, &hdata, &hdata_len);
714 len = 4 + 4 + hdata_len + 8 + 4 + data_len;
716 silc_sftp_send_packet(client, req->type, len,
717 SILC_STR_UI_INT(req->id),
718 SILC_STR_UI_INT(hdata_len),
719 SILC_STR_UI_XNSTRING(hdata, hdata_len),
720 SILC_STR_UI_INT64(offset),
721 SILC_STR_UI_INT(data_len),
722 SILC_STR_UI_XNSTRING(data, data_len),
726 void silc_sftp_remove(SilcSFTP sftp,
727 const char *filename,
728 SilcSFTPStatusCallback callback,
731 SilcSFTPClient client = (SilcSFTPClient)sftp;
735 SILC_LOG_DEBUG(("Remove request"));
737 req = silc_calloc(1, sizeof(*req));
740 req->id = client->id++;
741 req->type = SILC_SFTP_REMOVE;
742 req->status = callback;
743 req->context = context;
744 silc_list_add(client->requests, req);
746 len = 4 + 4 + strlen(filename);
748 silc_sftp_send_packet(client, req->type, len,
749 SILC_STR_UI_INT(req->id),
750 SILC_STR_UI_INT(strlen(filename)),
751 SILC_STR_UI32_STRING(filename),
755 void silc_sftp_rename(SilcSFTP sftp,
758 SilcSFTPStatusCallback callback,
761 SilcSFTPClient client = (SilcSFTPClient)sftp;
765 SILC_LOG_DEBUG(("Rename request"));
767 req = silc_calloc(1, sizeof(*req));
770 req->id = client->id++;
771 req->type = SILC_SFTP_RENAME;
772 req->status = callback;
773 req->context = context;
774 silc_list_add(client->requests, req);
776 len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
778 silc_sftp_send_packet(client, req->type, len,
779 SILC_STR_UI_INT(req->id),
780 SILC_STR_UI_INT(strlen(oldname)),
781 SILC_STR_UI32_STRING(oldname),
782 SILC_STR_UI_INT(strlen(newname)),
783 SILC_STR_UI32_STRING(newname),
787 void silc_sftp_mkdir(SilcSFTP sftp,
789 SilcSFTPAttributes attrs,
790 SilcSFTPStatusCallback callback,
793 SilcSFTPClient client = (SilcSFTPClient)sftp;
796 SilcBuffer attrs_buf;
798 SILC_LOG_DEBUG(("Mkdir request"));
800 req = silc_calloc(1, sizeof(*req));
803 req->id = client->id++;
804 req->type = SILC_SFTP_MKDIR;
805 req->status = callback;
806 req->context = context;
807 silc_list_add(client->requests, req);
809 attrs_buf = silc_sftp_attr_encode(attrs);
812 len = 4 + 4 + strlen(path) + attrs_buf->len;
814 silc_sftp_send_packet(client, req->type, len,
815 SILC_STR_UI_INT(req->id),
816 SILC_STR_UI_INT(strlen(path)),
817 SILC_STR_UI32_STRING(path),
818 SILC_STR_UI_XNSTRING(attrs_buf->data,
822 silc_buffer_free(attrs_buf);
825 void silc_sftp_rmdir(SilcSFTP sftp,
827 SilcSFTPStatusCallback callback,
830 SilcSFTPClient client = (SilcSFTPClient)sftp;
834 SILC_LOG_DEBUG(("Rmdir request"));
836 req = silc_calloc(1, sizeof(*req));
839 req->id = client->id++;
840 req->type = SILC_SFTP_RMDIR;
841 req->status = callback;
842 req->context = context;
843 silc_list_add(client->requests, req);
845 len = 4 + 4 + strlen(path);
847 silc_sftp_send_packet(client, req->type, len,
848 SILC_STR_UI_INT(req->id),
849 SILC_STR_UI_INT(strlen(path)),
850 SILC_STR_UI32_STRING(path),
854 void silc_sftp_opendir(SilcSFTP sftp,
856 SilcSFTPHandleCallback callback,
859 SilcSFTPClient client = (SilcSFTPClient)sftp;
863 SILC_LOG_DEBUG(("Opendir request"));
865 req = silc_calloc(1, sizeof(*req));
868 req->id = client->id++;
869 req->type = SILC_SFTP_OPENDIR;
870 req->handle = callback;
871 req->context = context;
872 silc_list_add(client->requests, req);
874 len = 4 + 4 + strlen(path);
876 silc_sftp_send_packet(client, req->type, len,
877 SILC_STR_UI_INT(req->id),
878 SILC_STR_UI_INT(strlen(path)),
879 SILC_STR_UI32_STRING(path),
883 void silc_sftp_readdir(SilcSFTP sftp,
884 SilcSFTPHandle handle,
885 SilcSFTPNameCallback callback,
888 SilcSFTPClient client = (SilcSFTPClient)sftp;
891 const unsigned char *hdata;
892 SilcUInt32 hdata_len;
894 SILC_LOG_DEBUG(("Readdir request"));
896 req = silc_calloc(1, sizeof(*req));
899 req->id = client->id++;
900 req->type = SILC_SFTP_READDIR;
901 req->name = callback;
902 req->context = context;
903 silc_list_add(client->requests, req);
905 silc_sftp_handle_get(handle, &hdata, &hdata_len);
906 len = 4 + 4 + hdata_len;
908 silc_sftp_send_packet(client, req->type, len,
909 SILC_STR_UI_INT(req->id),
910 SILC_STR_UI_INT(hdata_len),
911 SILC_STR_UI_XNSTRING(hdata, hdata_len),
915 void silc_sftp_stat(SilcSFTP sftp,
917 SilcSFTPAttrCallback callback,
920 SilcSFTPClient client = (SilcSFTPClient)sftp;
924 SILC_LOG_DEBUG(("Stat request"));
926 req = silc_calloc(1, sizeof(*req));
929 req->id = client->id++;
930 req->type = SILC_SFTP_STAT;
931 req->attr = callback;
932 req->context = context;
933 silc_list_add(client->requests, req);
935 len = 4 + 4 + strlen(path);
937 silc_sftp_send_packet(client, req->type, len,
938 SILC_STR_UI_INT(req->id),
939 SILC_STR_UI_INT(strlen(path)),
940 SILC_STR_UI32_STRING(path),
944 void silc_sftp_lstat(SilcSFTP sftp,
946 SilcSFTPAttrCallback callback,
949 SilcSFTPClient client = (SilcSFTPClient)sftp;
953 SILC_LOG_DEBUG(("Lstat request"));
955 req = silc_calloc(1, sizeof(*req));
958 req->id = client->id++;
959 req->type = SILC_SFTP_LSTAT;
960 req->attr = callback;
961 req->context = context;
962 silc_list_add(client->requests, req);
964 len = 4 + 4 + strlen(path);
966 silc_sftp_send_packet(client, req->type, len,
967 SILC_STR_UI_INT(req->id),
968 SILC_STR_UI_INT(strlen(path)),
969 SILC_STR_UI32_STRING(path),
973 void silc_sftp_fstat(SilcSFTP sftp,
974 SilcSFTPHandle handle,
975 SilcSFTPAttrCallback callback,
978 SilcSFTPClient client = (SilcSFTPClient)sftp;
981 const unsigned char *hdata;
982 SilcUInt32 hdata_len;
984 SILC_LOG_DEBUG(("Fstat request"));
986 req = silc_calloc(1, sizeof(*req));
989 req->id = client->id++;
990 req->type = SILC_SFTP_FSTAT;
991 req->attr = callback;
992 req->context = context;
993 silc_list_add(client->requests, req);
995 silc_sftp_handle_get(handle, &hdata, &hdata_len);
996 len = 4 + 4 + hdata_len;
998 silc_sftp_send_packet(client, req->type, len,
999 SILC_STR_UI_INT(req->id),
1000 SILC_STR_UI_INT(hdata_len),
1001 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1005 void silc_sftp_setstat(SilcSFTP sftp,
1007 SilcSFTPAttributes attrs,
1008 SilcSFTPStatusCallback callback,
1011 SilcSFTPClient client = (SilcSFTPClient)sftp;
1012 SilcSFTPRequest req;
1014 SilcBuffer attrs_buf;
1016 SILC_LOG_DEBUG(("Setstat request"));
1018 req = silc_calloc(1, sizeof(*req));
1021 req->id = client->id++;
1022 req->type = SILC_SFTP_SETSTAT;
1023 req->status = callback;
1024 req->context = context;
1025 silc_list_add(client->requests, req);
1027 attrs_buf = silc_sftp_attr_encode(attrs);
1030 len = 4 + 4 + strlen(path) + attrs_buf->len;
1032 silc_sftp_send_packet(client, req->type, len,
1033 SILC_STR_UI_INT(req->id),
1034 SILC_STR_UI_INT(strlen(path)),
1035 SILC_STR_UI32_STRING(path),
1036 SILC_STR_UI_XNSTRING(attrs_buf->data,
1040 silc_buffer_free(attrs_buf);
1043 void silc_sftp_fsetstat(SilcSFTP sftp,
1044 SilcSFTPHandle handle,
1045 SilcSFTPAttributes attrs,
1046 SilcSFTPStatusCallback callback,
1049 SilcSFTPClient client = (SilcSFTPClient)sftp;
1050 SilcSFTPRequest req;
1052 SilcBuffer attrs_buf;
1053 const unsigned char *hdata;
1054 SilcUInt32 hdata_len;
1056 SILC_LOG_DEBUG(("Fsetstat request"));
1058 req = silc_calloc(1, sizeof(*req));
1061 req->id = client->id++;
1062 req->type = SILC_SFTP_FSETSTAT;
1063 req->status = callback;
1064 req->context = context;
1065 silc_list_add(client->requests, req);
1067 silc_sftp_handle_get(handle, &hdata, &hdata_len);
1068 attrs_buf = silc_sftp_attr_encode(attrs);
1071 len = 4 + 4 + hdata_len + attrs_buf->len;
1073 silc_sftp_send_packet(client, req->type, len,
1074 SILC_STR_UI_INT(req->id),
1075 SILC_STR_UI_INT(hdata_len),
1076 SILC_STR_UI_XNSTRING(hdata, hdata_len),
1077 SILC_STR_UI_XNSTRING(attrs_buf->data,
1081 silc_buffer_free(attrs_buf);
1084 void silc_sftp_readlink(SilcSFTP sftp,
1086 SilcSFTPNameCallback callback,
1089 SilcSFTPClient client = (SilcSFTPClient)sftp;
1090 SilcSFTPRequest req;
1093 SILC_LOG_DEBUG(("Readlink request"));
1095 req = silc_calloc(1, sizeof(*req));
1098 req->id = client->id++;
1099 req->type = SILC_SFTP_READLINK;
1100 req->name = callback;
1101 req->context = context;
1102 silc_list_add(client->requests, req);
1104 len = 4 + 4 + strlen(path);
1106 silc_sftp_send_packet(client, req->type, len,
1107 SILC_STR_UI_INT(req->id),
1108 SILC_STR_UI_INT(strlen(path)),
1109 SILC_STR_UI32_STRING(path),
1113 void silc_sftp_symlink(SilcSFTP sftp,
1114 const char *linkpath,
1115 const char *targetpath,
1116 SilcSFTPStatusCallback callback,
1119 SilcSFTPClient client = (SilcSFTPClient)sftp;
1120 SilcSFTPRequest req;
1123 SILC_LOG_DEBUG(("Symlink request"));
1125 req = silc_calloc(1, sizeof(*req));
1128 req->id = client->id++;
1129 req->type = SILC_SFTP_SYMLINK;
1130 req->status = callback;
1131 req->context = context;
1132 silc_list_add(client->requests, req);
1134 len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
1136 silc_sftp_send_packet(client, req->type, len,
1137 SILC_STR_UI_INT(req->id),
1138 SILC_STR_UI_INT(strlen(linkpath)),
1139 SILC_STR_UI32_STRING(linkpath),
1140 SILC_STR_UI_INT(strlen(targetpath)),
1141 SILC_STR_UI32_STRING(targetpath),
1145 void silc_sftp_realpath(SilcSFTP sftp,
1147 SilcSFTPNameCallback callback,
1150 SilcSFTPClient client = (SilcSFTPClient)sftp;
1151 SilcSFTPRequest req;
1154 SILC_LOG_DEBUG(("Realpath request"));
1156 req = silc_calloc(1, sizeof(*req));
1159 req->id = client->id++;
1160 req->type = SILC_SFTP_REALPATH;
1161 req->name = callback;
1162 req->context = context;
1163 silc_list_add(client->requests, req);
1165 len = 4 + 4 + strlen(path);
1167 silc_sftp_send_packet(client, req->type, len,
1168 SILC_STR_UI_INT(req->id),
1169 SILC_STR_UI_INT(strlen(path)),
1170 SILC_STR_UI32_STRING(path),
1174 void silc_sftp_extended(SilcSFTP sftp,
1175 const char *request,
1176 const unsigned char *data,
1177 SilcUInt32 data_len,
1178 SilcSFTPExtendedCallback callback,
1181 SilcSFTPClient client = (SilcSFTPClient)sftp;
1182 SilcSFTPRequest req;
1185 SILC_LOG_DEBUG(("Extended request"));
1187 req = silc_calloc(1, sizeof(*req));
1190 req->id = client->id++;
1191 req->type = SILC_SFTP_WRITE;
1192 req->extended = callback;
1193 req->context = context;
1194 silc_list_add(client->requests, req);
1196 len = 4 + 4 + strlen(request) + data_len;
1198 silc_sftp_send_packet(client, req->type, len,
1199 SILC_STR_UI_INT(req->id),
1200 SILC_STR_UI_INT(strlen(request)),
1201 SILC_STR_UI32_STRING(request),
1202 SILC_STR_UI_XNSTRING(data, data_len),